Skip to content

Commit

Permalink
Ship two json schema files.. One that reference others, and a CMS one (
Browse files Browse the repository at this point in the history
…#13123)

* Ship two json schema files.. One that reference others, and a CMS one

* git ignore

* Build schema files sepearately
  • Loading branch information
bergmania authored Oct 5, 2022
1 parent 6dc8741 commit 46da0b0
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 142 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,8 @@ cypress.env.json
# Ignore auto-generated schema
/src/Umbraco.Cms.Targets/appsettings-schema.json
/src/Umbraco.Web.UI/appsettings-schema.json
/src/Umbraco.Web.UI/appsettings-schema.umbraco.json
/tests/Umbraco.Tests.Integration/appsettings-schema.json
/src/Umbraco.Cms.Targets/appsettings-schema.json
/src/Umbraco.Cms.Targets/appsettings-schema.umbraco.json

133 changes: 37 additions & 96 deletions src/JsonSchema/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,133 +3,74 @@

using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Deploy.Core.Configuration.DebugConfiguration;
using Umbraco.Deploy.Core.Configuration.DeployConfiguration;
using Umbraco.Deploy.Core.Configuration.DeployProjectConfiguration;
using Umbraco.Forms.Core.Configuration;
using SecuritySettings = Umbraco.Cms.Core.Configuration.Models.SecuritySettings;

namespace JsonSchema
{
internal class AppSettings
{
/// <summary>
/// Gets or sets the Umbraco
/// </summary>
public UmbracoDefinition? Umbraco { get; set; }

/// <summary>
/// Configuration of Umbraco CMS and packages
/// </summary>
internal class UmbracoDefinition
{
// ReSharper disable once InconsistentNaming
public CmsDefinition? CMS { get; set; }

public FormsDefinition? Forms { get; set; }
namespace JsonSchema;

public DeployDefinition? Deploy { get; set; }
internal class AppSettings
{
// ReSharper disable once InconsistentNaming
public CmsDefinition? CMS { get; set; }

/// <summary>
/// Configurations for the Umbraco CMS
/// </summary>
public class CmsDefinition
{
public ContentSettings? Content { get; set; }
public CoreDebugSettings? Debug { get; set; }
/// <summary>
/// Configurations for the Umbraco CMS
/// </summary>
public class CmsDefinition
{
public ContentSettings? Content { get; set; }
public CoreDebugSettings? Debug { get; set; }

public ExceptionFilterSettings? ExceptionFilter { get; set; }
public ExceptionFilterSettings? ExceptionFilter { get; set; }

public ModelsBuilderSettings? ModelsBuilder { get; set; }
public ModelsBuilderSettings? ModelsBuilder { get; set; }

public GlobalSettings? Global { get; set; }
public GlobalSettings? Global { get; set; }

public HealthChecksSettings? HealthChecks { get; set; }
public HealthChecksSettings? HealthChecks { get; set; }

public HostingSettings? Hosting { get; set; }
public HostingSettings? Hosting { get; set; }

public ImagingSettings? Imaging { get; set; }
public ImagingSettings? Imaging { get; set; }

public IndexCreatorSettings? Examine { get; set; }
public IndexCreatorSettings? Examine { get; set; }

public KeepAliveSettings? KeepAlive { get; set; }
public KeepAliveSettings? KeepAlive { get; set; }

public LoggingSettings? Logging { get; set; }
public LoggingSettings? Logging { get; set; }

public NuCacheSettings? NuCache { get; set; }

public RequestHandlerSettings? RequestHandler { get; set; }
public RequestHandlerSettings? RequestHandler { get; set; }

public RuntimeSettings? Runtime { get; set; }
public RuntimeSettings? Runtime { get; set; }

public SecuritySettings? Security { get; set; }
public SecuritySettings? Security { get; set; }

public TourSettings? Tours { get; set; }
public TourSettings? Tours { get; set; }

public TypeFinderSettings? TypeFinder { get; set; }
public TypeFinderSettings? TypeFinder { get; set; }

public WebRoutingSettings? WebRouting { get; set; }

public UmbracoPluginSettings? Plugins { get; set; }

public UnattendedSettings? Unattended { get; set; }

public RichTextEditorSettings? RichTextEditor { get; set; }

public RuntimeMinificationSettings? RuntimeMinification { get; set; }

public BasicAuthSettings? BasicAuth { get; set; }

public PackageMigrationSettings? PackageMigration { get; set; }

public LegacyPasswordMigrationSettings? LegacyPasswordMigration { get; set; }

public ContentDashboardSettings? ContentDashboard { get; set; }

public HelpPageSettings? HelpPage { get; set; }

public InstallDefaultDataSettings? DefaultDataCreation { get; set; }

public DataTypesSettings? DataTypes { get; set; }
}
public UmbracoPluginSettings? Plugins { get; set; }

/// <summary>
/// Configurations for the Umbraco Forms package to Umbraco CMS
/// </summary>
public class FormsDefinition
{
public FormDesignSettings? FormDesign { get; set; }
public UnattendedSettings? Unattended { get; set; }

public PackageOptionSettings? Options { get; set; }
public RichTextEditorSettings? RichTextEditor { get; set; }

public Umbraco.Forms.Core.Configuration.SecuritySettings? Security { get; set; }
public RuntimeMinificationSettings? RuntimeMinification { get; set; }

public FieldTypesDefinition? FieldTypes { get; set; }
public BasicAuthSettings? BasicAuth { get; set; }

/// <summary>
/// Configurations for the Umbraco Forms Field Types
/// </summary>
public class FieldTypesDefinition
{
public DatePickerSettings? DatePicker { get; set; }
public PackageMigrationSettings? PackageMigration { get; set; }

public Recaptcha2Settings? Recaptcha2 { get; set; }
public LegacyPasswordMigrationSettings? LegacyPasswordMigration { get; set; }

public Recaptcha3Settings? Recaptcha3 { get; set; }
}
}
public ContentDashboardSettings? ContentDashboard { get; set; }

/// <summary>
/// Configurations for the Umbraco Deploy package to Umbraco CMS
/// </summary>
public class DeployDefinition
{
public DeploySettings? Settings { get; set; }
public HelpPageSettings? HelpPage { get; set; }

public DeployProjectConfig? Project { get; set; }
public InstallDefaultDataSettings? DefaultDataCreation { get; set; }

public DebugSettings? Debug { get; set; }
}
}
public DataTypesSettings? DataTypes { get; set; }
}
}
18 changes: 18 additions & 0 deletions src/JsonSchema/JsonSchema.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,29 @@
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="NJsonSchema" Version="10.8.0" />
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<PackageReference Include="Umbraco.Deploy.Core" Version="10.1.0" />
<PackageReference Include="Umbraco.Forms.Core" Version="10.1.0" />
</ItemGroup>

<ItemGroup>
<None Remove="appsettings-schema.json" />
<EmbeddedResource Include="appsettings-schema.json" />
</ItemGroup>

<!-- Copy Forms XML docs-->
<PropertyGroup>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
</PropertyGroup>

<Target Name="CopyPackagesXml" BeforeTargets="Build">
<ItemGroup>
<PackageReferenceFiles Include="$(NugetPackageRoot)%(PackageReference.Identity)\%(PackageReference.Version)%(PackageReference.CopyToOutputDirectory)\lib\**\*.xml" />
</ItemGroup>
<Copy SourceFiles="@(PackageReferenceFiles)" DestinationFolder="$(OutDir)" />
</Target>
</Project>
7 changes: 5 additions & 2 deletions src/JsonSchema/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ namespace JsonSchema
{
internal class Options
{
[Option('o', "outputFile", Required = false, HelpText = "Set path of the output file.", Default = "appsettings-schema.json")]
public string OutputFile { get; set; } = null!;
[Option('m', "mainOutputFile", Required = false, HelpText = "Set path of the main output file.", Default = "../../../../Umbraco.Web.UI/appsettings-schema.json")]
public string MainOutputFile { get; set; } = null!;

[Option('f', "cmsOutputFile", Required = false, HelpText = "Set path of the cms output file.", Default = "../../../../Umbraco.Web.UI/appsettings-schema.umbraco.json")]
public string CmsOutputFile { get; set; } = null!;
}
}
20 changes: 14 additions & 6 deletions src/JsonSchema/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,23 @@ await Parser.Default.ParseArguments<Options>(args)
private static async Task Execute(Options options)
{
var generator = new UmbracoJsonSchemaGenerator();
var schema = await generator.Generate();

var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, options.OutputFile));
Console.WriteLine("Path to use {0}", path);
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
var cmsSchema = await generator.GenerateCmsFile();
await WriteSchemaToFile(cmsSchema, options.CmsOutputFile);

var schema = await generator.GenerateMainFile();
await WriteSchemaToFile(schema, options.MainOutputFile);
}

private static async Task WriteSchemaToFile(string schema, string filePath)
{
var mainPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, filePath));
Console.WriteLine("Path to use {0}", mainPath);
Directory.CreateDirectory(Path.GetDirectoryName(mainPath)!);
Console.WriteLine("Ensured directory exists");
await File.WriteAllTextAsync(path, schema);
await File.WriteAllTextAsync(mainPath, schema);

