@nestia/migrate 12.0.0-rc.2 → 12.0.0-rc.3

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.
Files changed (66) hide show
  1. package/LICENSE +21 -21
  2. package/lib/_virtual/_tstl.mjs +2 -2
  3. package/lib/_virtual/index.mjs +2 -2
  4. package/lib/_virtual/index2.mjs +2 -2
  5. package/lib/_virtual/index3.mjs +2 -2
  6. package/lib/archivers/NestiaMigrateFileArchiver2.mjs +2 -2
  7. package/lib/archivers/NestiaMigrateFileArchiver2.mjs.map +1 -1
  8. package/lib/bundles/NEST_TEMPLATE.js +47 -47
  9. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  10. package/lib/bundles/NEST_TEMPLATE2.mjs +47 -47
  11. package/lib/bundles/NEST_TEMPLATE2.mjs.map +1 -1
  12. package/lib/bundles/SDK_TEMPLATE.js +20 -20
  13. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  14. package/lib/bundles/SDK_TEMPLATE2.mjs +20 -20
  15. package/lib/bundles/SDK_TEMPLATE2.mjs.map +1 -1
  16. package/lib/index2.mjs +1 -1
  17. package/lib/module2.mjs +2 -2
  18. package/lib/programmers/NestiaMigrateApiProgrammer2.mjs +4 -4
  19. package/lib/programmers/NestiaMigrateApiProgrammer2.mjs.map +1 -1
  20. package/lib/programmers/index2.mjs +1 -1
  21. package/lib/structures/index2.mjs +1 -1
  22. package/package.json +6 -6
  23. package/src/NestiaMigrateApplication.ts +196 -196
  24. package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +51 -51
  25. package/src/archivers/NestiaMigrateFileArchiver.ts +28 -28
  26. package/src/bundles/NEST_TEMPLATE.ts +47 -47
  27. package/src/bundles/SDK_TEMPLATE.ts +20 -20
  28. package/src/executable/NestiaMigrateCommander.ts +115 -115
  29. package/src/executable/NestiaMigrateInquirer.ts +106 -106
  30. package/src/executable/bundle.js +323 -349
  31. package/src/executable/migrate.ts +7 -7
  32. package/src/factories/ExpressionFactory.ts +23 -23
  33. package/src/factories/FormatCheatSheet.ts +71 -71
  34. package/src/factories/IdentifierFactory.ts +84 -84
  35. package/src/factories/LiteralFactory.ts +54 -54
  36. package/src/factories/StatementFactory.ts +56 -56
  37. package/src/factories/TypeFactory.ts +27 -27
  38. package/src/factories/TypeLiteralFactory.ts +62 -62
  39. package/src/index.ts +4 -4
  40. package/src/internal/ts.ts +75 -75
  41. package/src/module.ts +6 -6
  42. package/src/programmers/NestiaMigrateApiFileProgrammer.ts +55 -55
  43. package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +358 -358
  44. package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +511 -511
  45. package/src/programmers/NestiaMigrateApiProgrammer.ts +108 -108
  46. package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +309 -309
  47. package/src/programmers/NestiaMigrateApiStartProgrammer.ts +198 -198
  48. package/src/programmers/NestiaMigrateDtoProgrammer.ts +117 -117
  49. package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +155 -155
  50. package/src/programmers/NestiaMigrateE2eProgrammer.ts +48 -48
  51. package/src/programmers/NestiaMigrateImportProgrammer.ts +119 -119
  52. package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +70 -70
  53. package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +402 -402
  54. package/src/programmers/NestiaMigrateNestModuleProgrammer.ts +64 -64
  55. package/src/programmers/NestiaMigrateNestProgrammer.ts +89 -89
  56. package/src/programmers/NestiaMigrateSchemaProgrammer.ts +475 -475
  57. package/src/programmers/index.ts +15 -15
  58. package/src/structures/INestiaMigrateConfig.ts +19 -19
  59. package/src/structures/INestiaMigrateContext.ts +9 -9
  60. package/src/structures/INestiaMigrateController.ts +8 -8
  61. package/src/structures/INestiaMigrateFile.ts +5 -5
  62. package/src/structures/index.ts +4 -4
  63. package/src/utils/FilePrinter.ts +44 -44
  64. package/src/utils/MapUtil.ts +13 -13
  65. package/src/utils/StringUtil.ts +109 -109
  66. package/README.md +0 -93
