Browse Source

Open API improvements (#667)

* Open API improvements
pull/668/head
Sebastian Stehle 5 years ago
committed by GitHub
parent
commit
ffa2ab140c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 64
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs
  2. 55
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs
  3. 42
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs
  4. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs
  5. 4
      backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs
  6. 51
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs
  7. 2
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs
  8. 22
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
  9. 1
      backend/src/Squidex/Config/Domain/CommandsServices.cs
  10. 46
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs
  11. 1
      backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs

64
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs

@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{ {
public static class JsonSchemaExtensions public static class JsonSchemaExtensions
{ {
public static JsonSchema BuildFlatJsonSchema(this Schema schema, SchemaResolver schemaResolver, bool withHidden = false) public static JsonSchema BuildFlatJsonSchema(this Schema schema, SchemaResolver schemaResolver)
{ {
Guard.NotNull(schemaResolver, nameof(schemaResolver)); Guard.NotNull(schemaResolver, nameof(schemaResolver));
@ -22,9 +22,9 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
var jsonSchema = SchemaBuilder.Object(); var jsonSchema = SchemaBuilder.Object();
foreach (var field in schema.Fields.ForApi(withHidden)) foreach (var field in schema.Fields.ForApi())
{ {
var property = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden); var property = JsonTypeVisitor.BuildProperty(field, null, false);
if (property != null) if (property != null)
{ {
@ -37,42 +37,62 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return jsonSchema; return jsonSchema;
} }
public static JsonSchema BuildJsonSchema(this Schema schema, PartitionResolver partitionResolver, SchemaResolver schemaResolver, bool withHidden = false) public static JsonSchema BuildDynamicJsonSchema(this Schema schema, SchemaResolver schemaResolver, bool withHidden = false)
{ {
Guard.NotNull(schemaResolver, nameof(schemaResolver)); Guard.NotNull(schemaResolver, nameof(schemaResolver));
Guard.NotNull(partitionResolver, nameof(partitionResolver));
var schemaName = schema.TypeName(); var jsonSchema = SchemaBuilder.Object();
foreach (var field in schema.Fields.ForApi(withHidden))
{
var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden);
if (propertyItem != null)
{
var property =
SchemaBuilder.ObjectProperty(propertyItem)
.SetDescription(field)
.SetRequired(field.RawProperties.IsRequired);
jsonSchema.Properties.Add(field.Name, property);
}
}
return jsonSchema;
}
public static JsonSchema BuildJsonSchema(this Schema schema, PartitionResolver partitionResolver, bool withHidden = false)
{
Guard.NotNull(partitionResolver, nameof(partitionResolver));
var jsonSchema = SchemaBuilder.Object(); var jsonSchema = SchemaBuilder.Object();
foreach (var field in schema.Fields.ForApi(withHidden)) foreach (var field in schema.Fields.ForApi(withHidden))
{ {
var partitionObject = SchemaBuilder.Object(); var propertyObject = SchemaBuilder.Object();
var partitioning = partitionResolver(field.Partitioning); var partitioning = partitionResolver(field.Partitioning);
foreach (var partitionKey in partitioning.AllKeys) foreach (var partitionKey in partitioning.AllKeys)
{ {
var partitionItemProperty = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden); var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden);
if (partitionItemProperty != null) if (propertyItem != null)
{ {
var isOptional = partitioning.IsOptional(partitionKey); var isOptional = partitioning.IsOptional(partitionKey);
var name = partitioning.GetName(partitionKey); var name = partitioning.GetName(partitionKey);
partitionItemProperty.Description = name; propertyItem.SetDescription(name);
partitionItemProperty.SetRequired(field.RawProperties.IsRequired && !isOptional); propertyItem.SetRequired(field.RawProperties.IsRequired && !isOptional);
partitionObject.Properties.Add(partitionKey, partitionItemProperty); propertyObject.Properties.Add(partitionKey, propertyItem);
} }
} }
if (partitionObject.Properties.Count > 0) if (propertyObject.Properties.Count > 0)
{ {
var propertyReference = schemaResolver($"{schemaName}{field.Name.ToPascalCase()}PropertyDto", () => partitionObject); jsonSchema.Properties.Add(field.Name, CreateProperty(field, propertyObject));
jsonSchema.Properties.Add(field.Name, CreateProperty(field, propertyReference));
} }
} }
@ -81,8 +101,16 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
public static JsonSchemaProperty CreateProperty(IField field, JsonSchema reference) public static JsonSchemaProperty CreateProperty(IField field, JsonSchema reference)
{ {
var jsonProperty = SchemaBuilder.ObjectProperty(reference); var jsonProperty =
SchemaBuilder.ReferenceProperty(reference)
.SetDescription(field)
.SetRequired(field.RawProperties.IsRequired);
return jsonProperty;
}
private static JsonSchemaProperty SetDescription(this JsonSchemaProperty jsonProperty, IField field)
{
if (!string.IsNullOrWhiteSpace(field.RawProperties.Hints)) if (!string.IsNullOrWhiteSpace(field.RawProperties.Hints))
{ {
jsonProperty.Description = $"{field.Name} ({field.RawProperties.Hints})"; jsonProperty.Description = $"{field.Name} ({field.RawProperties.Hints})";
@ -92,8 +120,6 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
jsonProperty.Description = field.Name; jsonProperty.Description = field.Name;
} }
jsonProperty.SetRequired(field.RawProperties.IsRequired);
return jsonProperty; return jsonProperty;
} }
} }

55
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs

@ -21,11 +21,11 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
public readonly struct Args public readonly struct Args
{ {
public readonly SchemaResolver SchemaResolver; public readonly SchemaResolver? SchemaResolver;
public readonly bool WithHiddenFields; public readonly bool WithHiddenFields;
public Args(SchemaResolver schemaResolver, bool withHiddenFields) public Args(SchemaResolver? schemaResolver, bool withHiddenFields)
{ {
SchemaResolver = schemaResolver; SchemaResolver = schemaResolver;
@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{ {
} }
public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver schemaResolver, bool withHiddenFields) public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver? schemaResolver, bool withHiddenFields)
{ {
var args = new Args(schemaResolver, withHiddenFields); var args = new Args(schemaResolver, withHiddenFields);
@ -81,30 +81,41 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
public JsonSchemaProperty? Visit(IField<GeolocationFieldProperties> field, Args args) public JsonSchemaProperty? Visit(IField<GeolocationFieldProperties> field, Args args)
{ {
var reference = args.SchemaResolver("GeolocationDto", () => if (args.SchemaResolver != null)
{ {
var geolocationSchema = SchemaBuilder.Object(); var reference = args.SchemaResolver("GeolocationDto", () =>
{
var geolocationSchema = SchemaBuilder.Object();
geolocationSchema.Format = GeoJson.Format; geolocationSchema.Format = GeoJson.Format;
geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty
{ {
Type = JsonObjectType.Number, Type = JsonObjectType.Number,
Maximum = 90, Maximum = 90,
Minimum = -90 Minimum = -90
}.SetRequired(true)); }.SetRequired(false));
geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty
{ {
Type = JsonObjectType.Number, Type = JsonObjectType.Number,
Maximum = 180, Maximum = 180,
Minimum = -180 Minimum = -180
}.SetRequired(true)); }.SetRequired(false));
return geolocationSchema;
});
return geolocationSchema; return SchemaBuilder.ObjectProperty(reference);
}); }
else
{
var property = SchemaBuilder.ObjectProperty();
return SchemaBuilder.ObjectProperty(reference); property.Format = GeoJson.Format;
return property;
}
} }
public JsonSchemaProperty? Visit(IField<JsonFieldProperties> field, Args args) public JsonSchemaProperty? Visit(IField<JsonFieldProperties> field, Args args)
@ -166,4 +177,4 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return null; return null;
} }
} }
} }

