mirror of https://github.com/Squidex/squidex.git
11 changed files with 372 additions and 366 deletions
@ -0,0 +1,57 @@ |
|||
// ==========================================================================
|
|||
// ContentSchemaBuilder.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using NJsonSchema; |
|||
using Squidex.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Read.Contents.Builders |
|||
{ |
|||
public sealed class ContentSchemaBuilder |
|||
{ |
|||
public JsonSchema4 CreateContentSchema(Schema schema, JsonSchema4 dataSchema) |
|||
{ |
|||
Guard.NotNull(schema, nameof(schema)); |
|||
Guard.NotNull(dataSchema, nameof(dataSchema)); |
|||
|
|||
var schemaName = schema.Properties.Label.WithFallback(schema.Name); |
|||
|
|||
var contentSchema = new JsonSchema4 |
|||
{ |
|||
Properties = |
|||
{ |
|||
["id"] = CreateProperty($"The id of the {schemaName} content."), |
|||
["data"] = CreateProperty($"The data of the {schemaName}.", dataSchema), |
|||
["version"] = CreateProperty($"The version of the {schemaName}.", JsonObjectType.Number), |
|||
["created"] = CreateProperty($"The date and time when the {schemaName} content has been created.", "date-time"), |
|||
["createdBy"] = CreateProperty($"The user that has created the {schemaName} content."), |
|||
["lastModified"] = CreateProperty($"The date and time when the {schemaName} content has been modified last.", "date-time"), |
|||
["lastModifiedBy"] = CreateProperty($"The user that has updated the {schemaName} content last.") |
|||
}, |
|||
Type = JsonObjectType.Object |
|||
}; |
|||
|
|||
return contentSchema; |
|||
} |
|||
|
|||
private static JsonProperty CreateProperty(string description, JsonSchema4 dataSchema) |
|||
{ |
|||
return new JsonProperty { Description = description, IsRequired = true, Type = JsonObjectType.Object, SchemaReference = dataSchema }; |
|||
} |
|||
|
|||
private static JsonProperty CreateProperty(string description, JsonObjectType type) |
|||
{ |
|||
return new JsonProperty { Description = description, IsRequired = true, Type = type }; |
|||
} |
|||
|
|||
private static JsonProperty CreateProperty(string description, string format = null) |
|||
{ |
|||
return new JsonProperty { Description = description, Format = format, IsRequired = true, Type = JsonObjectType.String }; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,227 @@ |
|||
// ==========================================================================
|
|||
// SchemaSwaggerGenerator.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using NJsonSchema; |
|||
using NSwag; |
|||
using Squidex.Core; |
|||
using Squidex.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Pipeline.Swagger; |
|||
using Squidex.Read.Contents.Builders; |
|||
|
|||
// ReSharper disable InvertIf
|
|||
|
|||
namespace Squidex.Controllers.ContentApi.Generator |
|||
{ |
|||
public sealed class SchemaSwaggerGenerator |
|||
{ |
|||
private static readonly string schemaQueryDescription; |
|||
private static readonly string schemaBodyDescription; |
|||
private readonly ContentSchemaBuilder schemaBuilder = new ContentSchemaBuilder(); |
|||
private readonly SwaggerDocument document; |
|||
private readonly JsonSchema4 contentSchema; |
|||
private readonly JsonSchema4 dataSchema; |
|||
private readonly string schemaPath; |
|||
private readonly string schemaName; |
|||
private readonly string schemaKey; |
|||
private readonly string appPath; |
|||
|
|||
static SchemaSwaggerGenerator() |
|||
{ |
|||
schemaBodyDescription = SwaggerHelper.LoadDocs("schemabody"); |
|||
schemaQueryDescription = SwaggerHelper.LoadDocs("schemaquery"); |
|||
} |
|||
|
|||
public SchemaSwaggerGenerator(SwaggerDocument document, string path, Schema schema, Func<string, JsonSchema4, JsonSchema4> schemaResolver, PartitionResolver partitionResolver) |
|||
{ |
|||
this.document = document; |
|||
|
|||
appPath = path; |
|||
|
|||
schemaPath = schema.Name; |
|||
schemaName = schema.Properties.Label.WithFallback(schema.Name); |
|||
schemaKey = schema.Name.ToPascalCase(); |
|||
|
|||
dataSchema = schemaResolver($"{schemaKey}Dto", schema.BuildJsonSchema(partitionResolver, schemaResolver)); |
|||
|
|||
contentSchema = schemaResolver($"{schemaKey}ContentDto", schemaBuilder.CreateContentSchema(schema, dataSchema)); |
|||
} |
|||
|
|||
public void GenerateSchemaOperations() |
|||
{ |
|||
document.Tags.Add( |
|||
new SwaggerTag |
|||
{ |
|||
Name = schemaName, Description = $"API to managed {schemaName} contents." |
|||
}); |
|||
|
|||
var schemaOperations = new List<SwaggerOperations> |
|||
{ |
|||
GenerateSchemaQueryOperation(), |
|||
GenerateSchemaCreateOperation(), |
|||
GenerateSchemaGetOperation(), |
|||
GenerateSchemaUpdateOperation(), |
|||
GenerateSchemaPatchOperation(), |
|||
GenerateSchemaPublishOperation(), |
|||
GenerateSchemaUnpublishOperation(), |
|||
GenerateSchemaDeleteOperation() |
|||
}; |
|||
|
|||
foreach (var operation in schemaOperations.SelectMany(x => x.Values).Distinct()) |
|||
{ |
|||
operation.Tags = new List<string> { schemaName }; |
|||
} |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaQueryOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Get, null, $"{appPath}/{schemaPath}", operation => |
|||
{ |
|||
operation.OperationId = $"Query{schemaKey}Contents"; |
|||
operation.Summary = $"Queries {schemaName} contents."; |
|||
|
|||
operation.Description = schemaQueryDescription; |
|||
|
|||
operation.AddQueryParameter("$top", JsonObjectType.Number, "Optional number of contents to take."); |
|||
operation.AddQueryParameter("$skip", JsonObjectType.Number, "Optional number of contents to skip."); |
|||
operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter."); |
|||
operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search."); |
|||
operation.AddQueryParameter("orderby", JsonObjectType.String, "Optional OData order definition."); |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema)); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaGetOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Get, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => |
|||
{ |
|||
operation.OperationId = $"Get{schemaKey}Content"; |
|||
operation.Summary = $"Get a {schemaName} content."; |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content found.", contentSchema); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaCreateOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Post, null, $"{appPath}/{schemaPath}", operation => |
|||
{ |
|||
operation.OperationId = $"Create{schemaKey}Content"; |
|||
operation.Summary = $"Create a {schemaName} content."; |
|||
|
|||
operation.AddBodyParameter("data", dataSchema, schemaBodyDescription); |
|||
operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content."); |
|||
|
|||
operation.AddResponse("201", $"{schemaName} created.", contentSchema); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaUpdateOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => |
|||
{ |
|||
operation.OperationId = $"Update{schemaKey}Content"; |
|||
operation.Summary = $"Update a {schemaName} content."; |
|||
|
|||
operation.AddBodyParameter("data", dataSchema, schemaBodyDescription); |
|||
|
|||
operation.AddResponse("204", $"{schemaName} element updated."); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaPatchOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Patch, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => |
|||
{ |
|||
operation.OperationId = $"Path{schemaKey}Content"; |
|||
operation.Summary = $"Patchs a {schemaName} content."; |
|||
|
|||
operation.AddBodyParameter("data", contentSchema, schemaBodyDescription); |
|||
|
|||
operation.AddResponse("204", $"{schemaName} element updated."); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaPublishOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/publish", operation => |
|||
{ |
|||
operation.OperationId = $"Publish{schemaKey}Content"; |
|||
operation.Summary = $"Publish a {schemaName} content."; |
|||
|
|||
operation.AddResponse("204", $"{schemaName} element published."); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaUnpublishOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/unpublish", operation => |
|||
{ |
|||
operation.OperationId = $"Unpublish{schemaKey}Content"; |
|||
operation.Summary = $"Unpublish a {schemaName} content."; |
|||
|
|||
operation.AddResponse("204", $"{schemaName} element unpublished."); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations GenerateSchemaDeleteOperation() |
|||
{ |
|||
return AddOperation(SwaggerOperationMethod.Delete, schemaName, $"{appPath}/{schemaPath}/{{id}}/", operation => |
|||
{ |
|||
operation.OperationId = $"Delete{schemaKey}Content"; |
|||
operation.Summary = $"Delete a {schemaName} content."; |
|||
|
|||
operation.AddResponse("204", $"{schemaName} content deleted."); |
|||
}); |
|||
} |
|||
|
|||
private SwaggerOperations AddOperation(SwaggerOperationMethod method, string entityName, string path, Action<SwaggerOperation> updater) |
|||
{ |
|||
var operations = document.Paths.GetOrAdd(path, k => new SwaggerOperations()); |
|||
var operation = new SwaggerOperation(); |
|||
|
|||
updater(operation); |
|||
|
|||
operations[method] = operation; |
|||
|
|||
if (entityName != null) |
|||
{ |
|||
operation.AddPathParameter("id", JsonObjectType.String, $"The id of the {entityName} content (GUID)."); |
|||
|
|||
operation.AddResponse("404", $"App, schema or {entityName} content not found."); |
|||
} |
|||
|
|||
return operations; |
|||
} |
|||
|
|||
private static JsonSchema4 CreateContentsSchema(string schemaName, JsonSchema4 contentSchema) |
|||
{ |
|||
var schema = new JsonSchema4 |
|||
{ |
|||
Properties = |
|||
{ |
|||
["total"] = new JsonProperty |
|||
{ |
|||
Type = JsonObjectType.Number, IsRequired = true, Description = $"The total number of {schemaName} contents." |
|||
}, |
|||
["items"] = new JsonProperty |
|||
{ |
|||
Type = JsonObjectType.Array, IsRequired = true, Item = contentSchema, Description = $"The {schemaName} contents." |
|||
} |
|||
}, |
|||
Type = JsonObjectType.Object |
|||
}; |
|||
|
|||
return schema; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue