@team-supercharge/oasg 18.1.0 → 18.2.1-temp-feat-spring-boot-4.956dbdab
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -15
- package/bin/oasg +5 -6
- package/config.schema.yml +4 -0
- package/package.json +4 -2
- package/targets/dotnet-webapi-system-text-json/README.md +7 -0
- package/targets/dotnet-webapi-system-text-json/generate.sh +1 -1
- package/targets/dotnet-webapi-system-text-json/generator-config.json +1 -1
- package/targets/dotnet-webapi-system-text-json/templates/Project.csproj.mustache +5 -4
- package/targets/dotnet-webapi-system-text-json/templates/enumClass.mustache +24 -0
- package/targets/dotnet-webapi-system-text-json/templates/minimalEndpoints.mustache +3 -1
- package/targets/dotnet-webapi-system-text-json/templates/model.mustache +0 -1
- package/targets/dotnet-webapi-system-text-json/templates/serviceCollectionExtensions.mustache +70 -46
- package/targets/dotnet-webapi-system-text-json/templates/typeConverter.mustache +11 -0
- package/targets/feign/.mvn/wrapper/maven-wrapper.jar +0 -0
- package/targets/feign/.mvn/wrapper/maven-wrapper.properties +4 -2
- package/targets/feign/generate.sh +14 -1
- package/targets/feign/generator-config.json +5 -9
- package/targets/feign/mvnw +196 -168
- package/targets/feign-kotlin/.mvn/wrapper/maven-wrapper.jar +0 -0
- package/targets/feign-kotlin/.mvn/wrapper/maven-wrapper.properties +4 -2
- package/targets/feign-kotlin/generate.sh +15 -1
- package/targets/feign-kotlin/generator-config.json +5 -8
- package/targets/feign-kotlin/mvnw +196 -168
- package/targets/feign-kotlin/templates/libraries/spring-cloud/pom-sb4.mustache +241 -0
- package/targets/msw/templates/modelOneOf.mustache +7 -0
- package/targets/plain-java/.mvn/wrapper/maven-wrapper.jar +0 -0
- package/targets/plain-java/.mvn/wrapper/maven-wrapper.properties +4 -2
- package/targets/plain-java/generate.sh +13 -1
- package/targets/plain-java/generator-config.json +4 -5
- package/targets/plain-java/mvnw +196 -168
- package/targets/python/generate.sh +6 -1
- package/targets/python-legacy/generate.sh +6 -1
- package/targets/spring/.mvn/wrapper/maven-wrapper.jar +0 -0
- package/targets/spring/.mvn/wrapper/maven-wrapper.properties +4 -2
- package/targets/spring/generate.sh +13 -1
- package/targets/spring/generator-config.json +5 -7
- package/targets/spring/mvnw +196 -168
- package/targets/spring-kotlin/.mvn/wrapper/maven-wrapper.jar +0 -0
- package/targets/spring-kotlin/.mvn/wrapper/maven-wrapper.properties +4 -2
- package/targets/spring-kotlin/generate.sh +13 -1
- package/targets/spring-kotlin/generator-config.json +5 -6
- package/targets/spring-kotlin/mvnw +196 -168
- package/targets/feign/.mvn/wrapper/MavenWrapperDownloader.java +0 -117
- package/targets/feign/templates/beanValidation.mustache +0 -2
- package/targets/feign/templates/formParams.mustache +0 -3
- package/targets/feign-kotlin/.mvn/wrapper/MavenWrapperDownloader.java +0 -117
- package/targets/plain-java/.mvn/wrapper/MavenWrapperDownloader.java +0 -117
- package/targets/spring/.mvn/wrapper/MavenWrapperDownloader.java +0 -117
- package/targets/spring-kotlin/.mvn/wrapper/MavenWrapperDownloader.java +0 -117
package/README.md
CHANGED
|
@@ -140,15 +140,15 @@ The table below gives an overview of the changes (breaking, non-breaking, bug fi
|
|
|
140
140
|
| `dotnet-system-text-json` |🆕➖|
|
|
141
141
|
| `dotnet-webapi` |✨ |➖ |🆕➖|
|
|
142
142
|
| `dotnet-webapi-system-text-json` |🆕➖|
|
|
143
|
-
| `feign`
|
|
144
|
-
| `feign-kotlin`
|
|
145
|
-
| `plain-java`
|
|
143
|
+
| `feign` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |🐛 |🆕 |
|
|
144
|
+
| `feign-kotlin` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |🆕 |
|
|
145
|
+
| `plain-java` |🐛 |🐛 |🆕 |
|
|
146
146
|
| `flutter` |➖ |➖ |➖ |➖ |➖ |🆕 |
|
|
147
147
|
| `ios` |➖ |➖ |➖ |➖ |➖ |💥 |🐛 |➖ |➖ |➖ |✨ |➖ |💥 |➖ |➖ |✨ |🆕 |
|
|
148
148
|
| `apple-swift` |➖ |➖ |🆕 |
|
|
149
149
|
| `kmp` |✨ |✨ |➖ |➖ |🆕 |
|
|
150
|
-
| `python`
|
|
151
|
-
| `python-legacy`
|
|
150
|
+
| `python` |🐛 |➖ |🆕 |
|
|
151
|
+
| `python-legacy` |🐛 |➖ |💥 |➖ |🐛 |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
|
|
152
152
|
| `react` |💥 |➖ |🐛 |🐛 |➖ |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
|
|
153
153
|
| `typescript-axios` |✨ |➖ |🆕 |
|
|
154
154
|
| `typescript-fetch` |✨ |➖ |🆕 |
|
|
@@ -156,8 +156,8 @@ The table below gives an overview of the changes (breaking, non-breaking, bug fi
|
|
|
156
156
|
| `nestjs` |✨ |🐛 |💥 |💥 |➖ |💥 |✨ |➖ |➖ |🐛 |➖ |➖ |✨ |🆕 |
|
|
157
157
|
| `python-fastapi` |➖ |➖ |➖ |➖ |🆕 |
|
|
158
158
|
| `python-fastapi-raw-request` |➖ |➖ |➖ |➖ |🆕 |
|
|
159
|
-
| `spring`
|
|
160
|
-
| `spring-kotlin`
|
|
159
|
+
| `spring` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |➖ |✨ |➖ |🆕 |
|
|
160
|
+
| `spring-kotlin` |🐛 |✨ |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |✨ |➖ |🆕 |
|
|
161
161
|
| **Misc Targets** | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|
|
162
162
|
| `contract-testing` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
|
|
163
163
|
| `openapi` |➖ |➖ |➖ |➖ |➖ |➖ |💥 |➖ |➖ |✨ |➖ |🆕 |
|
|
@@ -907,6 +907,7 @@ TBD
|
|
|
907
907
|
|-|-|-|-|
|
|
908
908
|
| packageName | Package nem for the project (convention: snake_case) | Y | - |
|
|
909
909
|
| repositoryUrl | URL of the PyPI repository | Y | - |
|
|
910
|
+
| projectName | Internal project name, inherits value of packageName (advised to keep the same) | N | $packageName |
|
|
910
911
|
|
|
911
912
|
Publishing the PyPI packages is done with Twine. For authentication against the PiPI repository you need to set the `TWINE_USERNAME` and `TWINE_PASSWORD` environment variables.
|
|
912
913
|
|
|
@@ -926,6 +927,7 @@ Publishing the PyPI packages is done with Twine. For authentication against the
|
|
|
926
927
|
|-|-|-|-|
|
|
927
928
|
| packageName | Package nem for the project (convention: snake_case) | Y | - |
|
|
928
929
|
| repositoryUrl | URL of the PyPI repository | Y | - |
|
|
930
|
+
| projectName | Internal project name, inherits value of packageName (advised to keep the same) | N | $packageName |
|
|
929
931
|
|
|
930
932
|
> ⚠️ Using Pydantic v1 for legacy reasons, this target will be discontinued.
|
|
931
933
|
|
|
@@ -1277,19 +1279,31 @@ with **System.Text.Json**, targeting **.NET 10** and marked
|
|
|
1277
1279
|
> implements each `I{ApiName}` and calls `app.MapAll{PackageName}Endpoints()`; the
|
|
1278
1280
|
> abstract MVC controllers are suppressed.
|
|
1279
1281
|
>
|
|
1280
|
-
> The
|
|
1281
|
-
>
|
|
1282
|
-
>
|
|
1283
|
-
>
|
|
1284
|
-
>
|
|
1282
|
+
> The package builds AOT-clean: it sets `<EnableRequestDelegateGenerator>` so the
|
|
1283
|
+
> minimal-API `Map*()` calls are statically generated (no reflection-based request
|
|
1284
|
+
> delegates), each model emits a source-generated `JsonSerializerContext` used by
|
|
1285
|
+
> its `ToJson()` (no Newtonsoft, no reflection `JsonSerializer`), and there is no
|
|
1286
|
+
> reflection-based enum converter. Building the package under the AOT analyzer
|
|
1287
|
+
> (`<IsAotCompatible>`) raises no IL2026/IL3050 warnings.
|
|
1285
1288
|
>
|
|
1286
|
-
>
|
|
1287
|
-
>
|
|
1288
|
-
>
|
|
1289
|
+
> Enums (de)serialize by their wire value (e.g. `"available"`): each generated enum
|
|
1290
|
+
> carries `[JsonConverter(typeof(JsonStringEnumConverter<T>))]` with per-member
|
|
1291
|
+
> `[JsonStringEnumMemberName]`, which the source generator honours.
|
|
1292
|
+
>
|
|
1293
|
+
> **JSON registration.** The package generates a `{PackageName}JsonSerializerContext`
|
|
1294
|
+
> (a source-generated `JsonSerializerContext` over every model, request/response type
|
|
1295
|
+
> and inline enum) plus an `Add{PackageName}JsonOptions()` extension that registers it
|
|
1296
|
+
> on the minimal-API JSON resolver chain. Call it in Program.cs:
|
|
1289
1297
|
>
|
|
1290
1298
|
> ```csharp
|
|
1291
1299
|
> builder.Services.Add{PackageName}JsonOptions();
|
|
1292
1300
|
> ```
|
|
1301
|
+
>
|
|
1302
|
+
> This is **required when the host is published with Native AOT** (`PublishAot=true`),
|
|
1303
|
+
> because AOT removes the reflection JSON fallback and the endpoints must resolve every
|
|
1304
|
+
> DTO through source generation. For a reflection-based (JIT) host it is harmless (the
|
|
1305
|
+
> reflection resolver already covers everything), but registering it still gives faster,
|
|
1306
|
+
> allocation-free metadata, so calling it unconditionally is recommended.
|
|
1293
1307
|
|
|
1294
1308
|
##### `withWolverineImplementation`
|
|
1295
1309
|
|
package/bin/oasg
CHANGED
|
@@ -38,9 +38,9 @@ const DEFAULT_GENERATOR_MAPPING = {
|
|
|
38
38
|
// client targets
|
|
39
39
|
"android": { version: '7.17.0', generator: 'kotlin' },
|
|
40
40
|
"angular": { version: '7.11.0', generator: 'typescript-angular' },
|
|
41
|
-
"feign": { version: '7.
|
|
42
|
-
"feign-kotlin": { version: '7.
|
|
43
|
-
"plain-java": { version: '7.
|
|
41
|
+
"feign": { version: '7.22.0', generator: 'spring' },
|
|
42
|
+
"feign-kotlin": { version: '7.22.0', generator: 'kotlin-spring' },
|
|
43
|
+
"plain-java": { version: '7.22.0', generator: 'java' },
|
|
44
44
|
"flutter": { version: '7.0.1', generator: 'dart-dio' },
|
|
45
45
|
"ios": { version: '7.0.1', generator: 'swift5' },
|
|
46
46
|
"apple-swift": { version: undefined, generator: undefined },
|
|
@@ -52,8 +52,8 @@ const DEFAULT_GENERATOR_MAPPING = {
|
|
|
52
52
|
"typescript-fetch": { version: '7.11.0', generator: 'typescript-fetch' },
|
|
53
53
|
// server targets
|
|
54
54
|
"nestjs": { version: '7.0.1', generator: 'typescript-angular' },
|
|
55
|
-
"spring": { version: '7.
|
|
56
|
-
"spring-kotlin": { version: '7.
|
|
55
|
+
"spring": { version: '7.22.0', generator: 'spring' },
|
|
56
|
+
"spring-kotlin": { version: '7.22.0', generator: 'kotlin-spring' },
|
|
57
57
|
"python-fastapi": { version: '7.8.0', generator: 'python-fastapi' },
|
|
58
58
|
"python-fastapi-raw-request": { version: '7.0.1', generator: 'python-fastapi' },
|
|
59
59
|
"dotnet": { version: '7.11.0', generator: 'csharp-functions' },
|
|
@@ -741,4 +741,3 @@ function determineArtifactVersion(argv) {
|
|
|
741
741
|
function determinePreRelease(argv) {
|
|
742
742
|
return argv.preRelease ? true : false;
|
|
743
743
|
}
|
|
744
|
-
|
package/config.schema.yml
CHANGED
|
@@ -344,6 +344,8 @@ targets:
|
|
|
344
344
|
type: string
|
|
345
345
|
repositoryUrl:
|
|
346
346
|
type: string
|
|
347
|
+
projectName:
|
|
348
|
+
type: string
|
|
347
349
|
required:
|
|
348
350
|
- packageName
|
|
349
351
|
- repositoryUrl
|
|
@@ -358,6 +360,8 @@ targets:
|
|
|
358
360
|
type: string
|
|
359
361
|
repositoryUrl:
|
|
360
362
|
type: string
|
|
363
|
+
projectName:
|
|
364
|
+
type: string
|
|
361
365
|
required:
|
|
362
366
|
- packageName
|
|
363
367
|
- repositoryUrl
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-supercharge/oasg",
|
|
3
|
-
"version": "18.1.
|
|
3
|
+
"version": "18.2.1-temp-feat-spring-boot-4.956dbdab",
|
|
4
4
|
"description": "Node-based tool to lint OpenAPI documents and generate clients, servers and documentation from them",
|
|
5
5
|
"author": "Supercharge",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"@types/jest": "^29.5.12",
|
|
49
49
|
"execa": "^5.0.0",
|
|
50
50
|
"fs-extra": "^11.1.1",
|
|
51
|
-
"jest": "^29.5.0"
|
|
51
|
+
"jest": "^29.5.0",
|
|
52
|
+
"jest-html-reporter": "^4.4.0",
|
|
53
|
+
"jest-junit": "^17.0.0"
|
|
52
54
|
}
|
|
53
55
|
}
|
|
@@ -31,6 +31,12 @@ Everything lives in a single `EndpointRouteBuilderExtensions.cs`:
|
|
|
31
31
|
- **`ConfigureWolverineMessaging(this WolverineOptions, string localQueueName = "MyApi")`** —
|
|
32
32
|
routes every request type in the assembly to a local queue.
|
|
33
33
|
|
|
34
|
+
A separate `ServiceCollectionExtensions.cs` holds a source-generated
|
|
35
|
+
`{PackageName}JsonSerializerContext` (covering every model, request/response type
|
|
36
|
+
and inline enum) and an **`Add{PackageName}JsonOptions(this IServiceCollection)`**
|
|
37
|
+
extension that registers it on the minimal-API JSON resolver chain — call it in
|
|
38
|
+
Program.cs (required when publishing the host with Native AOT; harmless otherwise).
|
|
39
|
+
|
|
34
40
|
The `WolverineFx` package reference is added automatically.
|
|
35
41
|
|
|
36
42
|
---
|
|
@@ -61,6 +67,7 @@ using MyApi; // generated Map{ApiName}Endpoints / MapAllMyApiEndpoints / Configu
|
|
|
61
67
|
|
|
62
68
|
var builder = WebApplication.CreateBuilder(args);
|
|
63
69
|
builder.Services.AddHttpContextAccessor(); // see "Authentication" below
|
|
70
|
+
builder.Services.AddMyApiJsonOptions(); // register the source-gen JSON context (required for Native AOT)
|
|
64
71
|
|
|
65
72
|
builder.Host.UseWolverine(opts =>
|
|
66
73
|
{
|
|
@@ -26,7 +26,7 @@ if [ -f "$endpointsFile" ]; then
|
|
|
26
26
|
sed -i.bak 's/\.MapHttp/.Map/g' "$destFile" && rm -f "$destFile.bak"
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
|
-
# Same for the JSON-
|
|
29
|
+
# Same for the JSON source-gen context / service-collection extension (SupportingFiles file).
|
|
30
30
|
serviceExtFile="out/$targetId/ServiceCollectionExtensions.cs"
|
|
31
31
|
if [ -f "$serviceExtFile" ]; then
|
|
32
32
|
mv "$serviceExtFile" "out/$targetId/src/$packageName/ServiceCollectionExtensions.cs"
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
<Authors>{{packageAuthors}}</Authors>
|
|
6
6
|
<TargetFramework>net10.0</TargetFramework>
|
|
7
7
|
<IsAotCompatible>true</IsAotCompatible>
|
|
8
|
+
<!-- Statically generate the minimal-API request delegates (interceptors) so the
|
|
9
|
+
Map*() calls are trim-/AOT-safe instead of reflection-based at runtime.
|
|
10
|
+
Without this the [RequiresDynamicCode]/[RequiresUnreferencedCode] Map*
|
|
11
|
+
overloads raise IL3050/IL2026 under the AOT analyzer enabled above. -->
|
|
12
|
+
<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
|
|
8
13
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
9
14
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
|
10
15
|
<Version>{{packageVersion}}</Version>
|
|
@@ -38,9 +43,6 @@
|
|
|
38
43
|
{{^useFrameworkReference}}
|
|
39
44
|
<PackageReference Include="Microsoft.AspNetCore.App" />
|
|
40
45
|
{{/useFrameworkReference}}
|
|
41
|
-
{{^useSeparateModelProject}}
|
|
42
|
-
<PackageReference Include="Microsoft.Extensions.Configuration.Json" {{#usePackageVersions}}Version="{{aspnetCoreVersion}}.0" {{/usePackageVersions}}/>
|
|
43
|
-
{{/useSeparateModelProject}}
|
|
44
46
|
{{#useSwashbuckle}}
|
|
45
47
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" {{#usePackageVersions}}Version="1.10.8" {{/usePackageVersions}}/>
|
|
46
48
|
{{#useNewtonsoft}}
|
|
@@ -57,7 +59,6 @@
|
|
|
57
59
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" {{#usePackageVersions}}Version="{{newtonsoftVersion}}" {{/usePackageVersions}}/>
|
|
58
60
|
{{/useNewtonsoft}}
|
|
59
61
|
{{/useSwashbuckle}}
|
|
60
|
-
<PackageReference Include="JsonSubTypes" {{#usePackageVersions}}Version="1.8.0" {{/usePackageVersions}}/>
|
|
61
62
|
</ItemGroup>
|
|
62
63
|
<ItemGroup>
|
|
63
64
|
<!--<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="{{aspnetCoreVersion}}.0" />-->
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
/// <summary>
|
|
3
|
+
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}}
|
|
4
|
+
/// </summary>
|
|
5
|
+
{{#description}}
|
|
6
|
+
/// <value>{{{.}}}</value>
|
|
7
|
+
{{/description}}
|
|
8
|
+
{{! AOT-safe enum (de)serialization: the source-generated, generic }}
|
|
9
|
+
{{! JsonStringEnumConverter<T> (no runtime MakeGenericType/Activator) plus the }}
|
|
10
|
+
{{! per-member JsonStringEnumMemberName below, which maps each value to its wire }}
|
|
11
|
+
{{! form. The attribute travels with the type, so enums round-trip as strings }}
|
|
12
|
+
{{! for reflection-based (JIT) hosts and source-generated (AOT) hosts alike. }}
|
|
13
|
+
[JsonConverter(typeof(JsonStringEnumConverter<{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}>))]
|
|
14
|
+
public enum {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
|
|
15
|
+
{
|
|
16
|
+
{{#allowableValues}}{{#enumVars}}
|
|
17
|
+
/// <summary>
|
|
18
|
+
/// Enum {{name}} for {{{value}}}
|
|
19
|
+
/// </summary>
|
|
20
|
+
{{#isString}}[EnumMember(Value = "{{{value}}}")]
|
|
21
|
+
[JsonStringEnumMemberName("{{{value}}}")]{{/isString}}
|
|
22
|
+
{{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},
|
|
23
|
+
{{/-last}}{{/enumVars}}{{/allowableValues}}
|
|
24
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// <auto-generated/>
|
|
2
2
|
#nullable enable
|
|
3
|
+
using System;
|
|
3
4
|
using System.Collections.Generic;
|
|
4
5
|
using System.Threading;
|
|
5
6
|
using System.Threading.Tasks;
|
|
@@ -25,6 +26,7 @@ namespace {{packageName}}
|
|
|
25
26
|
{
|
|
26
27
|
{{#operations}}
|
|
27
28
|
{{#operation}}
|
|
29
|
+
/// <summary>Application logic for the {{operationId}} operation.</summary>
|
|
28
30
|
Task<IResult> {{operationId}}({{#allParams}}{{>paramType}} {{paramName}}, {{/allParams}}CancellationToken cancellationToken);
|
|
29
31
|
{{/operation}}
|
|
30
32
|
{{/operations}}
|
|
@@ -76,7 +78,7 @@ namespace {{packageName}}
|
|
|
76
78
|
{{/apis}}
|
|
77
79
|
{{/apiInfo}}
|
|
78
80
|
/// <summary>Maps the endpoints of every generated API.</summary>
|
|
79
|
-
public static IEndpointRouteBuilder MapAll{{packageName}}Endpoints(this IEndpointRouteBuilder endpoints)
|
|
81
|
+
public static IEndpointRouteBuilder MapAll{{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}Endpoints(this IEndpointRouteBuilder endpoints)
|
|
80
82
|
{
|
|
81
83
|
{{#apiInfo}}
|
|
82
84
|
{{#apis}}
|
package/targets/dotnet-webapi-system-text-json/templates/serviceCollectionExtensions.mustache
CHANGED
|
@@ -1,66 +1,90 @@
|
|
|
1
1
|
// <auto-generated/>
|
|
2
|
+
#nullable enable
|
|
2
3
|
using System;
|
|
3
4
|
using System.Collections.Generic;
|
|
4
|
-
using System.Reflection;
|
|
5
|
-
using System.Runtime.Serialization;
|
|
6
|
-
using System.Text.Json;
|
|
7
5
|
using System.Text.Json.Serialization;
|
|
8
|
-
using Microsoft.AspNetCore.Http.Json;
|
|
9
6
|
using Microsoft.Extensions.DependencyInjection;
|
|
7
|
+
using {{packageName}}.Models;
|
|
10
8
|
|
|
11
9
|
namespace {{packageName}}
|
|
12
10
|
{
|
|
13
11
|
/// <summary>
|
|
14
|
-
///
|
|
15
|
-
///
|
|
12
|
+
/// System.Text.Json source-generation context covering every type this package
|
|
13
|
+
/// (de)serializes through its minimal-API endpoints: each generated model, each
|
|
14
|
+
/// operation request/response type, and each inline enum. Registering it (see
|
|
15
|
+
/// <see cref="{{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}ServiceCollectionExtensions" />)
|
|
16
|
+
/// lets the endpoints resolve JSON metadata via source generation, which is what
|
|
17
|
+
/// makes the package safe to trim and to publish with Native AOT — the pipeline
|
|
18
|
+
/// never falls back to reflection.
|
|
16
19
|
/// </summary>
|
|
17
|
-
|
|
20
|
+
/// <remarks>
|
|
21
|
+
/// Duplicate <c>[JsonSerializable]</c> entries are coalesced by the generator, so
|
|
22
|
+
/// request/response types that are also models are harmless. Inline enums are
|
|
23
|
+
/// registered with an explicit <c>TypeInfoPropertyName</c> because two models can
|
|
24
|
+
/// declare equally-named nested enums (e.g. <c>Order.StatusEnum</c> and
|
|
25
|
+
/// <c>Pet.StatusEnum</c>), which would otherwise collide under SYSLIB1031.
|
|
26
|
+
/// </remarks>
|
|
27
|
+
[JsonSerializable(typeof(string))]
|
|
28
|
+
{{#models}}
|
|
29
|
+
{{#model}}
|
|
30
|
+
[JsonSerializable(typeof({{classname}}))]
|
|
31
|
+
{{#vars}}
|
|
32
|
+
{{#isEnum}}
|
|
33
|
+
{{^complexType}}
|
|
34
|
+
[JsonSerializable(typeof({{classname}}.{{datatypeWithEnum}}), TypeInfoPropertyName = "{{classname}}{{datatypeWithEnum}}")]
|
|
35
|
+
{{/complexType}}
|
|
36
|
+
{{/isEnum}}
|
|
37
|
+
{{#items.isEnum}}
|
|
38
|
+
{{#items}}
|
|
39
|
+
{{^complexType}}
|
|
40
|
+
[JsonSerializable(typeof({{classname}}.{{datatypeWithEnum}}), TypeInfoPropertyName = "{{classname}}{{datatypeWithEnum}}")]
|
|
41
|
+
{{/complexType}}
|
|
42
|
+
{{/items}}
|
|
43
|
+
{{/items.isEnum}}
|
|
44
|
+
{{/vars}}
|
|
45
|
+
{{/model}}
|
|
46
|
+
{{/models}}
|
|
47
|
+
{{#apiInfo}}
|
|
48
|
+
{{#apis}}
|
|
49
|
+
{{#operations}}
|
|
50
|
+
{{#operation}}
|
|
51
|
+
{{^isResponseFile}}
|
|
52
|
+
{{#returnType}}
|
|
53
|
+
[JsonSerializable(typeof({{{returnType}}}))]
|
|
54
|
+
{{/returnType}}
|
|
55
|
+
{{/isResponseFile}}
|
|
56
|
+
{{#bodyParam}}
|
|
57
|
+
{{^isBinary}}
|
|
58
|
+
[JsonSerializable(typeof({{#isArray}}List<{{{items.dataType}}}>{{/isArray}}{{^isArray}}{{{baseType}}}{{/isArray}}))]
|
|
59
|
+
{{/isBinary}}
|
|
60
|
+
{{/bodyParam}}
|
|
61
|
+
{{/operation}}
|
|
62
|
+
{{/operations}}
|
|
63
|
+
{{/apis}}
|
|
64
|
+
{{/apiInfo}}
|
|
65
|
+
public partial class {{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}JsonSerializerContext : JsonSerializerContext
|
|
18
66
|
{
|
|
19
|
-
public static IServiceCollection Add{{packageName}}JsonOptions(this IServiceCollection services)
|
|
20
|
-
{
|
|
21
|
-
services.Configure<JsonOptions>(opts =>
|
|
22
|
-
opts.SerializerOptions.Converters.Add(new EnumMemberJsonConverterFactory()));
|
|
23
|
-
return services;
|
|
24
|
-
}
|
|
25
67
|
}
|
|
26
68
|
|
|
27
69
|
/// <summary>
|
|
28
|
-
///
|
|
29
|
-
///
|
|
70
|
+
/// Registers the System.Text.Json source-generation context for this generated
|
|
71
|
+
/// package. Call <c>builder.Services.Add{{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}JsonOptions()</c>
|
|
72
|
+
/// in Program.cs so the minimal-API endpoints resolve JSON metadata via source
|
|
73
|
+
/// generation — required when the host is published with Native AOT, harmless
|
|
74
|
+
/// (a no-op the reflection resolver already covers) for a JIT host.
|
|
30
75
|
/// </summary>
|
|
31
|
-
|
|
76
|
+
public static class {{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}ServiceCollectionExtensions
|
|
32
77
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
internal sealed class EnumMemberJsonConverter<T> : JsonConverter<T> where T : struct, Enum
|
|
41
|
-
{
|
|
42
|
-
private static readonly Dictionary<string, T> _read;
|
|
43
|
-
private static readonly Dictionary<T, string> _write;
|
|
44
|
-
|
|
45
|
-
static EnumMemberJsonConverter()
|
|
78
|
+
/// <summary>
|
|
79
|
+
/// Inserts <see cref="{{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}JsonSerializerContext" />
|
|
80
|
+
/// at the front of the minimal-API JSON type-info resolver chain.
|
|
81
|
+
/// </summary>
|
|
82
|
+
public static IServiceCollection Add{{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}JsonOptions(this IServiceCollection services)
|
|
46
83
|
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
var wireValue = field.GetCustomAttribute<EnumMemberAttribute>()?.Value ?? field.Name;
|
|
52
|
-
var enumValue = (T)field.GetValue(null)!;
|
|
53
|
-
_read[wireValue] = enumValue;
|
|
54
|
-
_write[enumValue] = wireValue;
|
|
55
|
-
}
|
|
84
|
+
services.ConfigureHttpJsonOptions(options =>
|
|
85
|
+
options.SerializerOptions.TypeInfoResolverChain.Insert(
|
|
86
|
+
0, {{#lambda.pascalcase}}{{packageName}}{{/lambda.pascalcase}}JsonSerializerContext.Default));
|
|
87
|
+
return services;
|
|
56
88
|
}
|
|
57
|
-
|
|
58
|
-
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
|
|
59
|
-
_read.TryGetValue(reader.GetString() ?? string.Empty, out var value)
|
|
60
|
-
? value
|
|
61
|
-
: throw new JsonException($"Unknown value '{reader.GetString()}' for {typeof(T).Name}");
|
|
62
|
-
|
|
63
|
-
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) =>
|
|
64
|
-
writer.WriteStringValue(_write.TryGetValue(value, out var s) ? s : value.ToString());
|
|
65
89
|
}
|
|
66
90
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// <auto-generated/>
|
|
2
|
+
//
|
|
3
|
+
// Intentionally empty for the System.Text.Json / Native-AOT target.
|
|
4
|
+
//
|
|
5
|
+
// The default aspnetcore template emits an MVC `CustomEnumConverter<T>`
|
|
6
|
+
// (a TypeConverter whose body calls the reflection-based
|
|
7
|
+
// JsonSerializer.Deserialize<T>, which raises IL2026/IL3050 under the AOT
|
|
8
|
+
// analyzer). This target suppresses MVC controllers and (de)serializes enums
|
|
9
|
+
// via [JsonConverter(typeof(JsonStringEnumConverter<T>))] + [JsonStringEnumMemberName]
|
|
10
|
+
// on each generated enum, so the converter is unused — and is omitted here to
|
|
11
|
+
// keep the package AOT-clean.
|
|
Binary file
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
wrapperVersion=3.3.4
|
|
2
|
+
distributionType=bin
|
|
3
|
+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
|
|
4
|
+
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar
|
|
@@ -5,13 +5,26 @@ source $(dirname "$0")/../common.sh
|
|
|
5
5
|
rm -rf out/$targetId
|
|
6
6
|
mkdir -p out/$targetId
|
|
7
7
|
|
|
8
|
+
properties=(
|
|
9
|
+
"artifactId=${artifactId}"
|
|
10
|
+
"groupId=${groupId}"
|
|
11
|
+
"artifactVersion=${version}"
|
|
12
|
+
"basePackage=${basePackage}"
|
|
13
|
+
"apiPackage=${basePackage}.api"
|
|
14
|
+
"modelPackage=${basePackage}.model"
|
|
15
|
+
"configPackage=${basePackage}.config"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
props=$(IFS=,; echo "${properties[*]}")
|
|
19
|
+
|
|
8
20
|
java -jar $binary generate \
|
|
9
21
|
-g $generatorId \
|
|
10
22
|
-i $openApiFile \
|
|
11
23
|
-t $templateDir \
|
|
12
24
|
-o out/$targetId \
|
|
13
25
|
-c $(dirname "$0")/generator-config.json \
|
|
14
|
-
-p "
|
|
26
|
+
-p "$props" \
|
|
27
|
+
$generatorCustomArgs
|
|
15
28
|
|
|
16
29
|
cd out/$targetId
|
|
17
30
|
cp $(dirname "$0")/mvnw .
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"library": "spring-cloud",
|
|
3
|
-
"dateLibrary": "java8",
|
|
4
|
-
"java8": true,
|
|
5
3
|
"useTags": true,
|
|
6
4
|
"hideGenerationTimestamp": true,
|
|
7
5
|
"booleanGetterPrefix": "is",
|
|
8
|
-
"generateForOpenFeign": true,
|
|
9
|
-
"removeEnumValuePrefix": false,
|
|
10
6
|
"documentationProvider": "none",
|
|
11
7
|
"annotationLibrary": "none",
|
|
12
|
-
"useSpringBoot3":
|
|
8
|
+
"useSpringBoot3": false,
|
|
9
|
+
"useSpringBoot4": true,
|
|
10
|
+
"useJackson3": true,
|
|
13
11
|
"typeMappings": {
|
|
14
|
-
"OffsetDateTime": "
|
|
15
|
-
"Date": "java.time.LocalDate"
|
|
12
|
+
"OffsetDateTime": "Instant"
|
|
16
13
|
},
|
|
17
14
|
"importMappings": {
|
|
18
|
-
"
|
|
19
|
-
"java.util.Date": "java.time.LocalDate"
|
|
15
|
+
"OffsetDateTime": "java.time.Instant"
|
|
20
16
|
},
|
|
21
17
|
"inlineSchemaOptions": {
|
|
22
18
|
"ARRAY_ITEM_SUFFIX": "",
|