Console.WriteLine("File written at {0}", path);
Console.WriteLine("File written at {0}", mainPath);
}
}
}
95 changes: 60 additions & 35 deletions src/JsonSchema/UmbracoJsonSchemaGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,58 +1,83 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.

using Microsoft.Extensions.FileProviders;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NJsonSchema.Generation;
using Umbraco.Cms.Core.Configuration.Models;

namespace JsonSchema
namespace JsonSchema;

/// <summary>
/// Generator of the JsonSchema for AppSettings.json including A specific Umbraco version.
/// </summary>
public class UmbracoJsonSchemaGenerator
{
private static readonly HttpClient s_client = new();
private readonly JsonSchemaGenerator _innerGenerator;

/// <summary>
/// Generator of the JsonSchema for AppSettings.json including A specific Umbraco version.
/// Initializes a new instance of the <see cref="UmbracoJsonSchemaGenerator" /> class.
/// </summary>
public class UmbracoJsonSchemaGenerator
public UmbracoJsonSchemaGenerator()
=> _innerGenerator = new JsonSchemaGenerator(new UmbracoJsonSchemaGeneratorSettings());

/// <summary>
/// Generates a json representing the JsonSchema for AppSettings.json including A specific Umbraco version..
/// </summary>
public async Task<string> GenerateMainFile()
{
private static readonly HttpClient s_client = new ();
private readonly JsonSchemaGenerator _innerGenerator;

/// <summary>
/// Initializes a new instance of the <see cref="UmbracoJsonSchemaGenerator" /> class.
/// </summary>
public UmbracoJsonSchemaGenerator()
=> _innerGenerator = new JsonSchemaGenerator(new UmbracoJsonSchemaGeneratorSettings());

/// <summary>
/// Generates a json representing the JsonSchema for AppSettings.json including A specific Umbraco version..
/// </summary>
public async Task<string> Generate()
{
JObject umbracoSchema = GenerateUmbracoSchema();
JObject officialSchema = await GetOfficialAppSettingsSchema();
JObject officialSchema = await GetOfficialAppSettingsSchema();
JObject externalFilePoints = GenerateSchemaWithExternalDefinitions();

officialSchema.Merge(umbracoSchema);
officialSchema.Merge(externalFilePoints);

return officialSchema.ToString();
}
return officialSchema.ToString();
}

private async Task<JObject> GetOfficialAppSettingsSchema()
{
HttpResponseMessage response = await s_client.GetAsync("https://json.schemastore.org/appsettings.json")
.ConfigureAwait(false);

var result = await response.Content.ReadAsStringAsync();
/// <summary>
/// Generates the CMS file
/// </summary>
/// <returns></returns>
public Task<string> GenerateCmsFile()
{
JObject cmsSchema = GenerateUmbracoSchema();

return JsonConvert.DeserializeObject<JObject>(result)!;
}
return Task.FromResult(cmsSchema.ToString());
}

private JObject GenerateUmbracoSchema()
{
NJsonSchema.JsonSchema schema = _innerGenerator.Generate(typeof(AppSettings));

// TODO: when the "UmbracoPath" setter is removed from "GlobalSettings" (scheduled for V12), remove this line as well
schema.Definitions["UmbracoCmsCoreConfigurationModelsGlobalSettings"]?.Properties?.Remove(nameof(GlobalSettings.UmbracoPath));

return JsonConvert.DeserializeObject<JObject>(schema.ToJson())!;
private JObject GenerateSchemaWithExternalDefinitions()
{
var fileProvider = new EmbeddedFileProvider(GetType().Assembly);

IFileInfo schema = fileProvider.GetFileInfo("appsettings-schema.json");

using (Stream? stream = schema.CreateReadStream())
using (var reader = new StreamReader(stream))
{
return JsonConvert.DeserializeObject<JObject>(reader.ReadToEnd())!;
}
}

private async Task<JObject> GetOfficialAppSettingsSchema()
{
HttpResponseMessage response = await s_client.GetAsync("https://json.schemastore.org/appsettings.json")
.ConfigureAwait(false);

var result = await response.Content.ReadAsStringAsync();

return JsonConvert.DeserializeObject<JObject>(result)!;
}

private JObject GenerateUmbracoSchema()
{
NJsonSchema.JsonSchema schema = _innerGenerator.Generate(typeof(AppSettings));

// TODO: when the "UmbracoPath" setter is removed from "GlobalSettings" (scheduled for V12), remove this line as well
schema.Definitions["UmbracoCmsCoreConfigurationModelsGlobalSettings"]?.Properties?.Remove(nameof(GlobalSettings.UmbracoPath));return JsonConvert.DeserializeObject<JObject>(schema.ToJson())!;
}
}
Loading

0 comments on commit 46da0b0

Please sign in to comment.