mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.4 KiB
190 lines
6.4 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using GraphQL;
|
|
using GraphQL.Resolvers;
|
|
using GraphQL.Types;
|
|
using Squidex.Domain.Apps.Core;
|
|
using Squidex.Domain.Apps.Core.Schemas;
|
|
using Squidex.Domain.Apps.Entities.Apps;
|
|
using Squidex.Domain.Apps.Entities.Assets;
|
|
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types;
|
|
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils;
|
|
using Squidex.Domain.Apps.Entities.Schemas;
|
|
using Squidex.Infrastructure;
|
|
using GraphQLSchema = GraphQL.Types.Schema;
|
|
|
|
#pragma warning disable IDE0003
|
|
|
|
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
|
|
{
|
|
public sealed class GraphQLModel : IGraphModel
|
|
{
|
|
private readonly Dictionary<ISchemaEntity, ContentGraphType> contentTypes = new Dictionary<ISchemaEntity, ContentGraphType>();
|
|
private readonly Dictionary<ISchemaEntity, ContentDataGraphType> contentDataTypes = new Dictionary<ISchemaEntity, ContentDataGraphType>();
|
|
private readonly Dictionary<Guid, ISchemaEntity> schemasById;
|
|
private readonly PartitionResolver partitionResolver;
|
|
private readonly IAppEntity app;
|
|
private readonly IGraphType assetType;
|
|
private readonly IGraphType assetListType;
|
|
private readonly GraphQLSchema graphQLSchema;
|
|
|
|
public bool CanGenerateAssetSourceUrl { get; }
|
|
|
|
public GraphQLModel(IAppEntity app,
|
|
IEnumerable<ISchemaEntity> schemas,
|
|
int pageSizeContents,
|
|
int pageSizeAssets,
|
|
IGraphQLUrlGenerator urlGenerator)
|
|
{
|
|
this.app = app;
|
|
|
|
partitionResolver = app.PartitionResolver();
|
|
|
|
CanGenerateAssetSourceUrl = urlGenerator.CanGenerateAssetSourceUrl;
|
|
|
|
assetType = new AssetGraphType(this);
|
|
assetListType = new ListGraphType(new NonNullGraphType(assetType));
|
|
|
|
schemasById = schemas.Where(x => x.SchemaDef.IsPublished).ToDictionary(x => x.Id);
|
|
|
|
graphQLSchema = BuildSchema(this, pageSizeContents, pageSizeAssets);
|
|
graphQLSchema.RegisterValueConverter(JsonConverter.Instance);
|
|
|
|
InitializeContentTypes();
|
|
}
|
|
|
|
private static GraphQLSchema BuildSchema(GraphQLModel model, int pageSizeContents, int pageSizeAssets)
|
|
{
|
|
var schemas = model.schemasById.Values;
|
|
|
|
return new GraphQLSchema { Query = new AppQueriesGraphType(model, pageSizeContents, pageSizeAssets, schemas) };
|
|
}
|
|
|
|
private void InitializeContentTypes()
|
|
{
|
|
foreach (var kvp in contentDataTypes)
|
|
{
|
|
kvp.Value.Initialize(this, kvp.Key);
|
|
}
|
|
|
|
foreach (var kvp in contentTypes)
|
|
{
|
|
kvp.Value.Initialize(this, kvp.Key, contentDataTypes[kvp.Key]);
|
|
}
|
|
}
|
|
|
|
public IFieldResolver ResolveAssetUrl()
|
|
{
|
|
var resolver = new FuncFieldResolver<IAssetEntity, object>(c =>
|
|
{
|
|
var context = (GraphQLExecutionContext)c.UserContext;
|
|
|
|
return context.UrlGenerator.GenerateAssetUrl(app, c.Source);
|
|
});
|
|
|
|
return resolver;
|
|
}
|
|
|
|
public IFieldResolver ResolveAssetSourceUrl()
|
|
{
|
|
var resolver = new FuncFieldResolver<IAssetEntity, object>(c =>
|
|
{
|
|
var context = (GraphQLExecutionContext)c.UserContext;
|
|
|
|
return context.UrlGenerator.GenerateAssetSourceUrl(app, c.Source);
|
|
});
|
|
|
|
return resolver;
|
|
}
|
|
|
|
public IFieldResolver ResolveAssetThumbnailUrl()
|
|
{
|
|
var resolver = new FuncFieldResolver<IAssetEntity, object>(c =>
|
|
{
|
|
var context = (GraphQLExecutionContext)c.UserContext;
|
|
|
|
return context.UrlGenerator.GenerateAssetThumbnailUrl(app, c.Source);
|
|
});
|
|
|
|
return resolver;
|
|
}
|
|
|
|
public IFieldResolver ResolveContentUrl(ISchemaEntity schema)
|
|
{
|
|
var resolver = new FuncFieldResolver<IContentEntity, object>(c =>
|
|
{
|
|
var context = (GraphQLExecutionContext)c.UserContext;
|
|
|
|
return context.UrlGenerator.GenerateContentUrl(app, schema, c.Source);
|
|
});
|
|
|
|
return resolver;
|
|
}
|
|
|
|
public IFieldPartitioning ResolvePartition(Partitioning key)
|
|
{
|
|
return partitionResolver(key);
|
|
}
|
|
|
|
public (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field, string fieldName)
|
|
{
|
|
return field.Accept(new QueryGraphTypeVisitor(schema, GetContentType, this, assetListType, fieldName));
|
|
}
|
|
|
|
public IGraphType GetAssetType()
|
|
{
|
|
return assetType;
|
|
}
|
|
|
|
public IGraphType GetContentDataType(Guid schemaId)
|
|
{
|
|
var schema = schemasById.GetOrDefault(schemaId);
|
|
|
|
if (schema == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return contentDataTypes.GetOrAddNew(schema);
|
|
}
|
|
|
|
public IGraphType GetContentType(Guid schemaId)
|
|
{
|
|
var schema = schemasById.GetOrDefault(schemaId);
|
|
|
|
if (schema == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
contentDataTypes.GetOrAdd(schema, s => new ContentDataGraphType());
|
|
|
|
return contentTypes.GetOrAdd(schema, s => new ContentGraphType());
|
|
}
|
|
|
|
public async Task<(object Data, object[] Errors)> ExecuteAsync(GraphQLExecutionContext context, GraphQLQuery query)
|
|
{
|
|
Guard.NotNull(context, nameof(context));
|
|
|
|
var result = await new DocumentExecuter().ExecuteAsync(execution =>
|
|
{
|
|
context.Setup(execution);
|
|
|
|
execution.Schema = graphQLSchema;
|
|
execution.Inputs = query.Variables?.ToInputs();
|
|
execution.Query = query.Query;
|
|
}).ConfigureAwait(false);
|
|
|
|
return (result.Data, result.Errors?.Select(x => (object)new { x.Message, x.Locations }).ToArray());
|
|
}
|
|
}
|
|
}
|
|
|