@nestia/migrate 0.1.0
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/.prettierignore +3 -0
- package/.vscode/settings.json +10 -0
- package/lib/NestiaMigrateApplication.d.ts +18 -0
- package/lib/NestiaMigrateApplication.js +1330 -0
- package/lib/NestiaMigrateApplication.js.map +1 -0
- package/lib/archivers/FileArchiver.d.ts +8 -0
- package/lib/archivers/FileArchiver.js +35 -0
- package/lib/archivers/FileArchiver.js.map +1 -0
- package/lib/bundles/TEMPLATE.d.ts +5 -0
- package/lib/bundles/TEMPLATE.js +261 -0
- package/lib/bundles/TEMPLATE.js.map +1 -0
- package/lib/executable/bundle.d.ts +1 -0
- package/lib/executable/bundle.js +75 -0
- package/lib/executable/bundle.js.map +1 -0
- package/lib/executable/migrate.d.ts +2 -0
- package/lib/executable/migrate.js +65 -0
- package/lib/executable/migrate.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +32 -0
- package/lib/index.js.map +1 -0
- package/lib/module.d.ts +3 -0
- package/lib/module.js +20 -0
- package/lib/module.js.map +1 -0
- package/lib/programmers/ControllerProgrammer.d.ts +6 -0
- package/lib/programmers/ControllerProgrammer.js +119 -0
- package/lib/programmers/ControllerProgrammer.js.map +1 -0
- package/lib/programmers/DtoProgrammer.d.ts +6 -0
- package/lib/programmers/DtoProgrammer.js +95 -0
- package/lib/programmers/DtoProgrammer.js.map +1 -0
- package/lib/programmers/MigrateProgrammer.d.ts +7 -0
- package/lib/programmers/MigrateProgrammer.js +31 -0
- package/lib/programmers/MigrateProgrammer.js.map +1 -0
- package/lib/programmers/RouteProgrammer.d.ts +11 -0
- package/lib/programmers/RouteProgrammer.js +199 -0
- package/lib/programmers/RouteProgrammer.js.map +1 -0
- package/lib/programmers/SchemaProgrammer.d.ts +4 -0
- package/lib/programmers/SchemaProgrammer.js +163 -0
- package/lib/programmers/SchemaProgrammer.js.map +1 -0
- package/lib/structures/IMigrateController.d.ts +7 -0
- package/lib/structures/IMigrateController.js +3 -0
- package/lib/structures/IMigrateController.js.map +1 -0
- package/lib/structures/IMigrateDto.d.ts +7 -0
- package/lib/structures/IMigrateDto.js +3 -0
- package/lib/structures/IMigrateDto.js.map +1 -0
- package/lib/structures/IMigrateFile.d.ts +5 -0
- package/lib/structures/IMigrateFile.js +3 -0
- package/lib/structures/IMigrateFile.js.map +1 -0
- package/lib/structures/IMigrateProgram.d.ts +6 -0
- package/lib/structures/IMigrateProgram.js +3 -0
- package/lib/structures/IMigrateProgram.js.map +1 -0
- package/lib/structures/IMigrateRoute.d.ts +19 -0
- package/lib/structures/IMigrateRoute.js +3 -0
- package/lib/structures/IMigrateRoute.js.map +1 -0
- package/lib/structures/IMigrateSchema.d.ts +4 -0
- package/lib/structures/IMigrateSchema.js +3 -0
- package/lib/structures/IMigrateSchema.js.map +1 -0
- package/lib/structures/ISwaggeSchema.d.ts +72 -0
- package/lib/structures/ISwaggeSchema.js +3 -0
- package/lib/structures/ISwaggeSchema.js.map +1 -0
- package/lib/structures/ISwagger.d.ts +22 -0
- package/lib/structures/ISwagger.js +3 -0
- package/lib/structures/ISwagger.js.map +1 -0
- package/lib/structures/ISwaggerComponents.d.ts +6 -0
- package/lib/structures/ISwaggerComponents.js +3 -0
- package/lib/structures/ISwaggerComponents.js.map +1 -0
- package/lib/structures/ISwaggerRoute.d.ts +38 -0
- package/lib/structures/ISwaggerRoute.js +3 -0
- package/lib/structures/ISwaggerRoute.js.map +1 -0
- package/lib/structures/ISwaggerSecurity.d.ts +40 -0
- package/lib/structures/ISwaggerSecurity.js +3 -0
- package/lib/structures/ISwaggerSecurity.js.map +1 -0
- package/lib/test/index.d.ts +1 -0
- package/lib/test/index.js +45 -0
- package/lib/test/index.js.map +1 -0
- package/lib/utils/JsonTypeChecker.d.ts +13 -0
- package/lib/utils/JsonTypeChecker.js +20 -0
- package/lib/utils/JsonTypeChecker.js.map +1 -0
- package/lib/utils/MapUtil.d.ts +3 -0
- package/lib/utils/MapUtil.js +15 -0
- package/lib/utils/MapUtil.js.map +1 -0
- package/lib/utils/SetupWizard.d.ts +3 -0
- package/lib/utils/SetupWizard.js +21 -0
- package/lib/utils/SetupWizard.js.map +1 -0
- package/lib/utils/StringUtil.d.ts +9 -0
- package/lib/utils/StringUtil.js +41 -0
- package/lib/utils/StringUtil.js.map +1 -0
- package/package.json +43 -0
- package/prettier.config.js +15 -0
- package/src/NestiaMigrateApplication.ts +51 -0
- package/src/archivers/FileArchiver.ts +38 -0
- package/src/bundles/TEMPLATE.ts +257 -0
- package/src/executable/bundle.ts +74 -0
- package/src/executable/migrate.ts +58 -0
- package/src/index.ts +4 -0
- package/src/module.ts +4 -0
- package/src/programmers/ControllerProgrammer.ts +159 -0
- package/src/programmers/DtoProgrammer.ts +122 -0
- package/src/programmers/MigrateProgrammer.ts +31 -0
- package/src/programmers/RouteProgrammer.ts +264 -0
- package/src/programmers/SchemaProgrammer.ts +215 -0
- package/src/structures/IMigrateController.ts +8 -0
- package/src/structures/IMigrateDto.ts +8 -0
- package/src/structures/IMigrateFile.ts +5 -0
- package/src/structures/IMigrateProgram.ts +7 -0
- package/src/structures/IMigrateRoute.ts +20 -0
- package/src/structures/IMigrateSchema.ts +4 -0
- package/src/structures/ISwaggeSchema.ts +85 -0
- package/src/structures/ISwagger.ts +24 -0
- package/src/structures/ISwaggerComponents.ts +7 -0
- package/src/structures/ISwaggerRoute.ts +42 -0
- package/src/structures/ISwaggerSecurity.ts +47 -0
- package/src/test/index.ts +38 -0
- package/src/utils/JsonTypeChecker.ts +48 -0
- package/src/utils/MapUtil.ts +13 -0
- package/src/utils/SetupWizard.ts +15 -0
- package/src/utils/StringUtil.ts +49 -0
- package/tsconfig.json +81 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { IMigrateRoute } from "../structures/IMigrateRoute";
|
|
2
|
+
import { ISwaggerSchema } from "../structures/ISwaggeSchema";
|
|
3
|
+
import { ISwagger } from "../structures/ISwagger";
|
|
4
|
+
import { ISwaggerRoute } from "../structures/ISwaggerRoute";
|
|
5
|
+
import { JsonTypeChecker } from "../utils/JsonTypeChecker";
|
|
6
|
+
import { StringUtil } from "../utils/StringUtil";
|
|
7
|
+
import { SchemaProgrammer } from "./SchemaProgrammer";
|
|
8
|
+
|
|
9
|
+
export namespace RouteProgrammer {
|
|
10
|
+
export const analyze =
|
|
11
|
+
(swagger: ISwagger) =>
|
|
12
|
+
(props: { path: string; method: string }) =>
|
|
13
|
+
(route: ISwaggerRoute): IMigrateRoute | null => {
|
|
14
|
+
const body = emplaceBodySchema(emplaceReference(swagger)("body"))(
|
|
15
|
+
route.requestBody?.content,
|
|
16
|
+
);
|
|
17
|
+
const response = emplaceBodySchema(
|
|
18
|
+
emplaceReference(swagger)("response"),
|
|
19
|
+
)((route.responses["200"] ?? route.responses["201"])?.content);
|
|
20
|
+
if (body === false || response === false) return null;
|
|
21
|
+
|
|
22
|
+
const [headers, query] = ["header", "query"].map((type) => {
|
|
23
|
+
const parameters = route.parameters.filter(
|
|
24
|
+
(p) => p.in === type,
|
|
25
|
+
);
|
|
26
|
+
if (parameters.length === 0) return null;
|
|
27
|
+
|
|
28
|
+
const objects = parameters
|
|
29
|
+
.map((p) =>
|
|
30
|
+
JsonTypeChecker.isObject(p.schema)
|
|
31
|
+
? p.schema
|
|
32
|
+
: JsonTypeChecker.isReference(p.schema) &&
|
|
33
|
+
JsonTypeChecker.isObject(
|
|
34
|
+
(swagger.components.schemas ?? {})[
|
|
35
|
+
p.schema.$ref.replace(
|
|
36
|
+
`#/components/schemas/`,
|
|
37
|
+
``,
|
|
38
|
+
)
|
|
39
|
+
] ?? {},
|
|
40
|
+
)
|
|
41
|
+
? p.schema
|
|
42
|
+
: null!,
|
|
43
|
+
)
|
|
44
|
+
.filter((s) => !!s);
|
|
45
|
+
const primitives = parameters.filter(
|
|
46
|
+
(p) =>
|
|
47
|
+
JsonTypeChecker.isBoolean(p.schema) ||
|
|
48
|
+
JsonTypeChecker.isNumber(p.schema) ||
|
|
49
|
+
JsonTypeChecker.isString(p.schema),
|
|
50
|
+
);
|
|
51
|
+
if (objects.length === 1) return objects[0];
|
|
52
|
+
else if (
|
|
53
|
+
objects.length + primitives.length !==
|
|
54
|
+
parameters.length
|
|
55
|
+
)
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Error on nestia.migrate.RouteProgrammer.analze(): ${type} typed parameters must be only one object type.`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const entire: ISwaggerSchema.IObject[] = [
|
|
61
|
+
...objects.map((o) =>
|
|
62
|
+
JsonTypeChecker.isObject(o)
|
|
63
|
+
? o
|
|
64
|
+
: (swagger.components.schemas?.[
|
|
65
|
+
o.$ref.replace(`#/components/schemas/`, ``)
|
|
66
|
+
]! as ISwaggerSchema.IObject),
|
|
67
|
+
),
|
|
68
|
+
{
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: Object.fromEntries(
|
|
71
|
+
primitives.map((p) => [
|
|
72
|
+
p.name,
|
|
73
|
+
{
|
|
74
|
+
...p.schema,
|
|
75
|
+
description:
|
|
76
|
+
p.schema.description ?? p.description,
|
|
77
|
+
},
|
|
78
|
+
]),
|
|
79
|
+
),
|
|
80
|
+
required: primitives
|
|
81
|
+
.filter((p) => p.required)
|
|
82
|
+
.map((p) => p.name),
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
return parameters.length === 0
|
|
86
|
+
? null
|
|
87
|
+
: emplaceReference(swagger)(
|
|
88
|
+
StringUtil.pascal(
|
|
89
|
+
`I/Api/${StringUtil.reJoinWithoutParameters(
|
|
90
|
+
props.path,
|
|
91
|
+
)}`,
|
|
92
|
+
) +
|
|
93
|
+
"." +
|
|
94
|
+
StringUtil.pascal(`${props.method}/${type}`),
|
|
95
|
+
)({
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: Object.fromEntries([
|
|
98
|
+
...new Map<string, ISwaggerSchema>(
|
|
99
|
+
entire
|
|
100
|
+
.map((o) =>
|
|
101
|
+
Object.entries(o.properties).map(
|
|
102
|
+
([name, schema]) =>
|
|
103
|
+
[
|
|
104
|
+
name,
|
|
105
|
+
{
|
|
106
|
+
...schema,
|
|
107
|
+
description:
|
|
108
|
+
schema.description ??
|
|
109
|
+
schema.description,
|
|
110
|
+
} as ISwaggerSchema,
|
|
111
|
+
] as const,
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
.flat(),
|
|
115
|
+
),
|
|
116
|
+
]),
|
|
117
|
+
required: [
|
|
118
|
+
...new Set(
|
|
119
|
+
entire.map((o) => o.required ?? []).flat(),
|
|
120
|
+
),
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
name: "@lazy",
|
|
127
|
+
path: props.path,
|
|
128
|
+
method: props.method,
|
|
129
|
+
headers,
|
|
130
|
+
parameters: route.parameters
|
|
131
|
+
.filter((p) => p.in === "path")
|
|
132
|
+
.map((p) => ({
|
|
133
|
+
key: p.name,
|
|
134
|
+
schema: {
|
|
135
|
+
...p.schema,
|
|
136
|
+
description: p.schema.description ?? p.description,
|
|
137
|
+
},
|
|
138
|
+
})),
|
|
139
|
+
query,
|
|
140
|
+
body,
|
|
141
|
+
response,
|
|
142
|
+
description: describe(route),
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const describe = (route: ISwaggerRoute): string | undefined => {
|
|
147
|
+
const content: string[] = [];
|
|
148
|
+
const add = (text: string) => {
|
|
149
|
+
if (!route.description || route.description.indexOf(text) === -1)
|
|
150
|
+
content.push(text);
|
|
151
|
+
};
|
|
152
|
+
if (route.summary)
|
|
153
|
+
add(
|
|
154
|
+
(route.summary.endsWith(".")
|
|
155
|
+
? route.summary
|
|
156
|
+
: route.summary + ".") + "\n",
|
|
157
|
+
);
|
|
158
|
+
if (route.description) {
|
|
159
|
+
content.push(...route.description.split("\n"));
|
|
160
|
+
if (!route.description.split("\n").at(-1)?.startsWith("@"))
|
|
161
|
+
content.push("");
|
|
162
|
+
}
|
|
163
|
+
if (route.tags) route.tags.forEach((name) => add(`@tag ${name}`));
|
|
164
|
+
if (route.deprecated) add("@deprecated");
|
|
165
|
+
return content.length ? content.join("\n") : undefined;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const isNotObjectLiteral = (schema: ISwaggerSchema): boolean =>
|
|
169
|
+
JsonTypeChecker.isReference(schema) ||
|
|
170
|
+
JsonTypeChecker.isBoolean(schema) ||
|
|
171
|
+
JsonTypeChecker.isNumber(schema) ||
|
|
172
|
+
JsonTypeChecker.isString(schema) ||
|
|
173
|
+
JsonTypeChecker.isUnknown(schema) ||
|
|
174
|
+
(JsonTypeChecker.isAnyOf(schema) &&
|
|
175
|
+
schema.anyOf.every(isNotObjectLiteral)) ||
|
|
176
|
+
(JsonTypeChecker.isOneOf(schema) &&
|
|
177
|
+
schema.oneOf.every(isNotObjectLiteral)) ||
|
|
178
|
+
(JsonTypeChecker.isArray(schema) && isNotObjectLiteral(schema.items));
|
|
179
|
+
|
|
180
|
+
const emplaceBodySchema =
|
|
181
|
+
(emplacer: (schema: ISwaggerSchema) => ISwaggerSchema.IReference) =>
|
|
182
|
+
(content?: ISwaggerRoute.IContent): false | null | ISwaggerSchema => {
|
|
183
|
+
if (!content) return null;
|
|
184
|
+
else if (content["application/json"]) {
|
|
185
|
+
const schema = content["application/json"].schema;
|
|
186
|
+
return isNotObjectLiteral(schema) ? schema : emplacer(schema);
|
|
187
|
+
} else if (content["text/plain"]) return { type: "string" };
|
|
188
|
+
return false;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const emplaceReference =
|
|
192
|
+
(swagger: ISwagger) =>
|
|
193
|
+
(name: string) =>
|
|
194
|
+
(schema: ISwaggerSchema): ISwaggerSchema.IReference => {
|
|
195
|
+
swagger.components.schemas ??= {};
|
|
196
|
+
swagger.components.schemas[name] = schema;
|
|
197
|
+
return { $ref: `#/components/schemas/${name}` };
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export const write =
|
|
201
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
202
|
+
(route: IMigrateRoute): string => {
|
|
203
|
+
const output: string = route.response
|
|
204
|
+
? SchemaProgrammer.write(references)(route.response)
|
|
205
|
+
: "void";
|
|
206
|
+
const content: string[] = [
|
|
207
|
+
...(route.description
|
|
208
|
+
? [
|
|
209
|
+
"/**",
|
|
210
|
+
...route.description
|
|
211
|
+
.split("\n")
|
|
212
|
+
.map((line) => ` * ${line}`),
|
|
213
|
+
" */",
|
|
214
|
+
]
|
|
215
|
+
: []),
|
|
216
|
+
`@core.TypedRoute.${StringUtil.capitalize(route.method)}${
|
|
217
|
+
route.path.length ? `(${JSON.stringify(route.path)})` : "()"
|
|
218
|
+
}`,
|
|
219
|
+
`public async ${route.name}(`,
|
|
220
|
+
...route.parameters.map((p) => ` ${writeParameter(p)},`),
|
|
221
|
+
...(route.query
|
|
222
|
+
? [
|
|
223
|
+
` @core.TypedQuery() query: ${SchemaProgrammer.write(
|
|
224
|
+
references,
|
|
225
|
+
)(route.query)}`,
|
|
226
|
+
]
|
|
227
|
+
: []),
|
|
228
|
+
...(route.body
|
|
229
|
+
? [
|
|
230
|
+
` @core.TypedBody() body: ${SchemaProgrammer.write(
|
|
231
|
+
references,
|
|
232
|
+
)(route.body)},`,
|
|
233
|
+
]
|
|
234
|
+
: []),
|
|
235
|
+
`): Promise<${output}> {`,
|
|
236
|
+
...route.parameters.map(
|
|
237
|
+
(p) => ` ${StringUtil.normalize(p.key)};`,
|
|
238
|
+
),
|
|
239
|
+
// ...(route.headers ? ["headers;"] : []),
|
|
240
|
+
...(route.query ? [" query;"] : []),
|
|
241
|
+
...(route.body ? [" body;"] : []),
|
|
242
|
+
...(output !== "void"
|
|
243
|
+
? [` return typia.random<${output}>();`]
|
|
244
|
+
: []),
|
|
245
|
+
`}`,
|
|
246
|
+
];
|
|
247
|
+
return content.join("\n");
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const writeParameter = ({
|
|
251
|
+
key,
|
|
252
|
+
schema,
|
|
253
|
+
}: IMigrateRoute.IParameter): string => {
|
|
254
|
+
const variable = StringUtil.normalize(key);
|
|
255
|
+
const format =
|
|
256
|
+
JsonTypeChecker.isString(schema) &&
|
|
257
|
+
(schema.format === "uuid" || schema.format === "date")
|
|
258
|
+
? schema.format
|
|
259
|
+
: null;
|
|
260
|
+
return `@core.TypedParam(${JSON.stringify(key)}${
|
|
261
|
+
format ? `, ${JSON.stringify(format)}` : ""
|
|
262
|
+
}) ${variable}: ${SchemaProgrammer.write([])(schema)}`;
|
|
263
|
+
};
|
|
264
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Escaper } from "typia/lib/utils/Escaper";
|
|
2
|
+
|
|
3
|
+
import { ISwaggerSchema } from "../structures/ISwaggeSchema";
|
|
4
|
+
import { JsonTypeChecker } from "../utils/JsonTypeChecker";
|
|
5
|
+
|
|
6
|
+
export namespace SchemaProgrammer {
|
|
7
|
+
export const write =
|
|
8
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
9
|
+
(schema: ISwaggerSchema): string =>
|
|
10
|
+
writeSchema(references)(() => () => {})(schema);
|
|
11
|
+
|
|
12
|
+
type Tagger = (tag: string) => (value?: string) => void;
|
|
13
|
+
const writeSchema =
|
|
14
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
15
|
+
(tagger: Tagger) =>
|
|
16
|
+
(schema: ISwaggerSchema): string => {
|
|
17
|
+
// SPECIAL TYPES
|
|
18
|
+
if (JsonTypeChecker.isUnknown(schema)) return "any";
|
|
19
|
+
else if (JsonTypeChecker.isAnyOf(schema))
|
|
20
|
+
return schema.anyOf
|
|
21
|
+
.map(writeSchema(references)(tagger))
|
|
22
|
+
.join(" | ");
|
|
23
|
+
else if (JsonTypeChecker.isOneOf(schema))
|
|
24
|
+
return schema.oneOf
|
|
25
|
+
.map(writeSchema(references)(tagger))
|
|
26
|
+
.join(" | ");
|
|
27
|
+
// ATOMIC TYPES
|
|
28
|
+
else if (JsonTypeChecker.isBoolean(schema))
|
|
29
|
+
return writeBoolean(tagger)(schema);
|
|
30
|
+
else if (JsonTypeChecker.isInteger(schema))
|
|
31
|
+
return writeInteger(tagger)(schema);
|
|
32
|
+
else if (JsonTypeChecker.isNumber(schema))
|
|
33
|
+
return writeNumber(tagger)(schema);
|
|
34
|
+
else if (JsonTypeChecker.isString(schema))
|
|
35
|
+
return writeString(tagger)(schema);
|
|
36
|
+
// INSTANCE TYPES
|
|
37
|
+
else if (JsonTypeChecker.isArray(schema))
|
|
38
|
+
return writeArray(references)(tagger)(schema);
|
|
39
|
+
else if (JsonTypeChecker.isObject(schema))
|
|
40
|
+
return writeObject(references)(schema);
|
|
41
|
+
else if (JsonTypeChecker.isReference(schema)) {
|
|
42
|
+
references.push(schema);
|
|
43
|
+
return schema.$ref.replace(`#/components/schemas/`, ``);
|
|
44
|
+
}
|
|
45
|
+
// NOTHING
|
|
46
|
+
return "any";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const writeBoolean =
|
|
50
|
+
(tagger: Tagger) =>
|
|
51
|
+
(schema: ISwaggerSchema.IBoolean): string => {
|
|
52
|
+
if (schema.default) tagger("default")(schema.default.toString());
|
|
53
|
+
return schema.enum ? schema.enum.join(" | ") : "boolean";
|
|
54
|
+
};
|
|
55
|
+
const writeInteger =
|
|
56
|
+
(tagger: Tagger) =>
|
|
57
|
+
(schema: ISwaggerSchema.IInteger): string => {
|
|
58
|
+
tagger("type")("int");
|
|
59
|
+
return writeNumber(tagger)(schema);
|
|
60
|
+
};
|
|
61
|
+
const writeNumber =
|
|
62
|
+
(tagger: Tagger) =>
|
|
63
|
+
(schema: ISwaggerSchema.IInteger | ISwaggerSchema.INumber): string => {
|
|
64
|
+
if (schema.default) tagger("default")(schema.default.toString());
|
|
65
|
+
if (schema.enum?.length) return schema.enum.join(" | ");
|
|
66
|
+
|
|
67
|
+
if (schema.minimum !== undefined)
|
|
68
|
+
tagger(
|
|
69
|
+
schema.exclusiveMinimum ? "exclusiveMinimum" : "minimum",
|
|
70
|
+
)(schema.minimum.toString());
|
|
71
|
+
if (schema.maximum !== undefined)
|
|
72
|
+
tagger(
|
|
73
|
+
schema.exclusiveMaximum ? "exclusiveMaximum" : "maximum",
|
|
74
|
+
)(schema.maximum.toString());
|
|
75
|
+
if (schema.multipleOf !== undefined)
|
|
76
|
+
tagger("multipleOf")(schema.multipleOf.toString());
|
|
77
|
+
return "number";
|
|
78
|
+
};
|
|
79
|
+
const writeString =
|
|
80
|
+
(tagger: Tagger) =>
|
|
81
|
+
(schema: ISwaggerSchema.IString): string => {
|
|
82
|
+
if (schema.default) tagger("default")(schema.default);
|
|
83
|
+
if (schema.enum?.length)
|
|
84
|
+
return schema.enum
|
|
85
|
+
.map((str) => JSON.stringify(str))
|
|
86
|
+
.join(" | ");
|
|
87
|
+
|
|
88
|
+
if (schema.minLength !== undefined)
|
|
89
|
+
tagger("minLength")(schema.minLength.toString());
|
|
90
|
+
if (schema.maxLength !== undefined)
|
|
91
|
+
tagger("maxLength")(schema.maxLength.toString());
|
|
92
|
+
if (schema.pattern !== undefined) tagger("pattern")(schema.pattern);
|
|
93
|
+
return "string";
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const writeArray =
|
|
97
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
98
|
+
(tagger: Tagger) =>
|
|
99
|
+
(schema: ISwaggerSchema.IArray): string =>
|
|
100
|
+
schema["x-typia-tuple"]
|
|
101
|
+
? `[${schema["x-typia-tuple"].items
|
|
102
|
+
.map(writeTupleElement(references))
|
|
103
|
+
.join(", ")}]`
|
|
104
|
+
: `Array<${writeSchema(references)(tagger)(schema.items)}>`;
|
|
105
|
+
const writeTupleElement =
|
|
106
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
107
|
+
(schema: ISwaggerSchema): string => {
|
|
108
|
+
const name: string = writeSchema(references)(() => () => {})(
|
|
109
|
+
schema,
|
|
110
|
+
);
|
|
111
|
+
return schema["x-typia-optional"]
|
|
112
|
+
? `${name}?`
|
|
113
|
+
: schema["x-typia-rest"]
|
|
114
|
+
? `...${name}`
|
|
115
|
+
: name;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const writeObject =
|
|
119
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
120
|
+
(schema: ISwaggerSchema.IObject): string => {
|
|
121
|
+
const entries = Object.entries(schema.properties);
|
|
122
|
+
return typeof schema.additionalProperties === "object"
|
|
123
|
+
? entries.length
|
|
124
|
+
? `${writeStaticObject(references)(
|
|
125
|
+
schema,
|
|
126
|
+
)} & ${writeDynamicObject(references)(
|
|
127
|
+
schema.additionalProperties,
|
|
128
|
+
)}`
|
|
129
|
+
: writeDynamicObject(references)(
|
|
130
|
+
schema.additionalProperties,
|
|
131
|
+
)
|
|
132
|
+
: writeStaticObject(references)(schema);
|
|
133
|
+
};
|
|
134
|
+
const writeStaticObject =
|
|
135
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
136
|
+
(schema: ISwaggerSchema.IObject): string =>
|
|
137
|
+
[
|
|
138
|
+
"{",
|
|
139
|
+
...Object.entries(schema.properties)
|
|
140
|
+
.map(([key, value]) =>
|
|
141
|
+
writeProperty(references)(key)(
|
|
142
|
+
(schema.required ?? []).some((r) => r === key),
|
|
143
|
+
)(value),
|
|
144
|
+
)
|
|
145
|
+
.map(tab(4)),
|
|
146
|
+
"}",
|
|
147
|
+
].join("\n");
|
|
148
|
+
const writeDynamicObject =
|
|
149
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
150
|
+
(additional: ISwaggerSchema): string => {
|
|
151
|
+
return [
|
|
152
|
+
"{",
|
|
153
|
+
tab(4)(
|
|
154
|
+
writeProperty(references)("[key: string]", true)(true)(
|
|
155
|
+
additional,
|
|
156
|
+
),
|
|
157
|
+
),
|
|
158
|
+
"}",
|
|
159
|
+
].join("\n");
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const writeProperty =
|
|
163
|
+
(references: ISwaggerSchema.IReference[]) =>
|
|
164
|
+
(key: string, ensureVariable: boolean = false) =>
|
|
165
|
+
(required: boolean) =>
|
|
166
|
+
(schema: ISwaggerSchema): string => {
|
|
167
|
+
const content: string[] = [];
|
|
168
|
+
const tagger = (tag: string) => (value?: string) => {
|
|
169
|
+
const exists: boolean =
|
|
170
|
+
(!!schema.description?.length &&
|
|
171
|
+
schema.description.includes(`@${tag}`)) ||
|
|
172
|
+
content.some((line) => line.includes(`@${tag}`));
|
|
173
|
+
if (exists === false)
|
|
174
|
+
if (value?.length) content.push(`@${tag} ${value}`);
|
|
175
|
+
else content.push(`@${tag}`);
|
|
176
|
+
};
|
|
177
|
+
if (schema.description) {
|
|
178
|
+
content.push(...schema.description.split("\n"));
|
|
179
|
+
if (!schema.description.split("\n").at(-1)?.startsWith("@"))
|
|
180
|
+
content.push("");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// STARTS FROM TITLE
|
|
184
|
+
if (schema.title) tagger("@title")(schema.title);
|
|
185
|
+
|
|
186
|
+
// GET TYPE WITH SPECIAL TAGS
|
|
187
|
+
const type: string = writeSchema(references)(tagger)(schema);
|
|
188
|
+
|
|
189
|
+
// ENDS WITH DEPRECATED TAG
|
|
190
|
+
if (schema.deprecated) tagger("@deprecated")();
|
|
191
|
+
|
|
192
|
+
const description: string =
|
|
193
|
+
content.length === 0
|
|
194
|
+
? ""
|
|
195
|
+
: [
|
|
196
|
+
"/**",
|
|
197
|
+
...content.map((line) => ` * ${line}`),
|
|
198
|
+
" */",
|
|
199
|
+
"",
|
|
200
|
+
].join("\n");
|
|
201
|
+
return `${description}${
|
|
202
|
+
ensureVariable === false && Escaper.variable(key) === false
|
|
203
|
+
? JSON.stringify(key)
|
|
204
|
+
: key
|
|
205
|
+
}${required ? "" : "?"}: ${type};`;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const tab =
|
|
209
|
+
(size: number) =>
|
|
210
|
+
(str: string): string =>
|
|
211
|
+
str
|
|
212
|
+
.split("\n")
|
|
213
|
+
.map((l) => `${" ".repeat(size)}${l}`)
|
|
214
|
+
.join("\n");
|
|
215
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ISwaggerSchema } from "./ISwaggeSchema";
|
|
2
|
+
|
|
3
|
+
export interface IMigrateRoute {
|
|
4
|
+
name: string;
|
|
5
|
+
path: string;
|
|
6
|
+
method: string;
|
|
7
|
+
parameters: IMigrateRoute.IParameter[];
|
|
8
|
+
headers: ISwaggerSchema | null;
|
|
9
|
+
query: ISwaggerSchema | null;
|
|
10
|
+
body: ISwaggerSchema | null;
|
|
11
|
+
response: ISwaggerSchema | null;
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
export namespace IMigrateRoute {
|
|
15
|
+
export interface IParameter {
|
|
16
|
+
key: string;
|
|
17
|
+
schema: ISwaggerSchema;
|
|
18
|
+
description?: string;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export type ISwaggerSchema =
|
|
2
|
+
| ISwaggerSchema.IUnknown
|
|
3
|
+
| ISwaggerSchema.IAnyOf
|
|
4
|
+
| ISwaggerSchema.IOneOf
|
|
5
|
+
| ISwaggerSchema.IBoolean
|
|
6
|
+
| ISwaggerSchema.IInteger
|
|
7
|
+
| ISwaggerSchema.INumber
|
|
8
|
+
| ISwaggerSchema.IString
|
|
9
|
+
| ISwaggerSchema.IArray
|
|
10
|
+
| ISwaggerSchema.IObject
|
|
11
|
+
| ISwaggerSchema.IReference;
|
|
12
|
+
export namespace ISwaggerSchema {
|
|
13
|
+
export interface IUnknown extends IAttribute {
|
|
14
|
+
type?: undefined;
|
|
15
|
+
}
|
|
16
|
+
export interface IAnyOf extends IAttribute {
|
|
17
|
+
anyOf: ISwaggerSchema[];
|
|
18
|
+
}
|
|
19
|
+
export interface IOneOf extends IAttribute {
|
|
20
|
+
oneOf: ISwaggerSchema[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface IBoolean extends ISignificant<"boolean"> {
|
|
24
|
+
default?: boolean;
|
|
25
|
+
enum?: boolean[];
|
|
26
|
+
}
|
|
27
|
+
export interface IInteger extends ISignificant<"integer"> {
|
|
28
|
+
/** @type int */ default?: number;
|
|
29
|
+
/** @type int */ enum?: number[];
|
|
30
|
+
/** @type int */ minimum?: number;
|
|
31
|
+
/** @type int */ maximum?: number;
|
|
32
|
+
/** @type int */ exclusiveMinimum?: boolean;
|
|
33
|
+
/** @type int */ exclusiveMaximum?: boolean;
|
|
34
|
+
/** @type uint */ multipleOf?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface INumber extends ISignificant<"number"> {
|
|
37
|
+
default?: number;
|
|
38
|
+
enum?: number[];
|
|
39
|
+
minimum?: number;
|
|
40
|
+
maximum?: number;
|
|
41
|
+
exclusiveMinimum?: boolean;
|
|
42
|
+
exclusiveMaximum?: boolean;
|
|
43
|
+
multipleOf?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface IString extends ISignificant<"string"> {
|
|
46
|
+
default?: string;
|
|
47
|
+
enum?: string[];
|
|
48
|
+
format?: string;
|
|
49
|
+
pattern?: string;
|
|
50
|
+
/** @type uint */ minLength?: number;
|
|
51
|
+
/** @type uint */ maxLength?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface IArray extends ISignificant<"array"> {
|
|
55
|
+
items: ISwaggerSchema;
|
|
56
|
+
/** @type uint */ minItems?: number;
|
|
57
|
+
/** @type uint */ maxItems?: number;
|
|
58
|
+
"x-typia-tuple"?: ITuple;
|
|
59
|
+
}
|
|
60
|
+
export interface ITuple extends ISignificant<"array"> {
|
|
61
|
+
items: ISwaggerSchema[];
|
|
62
|
+
}
|
|
63
|
+
export interface IObject extends ISignificant<"object"> {
|
|
64
|
+
properties: Record<string, ISwaggerSchema>;
|
|
65
|
+
required?: string[];
|
|
66
|
+
additionalProperties?: ISwaggerSchema | boolean;
|
|
67
|
+
"x-typia-patternProperties"?: Record<string, ISwaggerSchema>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface IReference extends IAttribute {
|
|
71
|
+
$ref: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface ISignificant<Type extends string> extends IAttribute {
|
|
75
|
+
type: Type;
|
|
76
|
+
nullable?: boolean;
|
|
77
|
+
}
|
|
78
|
+
interface IAttribute {
|
|
79
|
+
title?: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
deprecated?: boolean;
|
|
82
|
+
"x-typia-optional"?: boolean;
|
|
83
|
+
"x-typia-rest"?: boolean;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ISwaggerComponents } from "./ISwaggerComponents";
|
|
2
|
+
import { ISwaggerRoute } from "./ISwaggerRoute";
|
|
3
|
+
|
|
4
|
+
export interface ISwagger {
|
|
5
|
+
openapi: `3.0.${number}`;
|
|
6
|
+
info: ISwagger.IInfo;
|
|
7
|
+
servers: ISwagger.IServer[];
|
|
8
|
+
|
|
9
|
+
components: ISwaggerComponents;
|
|
10
|
+
paths: Record<string, ISwagger.IPath>;
|
|
11
|
+
security?: Record<string, string[]>[];
|
|
12
|
+
}
|
|
13
|
+
export namespace ISwagger {
|
|
14
|
+
export interface IServer {
|
|
15
|
+
url: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IInfo {
|
|
19
|
+
version: string;
|
|
20
|
+
title: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
}
|
|
23
|
+
export type IPath = Record<string, ISwaggerRoute>;
|
|
24
|
+
}
|