42
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs

@ -23,48 +23,68 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
public static JsonSchemaProperty ArrayProperty(JsonSchema item, string? description = null, bool isRequired = false) public static JsonSchemaProperty ArrayProperty(JsonSchema item, string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Array, Item = item }, description, isRequired); return new JsonSchemaProperty { Type = JsonObjectType.Array, Item = item }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty BooleanProperty(string? description = null, bool isRequired = false) public static JsonSchemaProperty BooleanProperty(string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Boolean }, description, isRequired); return new JsonSchemaProperty { Type = JsonObjectType.Boolean }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty DateTimeProperty(string? description = null, bool isRequired = false) public static JsonSchemaProperty DateTimeProperty(string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String, Format = JsonFormatStrings.DateTime }, description, isRequired); return new JsonSchemaProperty { Type = JsonObjectType.String, Format = JsonFormatStrings.DateTime }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty NumberProperty(string? description = null, bool isRequired = false) public static JsonSchemaProperty NumberProperty(string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Number }, description, isRequired); return new JsonSchemaProperty { Type = JsonObjectType.Number }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty StringProperty(string? description = null, bool isRequired = false) public static JsonSchemaProperty StringProperty(string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String }, description, isRequired); return new JsonSchemaProperty { Type = JsonObjectType.String }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty ObjectProperty(JsonSchema reference, string? description = null, bool isRequired = false) public static JsonSchemaProperty ReferenceProperty(JsonSchema reference, string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty { Reference = reference }, description, isRequired); return new JsonSchemaProperty { Reference = reference }
.SetDescription(description)
.SetRequired(isRequired);
}
public static JsonSchemaProperty ObjectProperty(JsonSchema? value = null, string? description = null, bool isRequired = false)
{
return new JsonSchemaProperty { Type = JsonObjectType.Object, AdditionalPropertiesSchema = value }
.SetDescription(description)
.SetRequired(isRequired);
} }
public static JsonSchemaProperty JsonProperty(string? description = null, bool isRequired = false) public static JsonSchemaProperty JsonProperty(string? description = null, bool isRequired = false)
{ {
return Enrich(new JsonSchemaProperty(), description, isRequired); return new JsonSchemaProperty()
.SetDescription(description)
.SetRequired(isRequired);
} }
private static JsonSchemaProperty Enrich(JsonSchemaProperty property, string? description = null, bool isRequired = false) public static T SetDescription<T>(this T property, string? description = null) where T : JsonSchemaProperty
{ {
property.Description = description; property.Description = description;
property.SetRequired(isRequired);
return property; return property;
} }
public static JsonSchemaProperty SetRequired(this JsonSchemaProperty property, bool isRequired) public static T SetRequired<T>(this T property, bool isRequired) where T : JsonSchemaProperty
{ {
property.IsRequired = isRequired; property.IsRequired = isRequired;
property.IsNullableRaw = !isRequired; property.IsNullableRaw = !isRequired;

2
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs

@ -235,7 +235,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
private static JsonSchema BuildJsonSchema(Schema schema, IAppEntity app, bool withHiddenFields) private static JsonSchema BuildJsonSchema(Schema schema, IAppEntity app, bool withHiddenFields)
{ {
var dataSchema = schema.BuildJsonSchema(app.PartitionResolver(), (n, action) => action(), withHiddenFields); var dataSchema = schema.BuildJsonSchema(app.PartitionResolver(), withHiddenFields);
return ContentJsonSchemaBuilder.BuildSchema(schema.DisplayName(), dataSchema); return ContentJsonSchemaBuilder.BuildSchema(schema.DisplayName(), dataSchema);
} }

4
backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs

@ -38,8 +38,8 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
if (dataSchema != null) if (dataSchema != null)
{ {
jsonSchema.Properties["data"] = SchemaBuilder.ObjectProperty(dataSchema, $"The data of the {name}.", true); jsonSchema.Properties["data"] = SchemaBuilder.ReferenceProperty(dataSchema, $"The data of the {name}.", true);
jsonSchema.Properties["dataDraft"] = SchemaBuilder.ObjectProperty(dataSchema, $"The draft data of the {name}."); jsonSchema.Properties["dataDraft"] = SchemaBuilder.ReferenceProperty(dataSchema, $"The draft data of the {name}.");
} }
return jsonSchema; return jsonSchema;

51
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs

@ -11,7 +11,6 @@ using NJsonSchema;
using NSwag; using NSwag;
using NSwag.Generation; using NSwag.Generation;
using Squidex.Areas.Api.Controllers.Contents.Models; using Squidex.Areas.Api.Controllers.Contents.Models;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Core.GenerateJsonSchema;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
@ -21,7 +20,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
{ {
internal sealed class Builder internal sealed class Builder
{ {
private readonly PartitionResolver partitionResolver; private const string ResultTotal = "total";
private const string ResultItems = "items";
public string AppName { get; } public string AppName { get; }
@ -34,8 +34,6 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
OpenApiSchemaResolver schemaResolver, OpenApiSchemaResolver schemaResolver,
OpenApiSchemaGenerator schemaGenerator) OpenApiSchemaGenerator schemaGenerator)
{ {
this.partitionResolver = app.PartitionResolver();
Document = document; Document = document;
AppName = app.Name; AppName = app.Name;
@ -50,16 +48,22 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return JsonSchema.CreateAnySchema(); return JsonSchema.CreateAnySchema();
}); });
var contentSchema = ResolveSchema($"ContentDto", () => var contentSchema = ResolveSchema("ContentDto", () =>
{ {
return ContentJsonSchemaBuilder.BuildSchema("Shared", dataSchema, true); return ContentJsonSchemaBuilder.BuildSchema("Shared", dataSchema, true);
}); });
var contentsSchema = ResolveSchema("ContentResultDto", () =>
{
return BuildResult(contentSchema);
});
var path = $"/content/{AppName}"; var path = $"/content/{AppName}";
var builder = new OperationsBuilder var builder = new OperationsBuilder
{ {
ContentSchema = contentSchema, ContentSchema = contentSchema,
ContentsSchema = contentsSchema,
DataSchema = dataSchema, DataSchema = dataSchema,
Path = path, Path = path,
Parent = this, Parent = this,
@ -83,19 +87,27 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
var dataSchema = ResolveSchema($"{typeName}DataDto", () => var dataSchema = ResolveSchema($"{typeName}DataDto", () =>
{ {
return schema.BuildJsonSchema(partitionResolver, ResolveSchema); return schema.BuildDynamicJsonSchema(ResolveSchema);
}); });
var dataFlatSchema = ResolveSchema($"{typeName}FlatDataDto", () => var contentSchema = ResolveSchema($"{typeName}ContentDto", () =>
{ {
return schema.BuildFlatJsonSchema(ResolveSchema); var contentDataSchema = dataSchema;
if (flat)
{
contentDataSchema = ResolveSchema($"{typeName}FlatDataDto", () =>
{
return schema.BuildFlatJsonSchema(ResolveSchema);
});
}
return ContentJsonSchemaBuilder.BuildSchema(displayName, contentDataSchema, true);
}); });
var contentSchema = ResolveSchema($"{typeName}ContentDto", () => var contentsSchema = ResolveSchema($"{typeName}ContentResultDto", () =>
{ {
var data = flat ? dataFlatSchema : dataSchema; return BuildResult(contentSchema);
return ContentJsonSchemaBuilder.BuildSchema(displayName, data, true);
}); });
var path = $"/content/{AppName}/{schema.Name}"; var path = $"/content/{AppName}/{schema.Name}";
@ -103,6 +115,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
var builder = new OperationsBuilder var builder = new OperationsBuilder
{ {
ContentSchema = contentSchema, ContentSchema = contentSchema,
ContentsSchema = contentsSchema,
DataSchema = dataSchema, DataSchema = dataSchema,
Path = path, Path = path,
Parent = this, Parent = this,
@ -127,5 +140,19 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
Reference = Document.Definitions.GetOrAdd(name, x => factory()) Reference = Document.Definitions.GetOrAdd(name, x => factory())
}; };
} }
private static JsonSchema BuildResult(JsonSchema contentSchema)
{
return new JsonSchema
{
AllowAdditionalProperties = false,
Properties =
{
[ResultTotal] = SchemaBuilder.NumberProperty("The total number of content items.", true),
[ResultItems] = SchemaBuilder.ArrayProperty(contentSchema, "The content items.", true)
},
Type = JsonObjectType.Object
};
}
} }
} }

