@nestia/migrate 14.0.0 → 14.0.2
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 +1 -1
- package/lib/NestiaMigrateApplication.d.ts +111 -0
- package/lib/NestiaMigrateApplication.js +148 -9
- package/lib/NestiaMigrateApplication.js.map +1 -1
- package/lib/NestiaMigrateApplication.mjs +147 -5
- package/lib/analyzers/NestiaMigrateControllerAnalyzer.d.ts +58 -0
- package/lib/analyzers/NestiaMigrateControllerAnalyzer.js +88 -2
- package/lib/analyzers/NestiaMigrateControllerAnalyzer.js.map +1 -1
- package/lib/analyzers/NestiaMigrateControllerAnalyzer.mjs +20 -2
- package/lib/archivers/NestiaMigrateFileArchiver.d.ts +34 -0
- package/lib/archivers/NestiaMigrateFileArchiver.js +34 -0
- package/lib/archivers/NestiaMigrateFileArchiver.js.map +1 -1
- package/lib/bundles/NEST_TEMPLATE.js +1 -1
- package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
- package/lib/bundles/NEST_TEMPLATE.mjs +1 -1
- package/lib/bundles/SDK_TEMPLATE.js +1 -1
- package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
- package/lib/bundles/SDK_TEMPLATE.mjs +1 -1
- package/lib/executable/NestiaMigrateCommander.d.ts +36 -0
- package/lib/executable/NestiaMigrateCommander.js +43 -1
- package/lib/executable/NestiaMigrateCommander.js.map +1 -1
- package/lib/executable/NestiaMigrateCommander.mjs +4 -2
- package/lib/executable/NestiaMigrateInquirer.d.ts +29 -0
- package/lib/executable/NestiaMigrateInquirer.js +27 -25
- package/lib/executable/NestiaMigrateInquirer.js.map +1 -1
- package/lib/executable/NestiaMigrateInquirer.mjs +5 -7
- package/lib/factories/ExpressionFactory.d.ts +14 -0
- package/lib/factories/ExpressionFactory.js +14 -0
- package/lib/factories/ExpressionFactory.js.map +1 -1
- package/lib/factories/IdentifierFactory.d.ts +20 -0
- package/lib/factories/IdentifierFactory.js +20 -0
- package/lib/factories/IdentifierFactory.js.map +1 -1
- package/lib/factories/LiteralFactory.d.ts +18 -2
- package/lib/factories/LiteralFactory.js +18 -2
- package/lib/factories/LiteralFactory.js.map +1 -1
- package/lib/factories/StatementFactory.d.ts +26 -1
- package/lib/factories/StatementFactory.js +26 -1
- package/lib/factories/StatementFactory.js.map +1 -1
- package/lib/factories/SupportedStringFormats.d.ts +6 -0
- package/lib/factories/SupportedStringFormats.js +33 -0
- package/lib/factories/SupportedStringFormats.js.map +1 -0
- package/lib/factories/SupportedStringFormats.mjs +34 -0
- package/lib/factories/SupportedStringFormats.mjs.map +1 -0
- package/lib/factories/TypeFactory.d.ts +21 -0
- package/lib/factories/TypeFactory.js +13 -0
- package/lib/factories/TypeFactory.js.map +1 -1
- package/lib/factories/TypeLiteralFactory.d.ts +18 -0
- package/lib/factories/TypeLiteralFactory.js +18 -0
- package/lib/factories/TypeLiteralFactory.js.map +1 -1
- package/lib/internal/ts.d.ts +153 -0
- package/lib/internal/ts.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiFileProgrammer.d.ts +31 -0
- package/lib/programmers/NestiaMigrateApiFileProgrammer.js +17 -0
- package/lib/programmers/NestiaMigrateApiFileProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiFunctionProgrammer.d.ts +40 -0
- package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js +34 -5
- package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiFunctionProgrammer.mjs +4 -2
- package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.d.ts +39 -0
- package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.js +57 -13
- package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.mjs +17 -8
- package/lib/programmers/NestiaMigrateApiProgrammer.d.ts +18 -0
- package/lib/programmers/NestiaMigrateApiProgrammer.js +18 -0
- package/lib/programmers/NestiaMigrateApiProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiProgrammer.mjs +1 -1
- package/lib/programmers/NestiaMigrateApiSimulationProgrammer.d.ts +40 -0
- package/lib/programmers/NestiaMigrateApiSimulationProgrammer.js +51 -22
- package/lib/programmers/NestiaMigrateApiSimulationProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiSimulationProgrammer.mjs +13 -20
- package/lib/programmers/NestiaMigrateApiStartProgrammer.d.ts +17 -0
- package/lib/programmers/NestiaMigrateApiStartProgrammer.js +19 -8
- package/lib/programmers/NestiaMigrateApiStartProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateApiStartProgrammer.mjs +1 -6
- package/lib/programmers/NestiaMigrateDtoProgrammer.d.ts +30 -0
- package/lib/programmers/NestiaMigrateDtoProgrammer.js +17 -0
- package/lib/programmers/NestiaMigrateDtoProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateE2eFileProgrammer.d.ts +39 -0
- package/lib/programmers/NestiaMigrateE2eFileProgrammer.js +46 -5
- package/lib/programmers/NestiaMigrateE2eFileProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateE2eFileProgrammer.mjs +6 -2
- package/lib/programmers/NestiaMigrateE2eProgrammer.d.ts +16 -0
- package/lib/programmers/NestiaMigrateE2eProgrammer.js +16 -0
- package/lib/programmers/NestiaMigrateE2eProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateImportProgrammer.d.ts +75 -0
- package/lib/programmers/NestiaMigrateImportProgrammer.js +58 -3
- package/lib/programmers/NestiaMigrateImportProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateImportProgrammer.mjs +58 -3
- package/lib/programmers/NestiaMigrateNestControllerProgrammer.d.ts +28 -0
- package/lib/programmers/NestiaMigrateNestControllerProgrammer.js +16 -0
- package/lib/programmers/NestiaMigrateNestControllerProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateNestMethodProgrammer.d.ts +30 -0
- package/lib/programmers/NestiaMigrateNestMethodProgrammer.js +85 -13
- package/lib/programmers/NestiaMigrateNestMethodProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateNestMethodProgrammer.mjs +46 -9
- package/lib/programmers/NestiaMigrateNestModuleProgrammer.d.ts +16 -0
- package/lib/programmers/NestiaMigrateNestModuleProgrammer.js +16 -0
- package/lib/programmers/NestiaMigrateNestModuleProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateNestProgrammer.d.ts +17 -0
- package/lib/programmers/NestiaMigrateNestProgrammer.js +17 -0
- package/lib/programmers/NestiaMigrateNestProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateSchemaProgrammer.d.ts +16 -0
- package/lib/programmers/NestiaMigrateSchemaProgrammer.js +45 -9
- package/lib/programmers/NestiaMigrateSchemaProgrammer.js.map +1 -1
- package/lib/programmers/NestiaMigrateSchemaProgrammer.mjs +19 -8
- package/lib/structures/INestiaMigrateConfig.d.ts +21 -0
- package/lib/structures/INestiaMigrateContext.d.ts +15 -0
- package/lib/structures/INestiaMigrateController.d.ts +13 -0
- package/lib/structures/INestiaMigrateFile.d.ts +11 -0
- package/lib/utils/FilePrinter.d.ts +33 -0
- package/lib/utils/FilePrinter.js +33 -0
- package/lib/utils/FilePrinter.js.map +1 -1
- package/lib/utils/MapUtil.d.ts +17 -0
- package/lib/utils/MapUtil.js +19 -3
- package/lib/utils/MapUtil.js.map +1 -1
- package/lib/utils/MapUtil.mjs +1 -2
- package/lib/utils/PathTemplate.d.ts +41 -0
- package/lib/utils/PathTemplate.js +56 -0
- package/lib/utils/PathTemplate.js.map +1 -0
- package/lib/utils/PathTemplate.mjs +34 -0
- package/lib/utils/PathTemplate.mjs.map +1 -0
- package/lib/utils/RequestBody.d.ts +22 -0
- package/lib/utils/RequestBody.js +29 -0
- package/lib/utils/RequestBody.js.map +1 -0
- package/lib/utils/RequestBody.mjs +9 -0
- package/lib/utils/RequestBody.mjs.map +1 -0
- package/lib/utils/StringUtil.d.ts +55 -0
- package/lib/utils/StringUtil.js +93 -8
- package/lib/utils/StringUtil.js.map +1 -1
- package/lib/utils/StringUtil.mjs +30 -8
- package/lib/utils/SuccessStatus.d.ts +34 -0
- package/lib/utils/SuccessStatus.js +48 -0
- package/lib/utils/SuccessStatus.js.map +1 -0
- package/lib/utils/SuccessStatus.mjs +14 -0
- package/lib/utils/SuccessStatus.mjs.map +1 -0
- package/package.json +5 -4
- package/src/NestiaMigrateApplication.ts +151 -13
- package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +94 -2
- package/src/archivers/NestiaMigrateFileArchiver.ts +34 -0
- package/src/bundles/NEST_TEMPLATE.ts +1 -1
- package/src/bundles/SDK_TEMPLATE.ts +1 -1
- package/src/executable/NestiaMigrateCommander.ts +47 -1
- package/src/executable/NestiaMigrateInquirer.ts +41 -26
- package/src/factories/ExpressionFactory.ts +14 -0
- package/src/factories/IdentifierFactory.ts +20 -0
- package/src/factories/LiteralFactory.ts +18 -2
- package/src/factories/StatementFactory.ts +26 -1
- package/src/factories/SupportedStringFormats.ts +29 -0
- package/src/factories/TypeFactory.ts +21 -0
- package/src/factories/TypeLiteralFactory.ts +18 -0
- package/src/internal/ts.ts +153 -0
- package/src/programmers/NestiaMigrateApiFileProgrammer.ts +35 -0
- package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +53 -4
- package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +83 -20
- package/src/programmers/NestiaMigrateApiProgrammer.ts +18 -0
- package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +66 -73
- package/src/programmers/NestiaMigrateApiStartProgrammer.ts +19 -10
- package/src/programmers/NestiaMigrateDtoProgrammer.ts +33 -0
- package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +83 -8
- package/src/programmers/NestiaMigrateE2eProgrammer.ts +16 -0
- package/src/programmers/NestiaMigrateImportProgrammer.ts +86 -5
- package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +30 -0
- package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +122 -29
- package/src/programmers/NestiaMigrateNestModuleProgrammer.ts +16 -0
- package/src/programmers/NestiaMigrateNestProgrammer.ts +17 -0
- package/src/programmers/NestiaMigrateSchemaProgrammer.ts +53 -18
- package/src/structures/INestiaMigrateConfig.ts +26 -0
- package/src/structures/INestiaMigrateContext.ts +17 -0
- package/src/structures/INestiaMigrateController.ts +16 -0
- package/src/structures/INestiaMigrateFile.ts +13 -0
- package/src/utils/FilePrinter.ts +33 -0
- package/src/utils/MapUtil.ts +18 -2
- package/src/utils/PathTemplate.ts +61 -0
- package/src/utils/RequestBody.ts +27 -0
- package/src/utils/StringUtil.ts +101 -9
- package/src/utils/SuccessStatus.ts +49 -0
- package/lib/factories/FormatCheatSheet.d.ts +0 -25
- package/lib/factories/FormatCheatSheet.js +0 -34
- package/lib/factories/FormatCheatSheet.js.map +0 -1
- package/lib/factories/FormatCheatSheet.mjs +0 -31
- package/lib/factories/FormatCheatSheet.mjs.map +0 -1
- package/src/factories/FormatCheatSheet.ts +0 -71
|
@@ -1,20 +1,48 @@
|
|
|
1
|
-
import { SyntaxKind, factory } from "@ttsc/factory";
|
|
1
|
+
import { type EntityName, SyntaxKind, factory } from "@ttsc/factory";
|
|
2
2
|
|
|
3
3
|
import { TypeLiteralFactory } from "../factories/TypeLiteralFactory";
|
|
4
4
|
import ts from "../internal/ts";
|
|
5
5
|
import { FilePrinter } from "../utils/FilePrinter";
|
|
6
6
|
import { MapUtil } from "../utils/MapUtil";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Collects the imports that generated code needs and turns them into import
|
|
10
|
+
* statements.
|
|
11
|
+
*
|
|
12
|
+
* @evidence contracts/common.md#principled-implementation External imports are grouped by library into one clause with an optional default and a set of named instances, DTO imports are grouped by module specifier and emitted type-only, and a DTO is never imported into its own file.
|
|
13
|
+
* @evidence contracts/common.md#clear-and-simple-design One class with two collections and one emitter; the tag helper builds `typia.tags` references.
|
|
14
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The imports follow the code that asks for them.
|
|
15
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states its purpose.
|
|
16
|
+
*/
|
|
8
17
|
export class NestiaMigrateImportProgrammer {
|
|
9
18
|
private external_: Map<string, IClause> = new Map();
|
|
10
19
|
private dtos_: Set<string> = new Set();
|
|
11
20
|
|
|
12
21
|
public constructor() {}
|
|
13
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Reports whether no import has been requested.
|
|
25
|
+
*
|
|
26
|
+
* @evidence contracts/common.md#principled-implementation The importer is empty exactly when both collections are empty.
|
|
27
|
+
* @evidence contracts/common.md#clear-and-simple-design One expression.
|
|
28
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It reads the state.
|
|
29
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the meaning.
|
|
30
|
+
*/
|
|
14
31
|
public empty(): boolean {
|
|
15
32
|
return this.external_.size === 0 && this.dtos_.size === 0;
|
|
16
33
|
}
|
|
17
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Requests an import from a library and returns the local name to use.
|
|
37
|
+
*
|
|
38
|
+
* The returned name is the first segment of the requested name, so a nested
|
|
39
|
+
* name such as `tags.Type` imports `tags`.
|
|
40
|
+
*
|
|
41
|
+
* @evidence contracts/common.md#principled-implementation A default import replaces the clause's default and an instance import adds a named import, and the first segment of a dotted name is what the code refers to.
|
|
42
|
+
* @evidence contracts/common.md#clear-and-simple-design One function over one map.
|
|
43
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The library and the name come from the caller.
|
|
44
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the returned name.
|
|
45
|
+
*/
|
|
18
46
|
public external(props: MigrateImportProgrammer.IProps): string {
|
|
19
47
|
const clause: IClause = MapUtil.take(this.external_)(props.library)(() => ({
|
|
20
48
|
default: null,
|
|
@@ -26,19 +54,41 @@ export class NestiaMigrateImportProgrammer {
|
|
|
26
54
|
return name;
|
|
27
55
|
}
|
|
28
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Requests a DTO import and returns a reference to it, qualified by a
|
|
59
|
+
* namespace when one is given.
|
|
60
|
+
*
|
|
61
|
+
* @evidence contracts/common.md#principled-implementation The DTO is recorded by the first segment of its dotted name, which is the file that exports it, and the returned reference keeps the full name, with the namespace prepended when one is given.
|
|
62
|
+
* @evidence contracts/common.md#clear-and-simple-design One function over one set.
|
|
63
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The name comes from the caller.
|
|
64
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the reference.
|
|
65
|
+
*/
|
|
29
66
|
public dto(name: string, namespace?: string): ts.TypeReferenceNode {
|
|
30
|
-
const
|
|
31
|
-
this.dtos_.add(
|
|
67
|
+
const segments: string[] = name.split(".");
|
|
68
|
+
this.dtos_.add(segments[0]!);
|
|
32
69
|
return factory.createTypeReferenceNode(
|
|
33
70
|
namespace?.length
|
|
34
|
-
?
|
|
71
|
+
? segments.reduce<EntityName>(
|
|
72
|
+
(left, segment) =>
|
|
73
|
+
factory.createQualifiedName(
|
|
74
|
+
left,
|
|
75
|
+
factory.createIdentifier(segment),
|
|
76
|
+
),
|
|
35
77
|
factory.createIdentifier(namespace),
|
|
36
|
-
factory.createIdentifier(file),
|
|
37
78
|
)
|
|
38
79
|
: name,
|
|
39
80
|
);
|
|
40
81
|
}
|
|
41
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Requests the `typia` tags import and returns a reference to a tag with an
|
|
85
|
+
* optional literal argument.
|
|
86
|
+
*
|
|
87
|
+
* @evidence contracts/common.md#principled-implementation The argument is converted to a literal type, so `Minimum<3>` is written as a type reference with the literal.
|
|
88
|
+
* @evidence contracts/common.md#clear-and-simple-design One function delegating the literal building.
|
|
89
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The tag name and the argument come from the caller.
|
|
90
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the reference.
|
|
91
|
+
*/
|
|
42
92
|
public tag(type: string, arg?: any): ts.TypeReferenceNode {
|
|
43
93
|
const instance: string = this.external({
|
|
44
94
|
type: "instance",
|
|
@@ -51,6 +101,15 @@ export class NestiaMigrateImportProgrammer {
|
|
|
51
101
|
);
|
|
52
102
|
}
|
|
53
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Returns the import statements: the external imports, a blank line when both
|
|
106
|
+
* kinds exist, and the type-only DTO imports.
|
|
107
|
+
*
|
|
108
|
+
* @evidence contracts/common.md#principled-implementation DTO names are grouped by the specifier that `dtoPath` returns, a name equal to the current file is skipped so a file never imports itself, and package specifiers merge into one clause.
|
|
109
|
+
* @evidence contracts/common.md#clear-and-simple-design One function with two emit sections.
|
|
110
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The specifier rule is the caller's.
|
|
111
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result and the self-import rule.
|
|
112
|
+
*/
|
|
54
113
|
public toStatements(
|
|
55
114
|
dtoPath: (name: string) => string,
|
|
56
115
|
current?: string,
|
|
@@ -114,10 +173,32 @@ export class NestiaMigrateImportProgrammer {
|
|
|
114
173
|
];
|
|
115
174
|
}
|
|
116
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Types of the importer: the properties of an external import request.
|
|
178
|
+
*
|
|
179
|
+
* @evidence contracts/common.md#principled-implementation The record names the import kind, the library, and the name.
|
|
180
|
+
* @evidence contracts/common.md#clear-and-simple-design One namespace with one interface.
|
|
181
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It contains types only.
|
|
182
|
+
* @evidence contracts/common.md#meaningful-documentation The comment names its content.
|
|
183
|
+
*/
|
|
117
184
|
export namespace MigrateImportProgrammer {
|
|
185
|
+
/**
|
|
186
|
+
* An external import request: `default` or `instance`, the library, and the
|
|
187
|
+
* name.
|
|
188
|
+
*
|
|
189
|
+
* @evidence contracts/common.md#principled-implementation The kind selects between the default clause and a named import.
|
|
190
|
+
* @evidence contracts/common.md#clear-and-simple-design A three-field record.
|
|
191
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
192
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states each field.
|
|
193
|
+
*/
|
|
118
194
|
export interface IProps {
|
|
195
|
+
/** Select the default export or a named import. */
|
|
119
196
|
type: "default" | "instance";
|
|
197
|
+
|
|
198
|
+
/** Module specifier emitted in the import declaration. */
|
|
120
199
|
library: string;
|
|
200
|
+
|
|
201
|
+
/** Requested binding; named imports use its leading dotted segment. */
|
|
121
202
|
name: string;
|
|
122
203
|
}
|
|
123
204
|
}
|
|
@@ -8,13 +8,43 @@ import { FilePrinter } from "../utils/FilePrinter";
|
|
|
8
8
|
import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
|
|
9
9
|
import { NestiaMigrateNestMethodProgrammer } from "./NestiaMigrateNestMethodProgrammer";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Generates the source of one NestJS controller.
|
|
13
|
+
*
|
|
14
|
+
* @evidence contracts/common.md#principled-implementation The controller class is decorated with `@Controller` and its path, each route becomes a method written by the configured method programmer or the default one, and the DTO types are imported by package name because they live in the API package.
|
|
15
|
+
* @evidence contracts/common.md#clear-and-simple-design One function; the method programmer is replaceable through the configuration.
|
|
16
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The replaceable programmer is a documented extension point.
|
|
17
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what is generated.
|
|
18
|
+
*/
|
|
11
19
|
export namespace NestiaMigrateNestControllerProgrammer {
|
|
20
|
+
/**
|
|
21
|
+
* The input of one controller: the configuration, the components, and the
|
|
22
|
+
* controller.
|
|
23
|
+
*
|
|
24
|
+
* @evidence contracts/common.md#principled-implementation The record holds exactly what the generation needs.
|
|
25
|
+
* @evidence contracts/common.md#clear-and-simple-design A flat record.
|
|
26
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
27
|
+
* @evidence contracts/common.md#meaningful-documentation The comment lists the fields.
|
|
28
|
+
*/
|
|
12
29
|
export interface IProps {
|
|
30
|
+
/** Generation options and an optional controller-method writer. */
|
|
13
31
|
config: INestiaMigrateConfig;
|
|
32
|
+
|
|
33
|
+
/** Schemas needed by generated controller method types. */
|
|
14
34
|
components: OpenApi.IComponents;
|
|
35
|
+
|
|
36
|
+
/** Controller name, router prefix and grouped operations. */
|
|
15
37
|
controller: INestiaMigrateController;
|
|
16
38
|
}
|
|
17
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Returns the statements of a controller file.
|
|
42
|
+
*
|
|
43
|
+
* @evidence contracts/common.md#principled-implementation Blank lines separate the methods, and the imports come first.
|
|
44
|
+
* @evidence contracts/common.md#clear-and-simple-design One function.
|
|
45
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The content follows the controller.
|
|
46
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result.
|
|
47
|
+
*/
|
|
18
48
|
export const write = (props: IProps): ts.Statement[] => {
|
|
19
49
|
const importer: NestiaMigrateImportProgrammer =
|
|
20
50
|
new NestiaMigrateImportProgrammer();
|
|
@@ -2,6 +2,7 @@ import { SyntaxKind, factory } from "@ttsc/factory";
|
|
|
2
2
|
import { IHttpMigrateRoute } from "@typia/interface";
|
|
3
3
|
import { OpenApi } from "typia";
|
|
4
4
|
|
|
5
|
+
import { NestiaMigrateControllerAnalyzer } from "../analyzers/NestiaMigrateControllerAnalyzer";
|
|
5
6
|
import { ExpressionFactory } from "../factories/ExpressionFactory";
|
|
6
7
|
import { IdentifierFactory } from "../factories/IdentifierFactory";
|
|
7
8
|
import { LiteralFactory } from "../factories/LiteralFactory";
|
|
@@ -10,19 +11,55 @@ import ts from "../internal/ts";
|
|
|
10
11
|
import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
|
|
11
12
|
import { INestiaMigrateController } from "../structures/INestiaMigrateController";
|
|
12
13
|
import { FilePrinter } from "../utils/FilePrinter";
|
|
14
|
+
import { RequestBody } from "../utils/RequestBody";
|
|
13
15
|
import { StringUtil } from "../utils/StringUtil";
|
|
16
|
+
import { SuccessStatus } from "../utils/SuccessStatus";
|
|
14
17
|
import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
|
|
15
18
|
import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Generates the controller method of one route.
|
|
22
|
+
*
|
|
23
|
+
* @evidence contracts/common.md#principled-implementation The method carries `TypedRoute`, `TypedException`, `HumanRoute`, and example decorators as the route requires, one parameter per path, header, query, and body input with the matching typed decorator, and a body that mentions each parameter and returns `typia.random` of the response type.
|
|
24
|
+
* @evidence contracts/common.md#clear-and-simple-design One entry function and private writers for the description, the decorators, and the parameters.
|
|
25
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The output derives from the route; the body is a stub that returns random data because the document does not define the behavior.
|
|
26
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what is generated.
|
|
27
|
+
*/
|
|
17
28
|
export namespace NestiaMigrateNestMethodProgrammer {
|
|
29
|
+
/**
|
|
30
|
+
* The input of one method: the configuration, the components, the importer,
|
|
31
|
+
* the controller, and the route.
|
|
32
|
+
*
|
|
33
|
+
* @evidence contracts/common.md#principled-implementation The record holds exactly what the generation needs.
|
|
34
|
+
* @evidence contracts/common.md#clear-and-simple-design A flat record.
|
|
35
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
36
|
+
* @evidence contracts/common.md#meaningful-documentation The comment lists the fields.
|
|
37
|
+
*/
|
|
18
38
|
export interface IContext {
|
|
39
|
+
/** Generation options, including the author tag used on the handler. */
|
|
19
40
|
config: INestiaMigrateConfig;
|
|
41
|
+
|
|
42
|
+
/** Component schemas referenced by request and response types. */
|
|
20
43
|
components: OpenApi.IComponents;
|
|
44
|
+
|
|
45
|
+
/** Controller-file import collector shared by all its methods. */
|
|
21
46
|
importer: NestiaMigrateImportProgrammer;
|
|
47
|
+
|
|
48
|
+
/** Controller prefix removed from this operation's router path. */
|
|
22
49
|
controller: INestiaMigrateController;
|
|
50
|
+
|
|
51
|
+
/** Analyzed operation supplying method, schemas and examples. */
|
|
23
52
|
route: IHttpMigrateRoute;
|
|
24
53
|
}
|
|
25
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Returns the method declaration of a route.
|
|
57
|
+
*
|
|
58
|
+
* @evidence contracts/common.md#principled-implementation The decorators and the parameters follow the route's HTTP method, path relative to the controller, and inputs.
|
|
59
|
+
* @evidence contracts/common.md#clear-and-simple-design One function composing the private writers.
|
|
60
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The method follows the route.
|
|
61
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result.
|
|
62
|
+
*/
|
|
26
63
|
export const write = (ctx: IContext): ts.MethodDeclaration => {
|
|
27
64
|
const output: ts.TypeNode = ctx.route.success
|
|
28
65
|
? NestiaMigrateSchemaProgrammer.write({
|
|
@@ -121,7 +158,9 @@ export namespace NestiaMigrateNestMethodProgrammer {
|
|
|
121
158
|
);
|
|
122
159
|
|
|
123
160
|
// ROUTER
|
|
124
|
-
const localPath: string =
|
|
161
|
+
const localPath: string = NestiaMigrateControllerAnalyzer.routePath(
|
|
162
|
+
ctx.route,
|
|
163
|
+
)
|
|
125
164
|
.slice(ctx.controller.path.length)
|
|
126
165
|
.split("/")
|
|
127
166
|
.filter((str) => !!str.length)
|
|
@@ -139,35 +178,43 @@ export namespace NestiaMigrateNestMethodProgrammer {
|
|
|
139
178
|
: undefined,
|
|
140
179
|
),
|
|
141
180
|
);
|
|
181
|
+
// a vanilla NestJS method decorator, relative to the controller like the
|
|
182
|
+
// nestia ones: the document's full path would be joined onto the
|
|
183
|
+
// controller's again
|
|
184
|
+
const nest = (method: string) =>
|
|
185
|
+
factory.createDecorator(
|
|
186
|
+
factory.createCallExpression(
|
|
187
|
+
external("@nestjs/common", method),
|
|
188
|
+
[],
|
|
189
|
+
localPath.length
|
|
190
|
+
? [factory.createStringLiteral(localPath)]
|
|
191
|
+
: undefined,
|
|
192
|
+
),
|
|
193
|
+
);
|
|
142
194
|
if (ctx.route.success?.["x-nestia-encrypted"])
|
|
143
195
|
decorators.push(router("EncryptedRoute"));
|
|
144
196
|
else if (ctx.route.success?.type === "text/plain")
|
|
145
|
-
decorators.push(
|
|
146
|
-
factory.createDecorator(
|
|
147
|
-
factory.createCallExpression(
|
|
148
|
-
external("@nestjs/common", StringUtil.capitalize(ctx.route.method)),
|
|
149
|
-
[],
|
|
150
|
-
[factory.createStringLiteral(ctx.route.path)],
|
|
151
|
-
),
|
|
152
|
-
),
|
|
153
|
-
);
|
|
197
|
+
decorators.push(nest(StringUtil.capitalize(ctx.route.method)));
|
|
154
198
|
else if (ctx.route.success?.type === "application/x-www-form-urlencoded")
|
|
155
199
|
decorators.push(router("TypedQuery"));
|
|
156
|
-
else if (ctx.route.method === "head")
|
|
200
|
+
else if (ctx.route.method === "head") decorators.push(nest("Head"));
|
|
201
|
+
else if (
|
|
202
|
+
ctx.route.success === null ||
|
|
203
|
+
ctx.route.success?.type === "application/json"
|
|
204
|
+
)
|
|
205
|
+
decorators.push(router("TypedRoute"));
|
|
206
|
+
// NestJS answers 201 for POST and 200 otherwise
|
|
207
|
+
const status: number | null = SuccessStatus.of(ctx.route);
|
|
208
|
+
if (status !== null && status !== SuccessStatus.nest(ctx.route))
|
|
157
209
|
decorators.push(
|
|
158
210
|
factory.createDecorator(
|
|
159
211
|
factory.createCallExpression(
|
|
160
|
-
external("@nestjs/common", "
|
|
161
|
-
|
|
162
|
-
[
|
|
212
|
+
external("@nestjs/common", "HttpCode"),
|
|
213
|
+
undefined,
|
|
214
|
+
[ExpressionFactory.number(status)],
|
|
163
215
|
),
|
|
164
216
|
),
|
|
165
217
|
);
|
|
166
|
-
else if (
|
|
167
|
-
ctx.route.success === null ||
|
|
168
|
-
ctx.route.success?.type === "application/json"
|
|
169
|
-
)
|
|
170
|
-
decorators.push(router("TypedRoute"));
|
|
171
218
|
for (const [key, value] of Object.entries(ctx.route.exceptions ?? {}))
|
|
172
219
|
decorators.push(
|
|
173
220
|
factory.createDecorator(
|
|
@@ -291,11 +338,7 @@ export namespace NestiaMigrateNestMethodProgrammer {
|
|
|
291
338
|
: [],
|
|
292
339
|
})(ctx.components)(ctx.importer)({
|
|
293
340
|
schema: ctx.route.body.schema,
|
|
294
|
-
required:
|
|
295
|
-
(ctx.route.body.type === "application/json" ||
|
|
296
|
-
ctx.route.body.type === "text/plain") &&
|
|
297
|
-
ctx.route.operation().requestBody?.required === false
|
|
298
|
-
),
|
|
341
|
+
required: RequestBody.optional(ctx.route) === false,
|
|
299
342
|
example: ctx.route.body.media().example,
|
|
300
343
|
examples: ctx.route.body.media().examples,
|
|
301
344
|
}),
|
|
@@ -380,8 +423,10 @@ export namespace NestiaMigrateNestMethodProgrammer {
|
|
|
380
423
|
),
|
|
381
424
|
]
|
|
382
425
|
: []),
|
|
383
|
-
...Object.entries(media.examples ?? {}).
|
|
384
|
-
|
|
426
|
+
...Object.entries(media.examples ?? {}).flatMap(([key, example]) => {
|
|
427
|
+
const value: { value: unknown } | null = exampleValue(example);
|
|
428
|
+
if (value === null) return [];
|
|
429
|
+
return factory.createDecorator(
|
|
385
430
|
factory.createCallExpression(
|
|
386
431
|
IdentifierFactory.access(
|
|
387
432
|
factory.createIdentifier(
|
|
@@ -394,9 +439,57 @@ export namespace NestiaMigrateNestMethodProgrammer {
|
|
|
394
439
|
kind,
|
|
395
440
|
),
|
|
396
441
|
[],
|
|
397
|
-
[
|
|
442
|
+
[
|
|
443
|
+
factory.createStringLiteral(key),
|
|
444
|
+
LiteralFactory.write(value.value),
|
|
445
|
+
],
|
|
398
446
|
),
|
|
399
|
-
)
|
|
400
|
-
),
|
|
447
|
+
);
|
|
448
|
+
}),
|
|
401
449
|
];
|
|
402
450
|
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* The value a named example stands for, or `null` when it names none.
|
|
454
|
+
*
|
|
455
|
+
* OpenAPI names examples with Example Objects, whose `value` (or, since 3.2,
|
|
456
|
+
* `dataValue`) holds the value, and a `$ref` to one arrives resolved. Documents
|
|
457
|
+
* from earlier nestia versions held the values themselves, so an object is read
|
|
458
|
+
* as an Example Object only when it is one: it has one of the value fields, and
|
|
459
|
+
* every other key is an Example Object field or an extension. A raw value of
|
|
460
|
+
* exactly that shape is ambiguous and is read as an Example Object, as a
|
|
461
|
+
* conforming document means it. An Example Object that only points at its value
|
|
462
|
+
* (`externalValue`) or only serializes it (`serializedValue`) gives
|
|
463
|
+
* `SwaggerExample` nothing to hold.
|
|
464
|
+
*/
|
|
465
|
+
const exampleValue = (example: unknown): { value: unknown } | null => {
|
|
466
|
+
if (isExampleObject(example) === false) return { value: example };
|
|
467
|
+
const record = example as Record<string, unknown>;
|
|
468
|
+
if (Object.prototype.hasOwnProperty.call(record, "value"))
|
|
469
|
+
return { value: record.value };
|
|
470
|
+
if (Object.prototype.hasOwnProperty.call(record, "dataValue"))
|
|
471
|
+
return { value: record.dataValue };
|
|
472
|
+
return null;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const isExampleObject = (example: unknown): boolean =>
|
|
476
|
+
typeof example === "object" &&
|
|
477
|
+
example !== null &&
|
|
478
|
+
Array.isArray(example) === false &&
|
|
479
|
+
VALUE_KEYS.some((key) =>
|
|
480
|
+
Object.prototype.hasOwnProperty.call(example, key),
|
|
481
|
+
) &&
|
|
482
|
+
Object.keys(example).every(
|
|
483
|
+
(key) =>
|
|
484
|
+
VALUE_KEYS.includes(key) ||
|
|
485
|
+
key === "summary" ||
|
|
486
|
+
key === "description" ||
|
|
487
|
+
key.startsWith("x-"),
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
const VALUE_KEYS: string[] = [
|
|
491
|
+
"value",
|
|
492
|
+
"dataValue",
|
|
493
|
+
"serializedValue",
|
|
494
|
+
"externalValue",
|
|
495
|
+
];
|
|
@@ -4,7 +4,23 @@ import ts from "../internal/ts";
|
|
|
4
4
|
import { INestiaMigrateController } from "../structures/INestiaMigrateController";
|
|
5
5
|
import { FilePrinter } from "../utils/FilePrinter";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Generates the NestJS module that lists the controllers.
|
|
9
|
+
*
|
|
10
|
+
* @evidence contracts/common.md#principled-implementation The module imports every controller from its location and lists them in the `controllers` array of a decorated class.
|
|
11
|
+
* @evidence contracts/common.md#clear-and-simple-design One function and one private import builder.
|
|
12
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The controllers follow the analysis.
|
|
13
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what is generated.
|
|
14
|
+
*/
|
|
7
15
|
export namespace NestiaMigrateNestModuleProgrammer {
|
|
16
|
+
/**
|
|
17
|
+
* Returns the statements of the module file.
|
|
18
|
+
*
|
|
19
|
+
* @evidence contracts/common.md#principled-implementation The import paths turn the `src/` prefix of a controller location into `./`, so the module can import from its own directory.
|
|
20
|
+
* @evidence contracts/common.md#clear-and-simple-design One function.
|
|
21
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The names follow the controllers.
|
|
22
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result.
|
|
23
|
+
*/
|
|
8
24
|
export const write = (
|
|
9
25
|
controllers: INestiaMigrateController[],
|
|
10
26
|
): ts.Statement[] => [
|
|
@@ -10,7 +10,24 @@ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
|
|
|
10
10
|
import { NestiaMigrateNestControllerProgrammer } from "./NestiaMigrateNestControllerProgrammer";
|
|
11
11
|
import { NestiaMigrateNestModuleProgrammer } from "./NestiaMigrateNestModuleProgrammer";
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Generates the NestJS side of a monorepo project: the module, the controllers,
|
|
15
|
+
* and the DTO structures.
|
|
16
|
+
*
|
|
17
|
+
* @evidence contracts/common.md#principled-implementation The controllers come from the analyzer, each DTO tree becomes a structure file, and a barrel file re-exports every non-empty structure file so the template's module keeps working.
|
|
18
|
+
* @evidence contracts/common.md#clear-and-simple-design One public function and private helpers for the DTO files and the barrel.
|
|
19
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The layout follows the analysis.
|
|
20
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what is generated.
|
|
21
|
+
*/
|
|
13
22
|
export namespace NestiaMigrateNestProgrammer {
|
|
23
|
+
/**
|
|
24
|
+
* Returns the map from file path to content of the NestJS files.
|
|
25
|
+
*
|
|
26
|
+
* @evidence contracts/common.md#principled-implementation The barrel is computed from the generated structure files, sorted by name, so its content is deterministic.
|
|
27
|
+
* @evidence contracts/common.md#clear-and-simple-design One function.
|
|
28
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The names follow the document.
|
|
29
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result.
|
|
30
|
+
*/
|
|
14
31
|
export const write = (
|
|
15
32
|
context: INestiaMigrateContext,
|
|
16
33
|
): Record<string, string> => {
|
|
@@ -2,17 +2,33 @@ import { SyntaxKind, factory } from "@ttsc/factory";
|
|
|
2
2
|
import { NamingConvention, OpenApiTypeChecker } from "@typia/utils";
|
|
3
3
|
import type { OpenApi } from "typia";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { SUPPORTED_STRING_FORMATS } from "../factories/SupportedStringFormats";
|
|
6
6
|
import { TypeFactory } from "../factories/TypeFactory";
|
|
7
7
|
import ts from "../internal/ts";
|
|
8
8
|
import { FilePrinter } from "../utils/FilePrinter";
|
|
9
9
|
import { StringUtil } from "../utils/StringUtil";
|
|
10
10
|
import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Generates the TypeScript type of an OpenAPI schema.
|
|
14
|
+
*
|
|
15
|
+
* @evidence contracts/common.md#principled-implementation The schema kind is decided by the type checker of `@typia/utils`, and each kind becomes a type: constants as literal types, numbers, integers, and strings with their constraints as `typia.tags` intersections, arrays, tuples, objects, references, and unions, with `any` for an unknown schema.
|
|
16
|
+
* @evidence contracts/common.md#clear-and-simple-design One entry function that dispatches to one private writer per kind.
|
|
17
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The dispatch follows the schema kinds of OpenAPI, and no schema name is special-cased.
|
|
18
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what is generated.
|
|
19
|
+
*/
|
|
12
20
|
export namespace NestiaMigrateSchemaProgrammer {
|
|
13
21
|
/* -----------------------------------------------------------
|
|
14
22
|
FACADE
|
|
15
23
|
----------------------------------------------------------- */
|
|
24
|
+
/**
|
|
25
|
+
* Returns the type node of a schema.
|
|
26
|
+
*
|
|
27
|
+
* @evidence contracts/common.md#principled-implementation An unknown schema is `any`, a `oneOf` becomes a TypeScript union, integer formats outside the supported four use the migration default `int64`, a binary string becomes `File`, and known string formats become typia tags. TypeScript unions do not encode oneOf exclusivity, and unsupported formats impose no generated constraint.
|
|
28
|
+
* @evidence contracts/common.md#clear-and-simple-design One function with an ordered chain of schema kind tests.
|
|
29
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Schema-kind dispatch applies uniformly; the int64 fallback and supported-format table are generator policies rather than constraints supplied by the document.
|
|
30
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the result.
|
|
31
|
+
*/
|
|
16
32
|
export const write = (props: {
|
|
17
33
|
components: OpenApi.IComponents;
|
|
18
34
|
importer: NestiaMigrateImportProgrammer;
|
|
@@ -123,12 +139,29 @@ export namespace NestiaMigrateSchemaProgrammer {
|
|
|
123
139
|
writeNumeric({
|
|
124
140
|
factory: () => [
|
|
125
141
|
TypeFactory.keyword("number"),
|
|
126
|
-
props.importer.tag("Type",
|
|
142
|
+
props.importer.tag("Type", integerType(props.schema)),
|
|
127
143
|
],
|
|
128
144
|
importer: props.importer,
|
|
129
145
|
schema: props.schema,
|
|
130
146
|
});
|
|
131
147
|
|
|
148
|
+
/**
|
|
149
|
+
* The typia integer type admitting what the schema admits: its own `format`
|
|
150
|
+
* when it names one typia has, else `int64`, as an integer schema without a
|
|
151
|
+
* format admits any integer.
|
|
152
|
+
*/
|
|
153
|
+
const integerType = (
|
|
154
|
+
schema: OpenApi.IJsonSchema.IInteger,
|
|
155
|
+
): "int32" | "uint32" | "int64" | "uint64" => {
|
|
156
|
+
const format: unknown = (schema as { format?: unknown }).format;
|
|
157
|
+
return format === "int32" ||
|
|
158
|
+
format === "uint32" ||
|
|
159
|
+
format === "int64" ||
|
|
160
|
+
format === "uint64"
|
|
161
|
+
? format
|
|
162
|
+
: "int64";
|
|
163
|
+
};
|
|
164
|
+
|
|
132
165
|
const writeNumber = (props: {
|
|
133
166
|
importer: NestiaMigrateImportProgrammer;
|
|
134
167
|
schema: OpenApi.IJsonSchema.INumber;
|
|
@@ -147,19 +180,19 @@ export namespace NestiaMigrateSchemaProgrammer {
|
|
|
147
180
|
const intersection: ts.TypeNode[] = props.factory();
|
|
148
181
|
if (props.schema.default !== undefined)
|
|
149
182
|
intersection.push(props.importer.tag("Default", props.schema.default));
|
|
183
|
+
// the emended schema holds each bound as a number, as OpenAPI 3.1 does;
|
|
184
|
+
// an OpenAPI 3.0 boolean `exclusiveMinimum` is converted into that form
|
|
150
185
|
if (props.schema.minimum !== undefined)
|
|
186
|
+
intersection.push(props.importer.tag("Minimum", props.schema.minimum));
|
|
187
|
+
if (typeof props.schema.exclusiveMinimum === "number")
|
|
151
188
|
intersection.push(
|
|
152
|
-
props.importer.tag(
|
|
153
|
-
props.schema.exclusiveMinimum ? "ExclusiveMinimum" : "Minimum",
|
|
154
|
-
props.schema.minimum,
|
|
155
|
-
),
|
|
189
|
+
props.importer.tag("ExclusiveMinimum", props.schema.exclusiveMinimum),
|
|
156
190
|
);
|
|
157
191
|
if (props.schema.maximum !== undefined)
|
|
192
|
+
intersection.push(props.importer.tag("Maximum", props.schema.maximum));
|
|
193
|
+
if (typeof props.schema.exclusiveMaximum === "number")
|
|
158
194
|
intersection.push(
|
|
159
|
-
props.importer.tag(
|
|
160
|
-
props.schema.exclusiveMaximum ? "ExclusiveMaximum" : "Maximum",
|
|
161
|
-
props.schema.maximum,
|
|
162
|
-
),
|
|
195
|
+
props.importer.tag("ExclusiveMaximum", props.schema.exclusiveMaximum),
|
|
163
196
|
);
|
|
164
197
|
if (props.schema.multipleOf !== undefined)
|
|
165
198
|
intersection.push(
|
|
@@ -192,8 +225,7 @@ export namespace NestiaMigrateSchemaProgrammer {
|
|
|
192
225
|
intersection.push(props.importer.tag("Pattern", props.schema.pattern));
|
|
193
226
|
if (
|
|
194
227
|
props.schema.format !== undefined &&
|
|
195
|
-
(
|
|
196
|
-
undefined
|
|
228
|
+
SUPPORTED_STRING_FORMATS.has(props.schema.format)
|
|
197
229
|
)
|
|
198
230
|
intersection.push(props.importer.tag("Format", props.schema.format));
|
|
199
231
|
if (props.schema.contentMediaType !== undefined)
|
|
@@ -250,11 +282,13 @@ export namespace NestiaMigrateSchemaProgrammer {
|
|
|
250
282
|
props.schema.additionalItems !== null
|
|
251
283
|
? [
|
|
252
284
|
factory.createRestTypeNode(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
285
|
+
factory.createArrayTypeNode(
|
|
286
|
+
write({
|
|
287
|
+
components: props.components,
|
|
288
|
+
importer: props.importer,
|
|
289
|
+
schema: props.schema.additionalItems,
|
|
290
|
+
}),
|
|
291
|
+
),
|
|
258
292
|
),
|
|
259
293
|
]
|
|
260
294
|
: props.schema.additionalItems === true
|
|
@@ -299,7 +333,8 @@ export namespace NestiaMigrateSchemaProgrammer {
|
|
|
299
333
|
schema: props.schema.additionalProperties as OpenApi.IJsonSchema,
|
|
300
334
|
}),
|
|
301
335
|
]);
|
|
302
|
-
|
|
336
|
+
// `properties` is a record, which has no length
|
|
337
|
+
return Object.keys(props.schema.properties ?? {}).length !== 0 &&
|
|
303
338
|
typeof props.schema.additionalProperties === "object"
|
|
304
339
|
? factory.createIntersectionTypeNode([regular(), dynamic()])
|
|
305
340
|
: typeof props.schema.additionalProperties === "object"
|
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
import ts from "../internal/ts";
|
|
2
2
|
import { NestiaMigrateNestMethodProgrammer } from "../programmers/NestiaMigrateNestMethodProgrammer";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Options of the migration: simulation, e2e tests, the package name, keyword
|
|
6
|
+
* parameters, the author tag, and a replaceable controller method programmer.
|
|
7
|
+
*
|
|
8
|
+
* @evidence contracts/common.md#principled-implementation The flags choose which parts are generated and the parameter style, the package name replaces the placeholder in every file, and the programmer option lets a caller generate controller methods differently.
|
|
9
|
+
* @evidence contracts/common.md#clear-and-simple-design A flat record whose optional members are the extension points.
|
|
10
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
11
|
+
* @evidence contracts/common.md#meaningful-documentation The comment lists the options.
|
|
12
|
+
*/
|
|
4
13
|
export interface INestiaMigrateConfig {
|
|
14
|
+
/** Include runtime request validation and random-response simulator members. */
|
|
5
15
|
simulate: boolean;
|
|
16
|
+
|
|
17
|
+
/** Emit a generated test feature for each migrated operation. */
|
|
6
18
|
e2e: boolean;
|
|
19
|
+
|
|
20
|
+
/** Replace the template package placeholder; omission retains the placeholder. */
|
|
7
21
|
package?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Use a props object when true; false or omission selects positional
|
|
25
|
+
* parameters.
|
|
26
|
+
*/
|
|
8
27
|
keyword?: boolean;
|
|
28
|
+
|
|
29
|
+
/** Override the generated declaration attribution tag and its text. */
|
|
9
30
|
author?: {
|
|
10
31
|
tag: string;
|
|
11
32
|
value: string;
|
|
12
33
|
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Replace controller method emission while retaining the surrounding
|
|
37
|
+
* controller.
|
|
38
|
+
*/
|
|
13
39
|
programmer?: {
|
|
14
40
|
controllerMethod?: (
|
|
15
41
|
ctx: NestiaMigrateNestMethodProgrammer.IContext,
|
|
@@ -2,8 +2,25 @@ import { IHttpMigrateApplication } from "@typia/interface";
|
|
|
2
2
|
|
|
3
3
|
import { INestiaMigrateConfig } from "./INestiaMigrateConfig";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The shared input of the programmers: the mode, the analyzed application, and
|
|
7
|
+
* the configuration.
|
|
8
|
+
*
|
|
9
|
+
* @evidence contracts/common.md#principled-implementation The record is built once per migration, so every programmer sees the same routes and options.
|
|
10
|
+
* @evidence contracts/common.md#clear-and-simple-design A three-member record.
|
|
11
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
12
|
+
* @evidence contracts/common.md#meaningful-documentation The comment lists the members.
|
|
13
|
+
*/
|
|
5
14
|
export interface INestiaMigrateContext {
|
|
15
|
+
/** Select backend/API workspace output or a standalone SDK project. */
|
|
6
16
|
mode: "nest" | "sdk";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generation-local route/accessor copies backed by the shared analyzed
|
|
20
|
+
* document.
|
|
21
|
+
*/
|
|
7
22
|
application: IHttpMigrateApplication;
|
|
23
|
+
|
|
24
|
+
/** Options used consistently by each programmer in this generation. */
|
|
8
25
|
config: INestiaMigrateConfig;
|
|
9
26
|
}
|