@@ -1,198 +1,198 @@
1
- import { NodeFlags, SyntaxKind, factory } from "@ttsc/factory";
2
- import { IHttpMigrateRoute } from "@typia/interface";
3
-
4
- import { IdentifierFactory } from "../factories/IdentifierFactory";
5
- import { StatementFactory } from "../factories/StatementFactory";
6
- import ts from "../internal/ts";
7
- import { INestiaMigrateContext } from "../structures/INestiaMigrateContext";
8
- import { FilePrinter } from "../utils/FilePrinter";
9
- import { NestiaMigrateE2eFunctionProgrammer } from "./NestiaMigrateE2eFileProgrammer";
10
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
-
12
- export namespace NestiaMigrateApiStartProgrammer {
13
- export const write = (
14
- context: INestiaMigrateContext,
15
- ): Record<string, string> => {
16
- const importer: NestiaMigrateImportProgrammer =
17
- new NestiaMigrateImportProgrammer();
18
- const main: ts.VariableStatement = writeMain(
19
- context,
20
- importer,
21
- pick(context.application.routes),
22
- );
23
- const statements: ts.Statement[] = [
24
- ...importer.toStatements(
25
- (name) => `@ORGANIZATION/PROJECT-api/lib/structures/${name}`,
26
- ),
27
- FilePrinter.newLine(),
28
- factory.createImportDeclaration(
29
- undefined,
30
- factory.createImportClause(
31
- false,
32
- undefined,
33
- factory.createNamedImports([
34
- factory.createImportSpecifier(
35
- false,
36
- undefined,
37
- factory.createIdentifier("TestGlobal"),
38
- ),
39
- ]),
40
- ),
41
- factory.createStringLiteral("./TestGlobal"),
42
- ),
43
- FilePrinter.newLine(),
44
- main,
45
- factory.createExpressionStatement(writeStarter()),
46
- ];
47
- return {
48
- "test/start.ts": FilePrinter.write({ statements }),
49
- };
50
- };
51
-
52
- const writeMain = (
53
- ctx: INestiaMigrateContext,
54
- importer: NestiaMigrateImportProgrammer,
55
- route: IHttpMigrateRoute,
56
- ): ts.VariableStatement =>
57
- StatementFactory.constant({
58
- name: "main",
59
- value: factory.createArrowFunction(
60
- [factory.createToken(SyntaxKind.AsyncKeyword)],
61
- undefined,
62
- [],
63
- undefined,
64
- undefined,
65
- factory.createBlock(
66
- [
67
- writeConnection(ctx, importer),
68
- ...NestiaMigrateE2eFunctionProgrammer.writeBody({
69
- config: ctx.config,
70
- components: ctx.application.document().components,
71
- importer,
72
- route,
73
- }),
74
- ],
75
- true,
76
- ),
77
- ),
78
- });
79
-
80
- const writeConnection = (
81
- ctx: INestiaMigrateContext,
82
- importer: NestiaMigrateImportProgrammer,
83
- ): ts.VariableStatement =>
84
- factory.createVariableStatement(
85
- undefined,
86
- factory.createVariableDeclarationList(
87
- [
88
- factory.createVariableDeclaration(
89
- "connection",
90
- undefined,
91
- factory.createTypeReferenceNode(
92
- factory.createQualifiedName(
93
- factory.createIdentifier(
94
- importer.external({
95
- type: "default",
96
- library: "@ORGANIZATION/PROJECT-api",
97
- name: "api",
98
- }),
99
- ),
100
- factory.createIdentifier("IConnection"),
101
- ),
102
- ),
103
- factory.createObjectLiteralExpression(
104
- [
105
- factory.createSpreadAssignment(
106
- factory.createCallExpression(
107
- factory.createPropertyAccessExpression(
108
- factory.createIdentifier("TestGlobal"),
109
- "connection",
110
- ),
111
- undefined,
112
- undefined,
113
- ),
114
- ),
115
- ...(ctx.application.document().servers?.[0]?.url?.length
116
- ? [
117
- factory.createPropertyAssignment(
118
- "host",
119
- factory.createStringLiteral(
120
- ctx.application.document().servers![0]!.url,
121
- ),
122
- ),
123
- ]
124
- : []),
125
- ...(ctx.config.simulate === true
126
- ? [
127
- factory.createPropertyAssignment(
128
- "simulate",
129
- factory.createTrue(),
130
- ),
131
- ]
132
- : []),
133
- ],
134
- true,
135
- ),
136
- ),
137
- ],
138
- NodeFlags.Const,
139
- ),
140
- );
141
-
142
- const writeStarter = (): ts.CallExpression =>
143
- factory.createCallExpression(
144
- factory.createPropertyAccessExpression(
145
- factory.createCallExpression(
146
- factory.createIdentifier("main"),
147
- undefined,
148
- undefined,
149
- ),
150
- "catch",
151
- ),
152
- undefined,
153
- [
154
- factory.createArrowFunction(
155
- undefined,
156
- undefined,
157
- [IdentifierFactory.parameter("exp")],
158
- undefined,
159
- undefined,
160
- factory.createBlock(
161
- [
162
- factory.createExpressionStatement(
163
- factory.createCallExpression(
164
- factory.createPropertyAccessExpression(
165
- factory.createIdentifier("console"),
166
- "log",
167
- ),
168
- undefined,
169
- [factory.createIdentifier("exp")],
170
- ),
171
- ),
172
- factory.createExpressionStatement(
173
- factory.createCallExpression(
174
- factory.createPropertyAccessExpression(
175
- factory.createIdentifier("process"),
176
- "exit",
177
- ),
178
- undefined,
179
- [
180
- factory.createPrefixMinus(
181
- factory.createNumericLiteral("1"),
182
- ),
183
- ],
184
- ),
185
- ),
186
- ],
187
- true,
188
- ),
189
- ),
190
- ],
191
- );
192
- }
193
-
194
- const pick = <T>(array: T[]): T => {
195
- const rand: number = Math.random() * array.length;
196
- const index: number = Math.min(array.length - 1, Math.floor(rand));
197
- return array[index]!;
198
- };
1
+ import { NodeFlags, SyntaxKind, factory } from "@ttsc/factory";
2
+ import { IHttpMigrateRoute } from "@typia/interface";
3
+
4
+ import { IdentifierFactory } from "../factories/IdentifierFactory";
5
+ import { StatementFactory } from "../factories/StatementFactory";
6
+ import ts from "../internal/ts";
7
+ import { INestiaMigrateContext } from "../structures/INestiaMigrateContext";
8
+ import { FilePrinter } from "../utils/FilePrinter";
9
+ import { NestiaMigrateE2eFunctionProgrammer } from "./NestiaMigrateE2eFileProgrammer";
10
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
+
12
+ export namespace NestiaMigrateApiStartProgrammer {
13
+ export const write = (
14
+ context: INestiaMigrateContext,
15
+ ): Record<string, string> => {
16
+ const importer: NestiaMigrateImportProgrammer =
17
+ new NestiaMigrateImportProgrammer();
18
+ const main: ts.VariableStatement = writeMain(
19
+ context,
20
+ importer,
21
+ pick(context.application.routes),
22
+ );
23
+ const statements: ts.Statement[] = [
24
+ ...importer.toStatements(
25
+ (name) => `@ORGANIZATION/PROJECT-api/lib/structures/${name}`,
26
+ ),
27
+ FilePrinter.newLine(),
28
+ factory.createImportDeclaration(
29
+ undefined,
30
+ factory.createImportClause(
31
+ false,
32
+ undefined,
33
+ factory.createNamedImports([
34
+ factory.createImportSpecifier(
35
+ false,
36
+ undefined,
37
+ factory.createIdentifier("TestGlobal"),
38
+ ),
39
+ ]),
40
+ ),
41
+ factory.createStringLiteral("./TestGlobal"),
42
+ ),
43
+ FilePrinter.newLine(),
44
+ main,
45
+ factory.createExpressionStatement(writeStarter()),
46
+ ];
47
+ return {
48
+ "test/start.ts": FilePrinter.write({ statements }),
49
+ };
50
+ };
51
+
52
+ const writeMain = (
53
+ ctx: INestiaMigrateContext,
54
+ importer: NestiaMigrateImportProgrammer,
55
+ route: IHttpMigrateRoute,
56
+ ): ts.VariableStatement =>
57
+ StatementFactory.constant({
58
+ name: "main",
59
+ value: factory.createArrowFunction(
60
+ [factory.createToken(SyntaxKind.AsyncKeyword)],
61
+ undefined,
62
+ [],
63
+ undefined,
64
+ undefined,
65
+ factory.createBlock(
66
+ [
67
+ writeConnection(ctx, importer),
68
+ ...NestiaMigrateE2eFunctionProgrammer.writeBody({
69
+ config: ctx.config,
70
+ components: ctx.application.document().components,
71
+ importer,
72
+ route,
73
+ }),
74
+ ],
75
+ true,
76
+ ),
77
+ ),
78
+ });
79
+
80
+ const writeConnection = (
81
+ ctx: INestiaMigrateContext,
82
+ importer: NestiaMigrateImportProgrammer,
83
+ ): ts.VariableStatement =>
84
+ factory.createVariableStatement(
85
+ undefined,
86
+ factory.createVariableDeclarationList(
87
+ [
88
+ factory.createVariableDeclaration(
89
+ "connection",
90
+ undefined,
91
+ factory.createTypeReferenceNode(
92
+ factory.createQualifiedName(
93
+ factory.createIdentifier(
94
+ importer.external({
95
+ type: "default",
96
+ library: "@ORGANIZATION/PROJECT-api",
97
+ name: "api",
98
+ }),
99
+ ),
100
+ factory.createIdentifier("IConnection"),
101
+ ),
102
+ ),
103
+ factory.createObjectLiteralExpression(
104
+ [
105
+ factory.createSpreadAssignment(
106
+ factory.createCallExpression(
107
+ factory.createPropertyAccessExpression(
108
+ factory.createIdentifier("TestGlobal"),
109
+ "connection",
110
+ ),
111
+ undefined,
112
+ undefined,
113
+ ),
114
+ ),
115
+ ...(ctx.application.document().servers?.[0]?.url?.length
116
+ ? [
117
+ factory.createPropertyAssignment(
118
+ "host",
119
+ factory.createStringLiteral(
120
+ ctx.application.document().servers![0]!.url,
121
+ ),
122
+ ),
123
+ ]
124
+ : []),
125
+ ...(ctx.config.simulate === true
126
+ ? [
127
+ factory.createPropertyAssignment(
128
+ "simulate",
129
+ factory.createTrue(),
130
+ ),
131
+ ]
132
+ : []),
133
+ ],
134
+ true,
135
+ ),
136
+ ),
137
+ ],
138
+ NodeFlags.Const,
139
+ ),
140
+ );
141
+
142
+ const writeStarter = (): ts.CallExpression =>
143
+ factory.createCallExpression(
144
+ factory.createPropertyAccessExpression(
145
+ factory.createCallExpression(
146
+ factory.createIdentifier("main"),
147
+ undefined,
148
+ undefined,
149
+ ),
150
+ "catch",
151
+ ),
152
+ undefined,
153
+ [
154
+ factory.createArrowFunction(
155
+ undefined,
156
+ undefined,
157
+ [IdentifierFactory.parameter("exp")],
158
+ undefined,
159
+ undefined,
160
+ factory.createBlock(
161
+ [
162
+ factory.createExpressionStatement(
163
+ factory.createCallExpression(
164
+ factory.createPropertyAccessExpression(
165
+ factory.createIdentifier("console"),
166
+ "log",
167
+ ),
168
+ undefined,
169
+ [factory.createIdentifier("exp")],
170
+ ),
171
+ ),
172
+ factory.createExpressionStatement(
173
+ factory.createCallExpression(
174
+ factory.createPropertyAccessExpression(
175
+ factory.createIdentifier("process"),
176
+ "exit",
177
+ ),
178
+ undefined,
179
+ [
180
+ factory.createPrefixMinus(
181
+ factory.createNumericLiteral("1"),
182
+ ),
183
+ ],
184
+ ),
185
+ ),
186
+ ],
187
+ true,
188
+ ),
189
+ ),
190
+ ],
191
+ );
192
+ }
193
+
194
+ const pick = <T>(array: T[]): T => {
195
+ const rand: number = Math.random() * array.length;
196
+ const index: number = Math.min(array.length - 1, Math.floor(rand));
197
+ return array[index]!;
198
+ };
@@ -1,117 +1,117 @@
1
- import { SyntaxKind, factory } from "@ttsc/factory";
2
- import { OpenApi } from "@typia/interface";
3
- import { IPointer } from "tstl";
4
-
5
- import ts from "../internal/ts";
6
- import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
7
- import { FilePrinter } from "../utils/FilePrinter";
8
- import { MapUtil } from "../utils/MapUtil";
9
- import { StringUtil } from "../utils/StringUtil";
10
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
- import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
12
-
13
- export namespace NestiaMigrateDtoProgrammer {
14
- export interface IModule {
15
- name: string;
16
- children: Map<string, IModule>;
17
- programmer:
18
- | null
19
- | ((importer: NestiaMigrateImportProgrammer) => ts.TypeAliasDeclaration);
20
- }
21
-
22
- export const compose = (props: {
23
- config: INestiaMigrateConfig;
24
- components: OpenApi.IComponents;
25
- }): Map<string, IModule> => {
26
- const dict: Map<string, IModule> = new Map();
27
- for (const [key, value] of Object.entries(props.components.schemas ?? {})) {
28
- const emendedKey: string = key
29
- .split("/")
30
- .filter((str) => str.length !== 0)
31
- .map(StringUtil.escapeNonVariable)
32
- .join("");
33
- prepare(dict)(emendedKey)((importer) =>
34
- writeAlias(props.config)(props.components)(importer)(emendedKey, value),
35
- );
36
- }
37
- return dict;
38
- };
39
-
40
- const prepare =
41
- (dict: Map<string, IModule>) =>
42
- (name: string) =>
43
- (
44
- programmer: (
45
- importer: NestiaMigrateImportProgrammer,
46
- ) => ts.TypeAliasDeclaration,
47
- ) => {
48
- const accessors: string[] = name.split(".");
49
- const modulo: IPointer<IModule> = { value: null! };
50
-
51
- accessors.forEach((acc, i) => {
52
- modulo.value = MapUtil.take(dict)(acc)(() => ({
53
- name: acc,
54
- children: new Map(),
55
- programmer: null,
56
- }));
57
- if (i === accessors.length - 1) modulo.value.programmer = programmer;
58
- dict = modulo.value.children;
59
- });
60
- return modulo!;
61
- };
62
-
63
- const writeAlias =
64
- (config: INestiaMigrateConfig) =>
65
- (components: OpenApi.IComponents) =>
66
- (importer: NestiaMigrateImportProgrammer) =>
67
- (key: string, value: OpenApi.IJsonSchema) =>
68
- FilePrinter.description(
69
- factory.createTypeAliasDeclaration(
70
- [factory.createToken(SyntaxKind.ExportKeyword)],
71
- key.split(".").at(-1)!,
72
- [],
73
- NestiaMigrateSchemaProgrammer.write({
74
- components,
75
- importer,
76
- schema: value,
77
- }),
78
- ),
79
- writeComment(config)(value, key.indexOf(".") === -1),
80
- );
81
- }
82
-
83
- const writeComment =
84
- (config: INestiaMigrateConfig) =>
85
- (schema: OpenApi.IJsonSchema, top: boolean): string => {
86
- // PLUGIN PROPERTIES (x-) AS JSDOC TAGS
87
- //
88
- // Mirror NestiaMigrateSchemaProgrammer: emit every `x-` extension property
89
- // whose value is a primitive as an `@x-key value` JSDoc tag, so the plugin
90
- // metadata survives the swagger -> DTO round trip.
91
- const plugins: string[] = [];
92
- for (const [key, value] of Object.entries(schema))
93
- if (key.startsWith("x-") && isExtensionValue(value))
94
- plugins.push(`@${key} ${String(value)}`);
95
- return [
96
- ...(schema.description?.length ? [schema.description] : []),
97
- ...(schema.description?.length &&
98
- (schema.title !== undefined ||
99
- schema.deprecated === true ||
100
- plugins.length !== 0)
101
- ? [""]
102
- : []),
103
- ...(schema.title !== undefined ? [`@title ${schema.title}`] : []),
104
- ...(schema.deprecated === true ? [`@deprecated`] : []),
105
- ...plugins,
106
- ...(top
107
- ? [
108
- `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
109
- ]
110
- : []),
111
- ].join("\n");
112
- };
113
-
114
- const isExtensionValue = (value: unknown): value is boolean | number | string =>
115
- typeof value === "boolean" ||
116
- typeof value === "number" ||
117
- typeof value === "string";
1
+ import { SyntaxKind, factory } from "@ttsc/factory";
2
+ import { OpenApi } from "@typia/interface";
3
+ import { IPointer } from "tstl";
4
+
5
+ import ts from "../internal/ts";
6
+ import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
7
+ import { FilePrinter } from "../utils/FilePrinter";
8
+ import { MapUtil } from "../utils/MapUtil";
9
+ import { StringUtil } from "../utils/StringUtil";
10
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
+ import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
12
+
13
+ export namespace NestiaMigrateDtoProgrammer {
14
+ export interface IModule {
15
+ name: string;
16
+ children: Map<string, IModule>;
17
+ programmer:
18
+ | null
19
+ | ((importer: NestiaMigrateImportProgrammer) => ts.TypeAliasDeclaration);
20
+ }
21
+
22
+ export const compose = (props: {
23
+ config: INestiaMigrateConfig;
24
+ components: OpenApi.IComponents;
25
+ }): Map<string, IModule> => {
26
+ const dict: Map<string, IModule> = new Map();
27
+ for (const [key, value] of Object.entries(props.components.schemas ?? {})) {
28
+ const emendedKey: string = key
29
+ .split("/")
30
+ .filter((str) => str.length !== 0)
31
+ .map(StringUtil.escapeNonVariable)
32
+ .join("");
33
+ prepare(dict)(emendedKey)((importer) =>
34
+ writeAlias(props.config)(props.components)(importer)(emendedKey, value),
35
+ );
36
+ }
37
+ return dict;
38
+ };
39
+
40
+ const prepare =
41
+ (dict: Map<string, IModule>) =>
42
+ (name: string) =>
43
+ (
44
+ programmer: (
45
+ importer: NestiaMigrateImportProgrammer,
46
+ ) => ts.TypeAliasDeclaration,
47
+ ) => {
48
+ const accessors: string[] = name.split(".");
49
+ const modulo: IPointer<IModule> = { value: null! };
50
+
51
+ accessors.forEach((acc, i) => {
52
+ modulo.value = MapUtil.take(dict)(acc)(() => ({
53
+ name: acc,
54
+ children: new Map(),
55
+ programmer: null,
56
+ }));
57
+ if (i === accessors.length - 1) modulo.value.programmer = programmer;
58
+ dict = modulo.value.children;
59
+ });
60
+ return modulo!;
61
+ };
62
+
63
+ const writeAlias =
64
+ (config: INestiaMigrateConfig) =>
65
+ (components: OpenApi.IComponents) =>
66
+ (importer: NestiaMigrateImportProgrammer) =>
67
+ (key: string, value: OpenApi.IJsonSchema) =>
68
+ FilePrinter.description(
69
+ factory.createTypeAliasDeclaration(
70
+ [factory.createToken(SyntaxKind.ExportKeyword)],
71
+ key.split(".").at(-1)!,
72
+ [],
73
+ NestiaMigrateSchemaProgrammer.write({
74
+ components,
75
+ importer,
76
+ schema: value,
77
+ }),
78
+ ),
79
+ writeComment(config)(value, key.indexOf(".") === -1),
80
+ );
81
+ }
82
+
83
+ const writeComment =
84
+ (config: INestiaMigrateConfig) =>
85
+ (schema: OpenApi.IJsonSchema, top: boolean): string => {
86
+ // PLUGIN PROPERTIES (x-) AS JSDOC TAGS
87
+ //
88
+ // Mirror NestiaMigrateSchemaProgrammer: emit every `x-` extension property
89
+ // whose value is a primitive as an `@x-key value` JSDoc tag, so the plugin
90
+ // metadata survives the swagger -> DTO round trip.
91
+ const plugins: string[] = [];
92
+ for (const [key, value] of Object.entries(schema))
93
+ if (key.startsWith("x-") && isExtensionValue(value))
94
+ plugins.push(`@${key} ${String(value)}`);
95
+ return [
96
+ ...(schema.description?.length ? [schema.description] : []),
97
+ ...(schema.description?.length &&
98
+ (schema.title !== undefined ||
99
+ schema.deprecated === true ||
100
+ plugins.length !== 0)
101
+ ? [""]
102
+ : []),
103
+ ...(schema.title !== undefined ? [`@title ${schema.title}`] : []),
104
+ ...(schema.deprecated === true ? [`@deprecated`] : []),
105
+ ...plugins,
106
+ ...(top
107
+ ? [
108
+ `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
109
+ ]
110
+ : []),
111
+ ].join("\n");
112
+ };
113
+
114
+ const isExtensionValue = (value: unknown): value is boolean | number | string =>
115
+ typeof value === "boolean" ||
116
+ typeof value === "number" ||
117
+ typeof value === "string";