2
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs

@ -27,6 +27,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
public JsonSchema ContentSchema { get; init; } public JsonSchema ContentSchema { get; init; }
public JsonSchema ContentsSchema { get; init; }
public JsonSchema DataSchema { get; init; } public JsonSchema DataSchema { get; init; }
public string FormatText(string text) public string FormatText(string text)

22
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs

@ -13,7 +13,6 @@ using NJsonSchema;
using NSwag; using NSwag;
using NSwag.Generation; using NSwag.Generation;
using NSwag.Generation.Processors.Contexts; using NSwag.Generation.Processors.Contexts;
using Squidex.Domain.Apps.Core.GenerateJsonSchema;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Hosting; using Squidex.Hosting;
@ -82,28 +81,24 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private static void GenerateSharedOperations(OperationsBuilder builder) private static void GenerateSharedOperations(OperationsBuilder builder)
{ {
var contentsSchema = BuildResults(builder);
builder.AddOperation(OpenApiOperationMethod.Get, "/") builder.AddOperation(OpenApiOperationMethod.Get, "/")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(Permissions.AppContentsReadOwn)
.Operation("Query") .Operation("Query")
.OperationSummary("Query contents across all schemas.") .OperationSummary("Query contents across all schemas.")
.HasQuery("ids", JsonObjectType.String, "Comma-separated list of content IDs.") .HasQuery("ids", JsonObjectType.String, "Comma-separated list of content IDs.")
.Responds(200, "Content items retrieved.", contentsSchema) .Responds(200, "Content items retrieved.", builder.ContentsSchema)
.Responds(400, "Query not valid."); .Responds(400, "Query not valid.");
} }
private static void GenerateSchemaOperations(OperationsBuilder builder) private static void GenerateSchemaOperations(OperationsBuilder builder)
{ {
var contentsSchema = BuildResults(builder);
builder.AddOperation(OpenApiOperationMethod.Get, "/") builder.AddOperation(OpenApiOperationMethod.Get, "/")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(Permissions.AppContentsReadOwn)
.Operation("Query") .Operation("Query")
.OperationSummary("Query schema contents items.") .OperationSummary("Query schema contents items.")
.Describe(Properties.Resources.OpenApiSchemaQuery) .Describe(Properties.Resources.OpenApiSchemaQuery)
.HasQueryOptions(true) .HasQueryOptions(true)
.Responds(200, "Content items retrieved.", contentsSchema) .Responds(200, "Content items retrieved.", builder.ContentsSchema)
.Responds(400, "Query not valid."); .Responds(400, "Query not valid.");
builder.AddOperation(OpenApiOperationMethod.Get, "/{id}") builder.AddOperation(OpenApiOperationMethod.Get, "/{id}")
@ -192,19 +187,6 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(204, "Content item deleted"); .Responds(204, "Content item deleted");
} }
private static JsonSchema BuildResults(OperationsBuilder builder)
{
return new JsonSchema
{
Properties =
{
["total"] = SchemaBuilder.NumberProperty("The total number of content items.", true),
["items"] = SchemaBuilder.ArrayProperty(builder.ContentSchema, "The content items.", true)
},
Type = JsonObjectType.Object
};
}
private OpenApiDocument CreateApiDocument(HttpContext context, IAppEntity app) private OpenApiDocument CreateApiDocument(HttpContext context, IAppEntity app)
{ {
var appName = app.Name; var appName = app.Name;

1
backend/src/Squidex/Config/Domain/CommandsServices.cs

@ -23,7 +23,6 @@ using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Domain.Apps.Entities.Schemas.DomainObject; using Squidex.Domain.Apps.Entities.Schemas.DomainObject;
using Squidex.Domain.Apps.Entities.Schemas.Indexes; using Squidex.Domain.Apps.Entities.Schemas.Indexes;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Web.CommandMiddlewares; using Squidex.Web.CommandMiddlewares;
namespace Squidex.Config.Domain namespace Squidex.Config.Domain

46
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NJsonSchema; using NJsonSchema;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Core.GenerateJsonSchema;
@ -25,38 +26,19 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema
{ {
var languagesConfig = LanguagesConfig.English.Set(Language.DE); var languagesConfig = LanguagesConfig.English.Set(Language.DE);
var schemaResolver = new SchemaResolver((name, action) => var jsonSchema = schema.BuildJsonSchema(languagesConfig.ToResolver());
{
return action();
});
var jsonSchema = schema.BuildJsonSchema(languagesConfig.ToResolver(), schemaResolver); CheckFields(jsonSchema);
var jsonProperties = AllPropertyNames(jsonSchema); }
void CheckField(IField field) [Fact]
{ public void Should_build_json_schema_with_resolver()
if (!field.IsForApi()) {
{ var schemaResolver = new SchemaResolver((name, action) => action());
Assert.DoesNotContain(field.Name, jsonProperties);
}
else
{
Assert.Contains(field.Name, jsonProperties);
}
if (field is IArrayField array) var jsonSchema = schema.BuildDynamicJsonSchema(schemaResolver);
{
foreach (var nested in array.Fields)
{
CheckField(nested);
}
}
}
foreach (var field in schema.Fields) CheckFields(jsonSchema);
{
CheckField(field);
}
} }
[Fact] [Fact]
@ -70,6 +52,12 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema
}); });
var jsonSchema = schema.BuildFlatJsonSchema(schemaResolver); var jsonSchema = schema.BuildFlatJsonSchema(schemaResolver);
CheckFields(jsonSchema);
}
private void CheckFields(JsonSchema jsonSchema)
{
var jsonProperties = AllPropertyNames(jsonSchema); var jsonProperties = AllPropertyNames(jsonSchema);
void CheckField(IField field) void CheckField(IField field)
@ -118,6 +106,8 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema
AddProperties(current.Item); AddProperties(current.Item);
AddProperties(current.Reference); AddProperties(current.Reference);
AddProperties(current.AdditionalItemsSchema);
AddProperties(current.AdditionalPropertiesSchema);
} }
} }

1
backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs

@ -7,7 +7,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;

Loading…
Cancel
Save