@nestia/migrate 0.9.6 → 0.10.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.
Files changed (53) hide show
  1. package/lib/MigrateApplication.js +367 -197
  2. package/lib/MigrateApplication.js.map +1 -1
  3. package/lib/analyzers/MigrateControllerAnalyzer.js +5 -0
  4. package/lib/analyzers/MigrateControllerAnalyzer.js.map +1 -1
  5. package/lib/analyzers/MigrateMethodAnalyzer.js +121 -36
  6. package/lib/analyzers/MigrateMethodAnalyzer.js.map +1 -1
  7. package/lib/bundles/NEST_TEMPLATE.js +2 -2
  8. package/lib/bundles/SDK_TEMPLATE.js +1 -1
  9. package/lib/programmers/MigrateSchemaProgrammer.js +15 -13
  10. package/lib/programmers/MigrateSchemaProgrammer.js.map +1 -1
  11. package/lib/structures/ISwagger.d.ts +1 -1
  12. package/lib/structures/ISwaggerComponents.d.ts +7 -1
  13. package/lib/structures/ISwaggerRoute.d.ts +6 -41
  14. package/lib/structures/ISwaggerRouteBodyContent.d.ts +14 -0
  15. package/lib/structures/ISwaggerRouteBodyContent.js +3 -0
  16. package/lib/structures/ISwaggerRouteBodyContent.js.map +1 -0
  17. package/lib/structures/ISwaggerRouteHeader.d.ts +0 -0
  18. package/lib/structures/ISwaggerRouteHeader.js +2 -0
  19. package/lib/structures/ISwaggerRouteHeader.js.map +1 -0
  20. package/lib/structures/ISwaggerRouteParameter.d.ts +13 -0
  21. package/lib/structures/ISwaggerRouteParameter.js +3 -0
  22. package/lib/structures/ISwaggerRouteParameter.js.map +1 -0
  23. package/lib/structures/ISwaggerRouteRequestBody.d.ts +11 -0
  24. package/lib/structures/ISwaggerRouteRequestBody.js +3 -0
  25. package/lib/structures/ISwaggerRouteRequestBody.js.map +1 -0
  26. package/lib/structures/ISwaggerRouteResponse.d.ts +10 -0
  27. package/lib/structures/ISwaggerRouteResponse.js +3 -0
  28. package/lib/structures/ISwaggerRouteResponse.js.map +1 -0
  29. package/lib/utils/SwaggerComponentsExplorer.d.ts +9 -0
  30. package/lib/utils/SwaggerComponentsExplorer.js +29 -0
  31. package/lib/utils/SwaggerComponentsExplorer.js.map +1 -0
  32. package/lib/utils/SwaggerExplorer.d.ts +0 -0
  33. package/lib/utils/SwaggerExplorer.js +2 -0
  34. package/lib/utils/SwaggerExplorer.js.map +1 -0
  35. package/lib/utils/SwaggerTypeChecker.d.ts +2 -2
  36. package/lib/utils/SwaggerTypeChecker.js +25 -25
  37. package/lib/utils/SwaggerTypeChecker.js.map +1 -1
  38. package/package.json +2 -2
  39. package/src/analyzers/MigrateControllerAnalyzer.ts +7 -0
  40. package/src/analyzers/MigrateMethodAnalyzer.ts +147 -71
  41. package/src/bundles/NEST_TEMPLATE.ts +2 -2
  42. package/src/bundles/SDK_TEMPLATE.ts +1 -1
  43. package/src/programmers/MigrateSchemaProgrammer.ts +19 -16
  44. package/src/structures/ISwagger.ts +4 -1
  45. package/src/structures/ISwaggerComponents.ts +7 -1
  46. package/src/structures/ISwaggerRoute.ts +9 -44
  47. package/src/structures/ISwaggerRouteBodyContent.ts +15 -0
  48. package/src/structures/ISwaggerRouteHeader.ts +0 -0
  49. package/src/structures/ISwaggerRouteParameter.ts +14 -0
  50. package/src/structures/ISwaggerRouteRequestBody.ts +12 -0
  51. package/src/structures/ISwaggerRouteResponse.ts +11 -0
  52. package/src/utils/SwaggerComponentsExplorer.ts +43 -0
  53. package/src/utils/SwaggerTypeChecker.ts +5 -5
@@ -1,12 +1,17 @@
1
+ import typia from "typia";
1
2
  import { Escaper } from "typia/lib/utils/Escaper";
2
3
 
3
4
  import { IMigrateProgram } from "../structures/IMigrateProgram";
4
5
  import { IMigrateRoute } from "../structures/IMigrateRoute";
5
6
  import { ISwagger } from "../structures/ISwagger";
6
7
  import { ISwaggerRoute } from "../structures/ISwaggerRoute";
8
+ import { ISwaggerRouteBodyContent } from "../structures/ISwaggerRouteBodyContent";
9
+ import { ISwaggerRouteParameter } from "../structures/ISwaggerRouteParameter";
10
+ import { ISwaggerRouteResponse } from "../structures/ISwaggerRouteResponse";
7
11
  import { ISwaggerSchema } from "../structures/ISwaggerSchema";
8
12
  import { StringUtil } from "../utils/StringUtil";
9
- import { SwaggerSwaggerChecker } from "../utils/SwaggerTypeChecker";
13
+ import { SwaggerComponentsExplorer } from "../utils/SwaggerComponentsExplorer";
14
+ import { SwaggerTypeChecker } from "../utils/SwaggerTypeChecker";
10
15
 
11
16
  export namespace MigrateMethodAnalzyer {
12
17
  export const analyze =
@@ -19,12 +24,46 @@ export namespace MigrateMethodAnalzyer {
19
24
  const success = emplaceBodySchema("response")(
20
25
  emplaceReference(props.swagger)("response"),
21
26
  )(
22
- route.responses?.["201"] ??
23
- route.responses?.["200"] ??
24
- route.responses?.default,
27
+ (() => {
28
+ const response =
29
+ route.responses?.["201"] ??
30
+ route.responses?.["200"] ??
31
+ route.responses?.default;
32
+ if (response === undefined) return undefined;
33
+ SwaggerComponentsExplorer.getResponse(props.swagger.components)(
34
+ response,
35
+ ) ?? undefined;
36
+ })(),
25
37
  );
26
38
 
27
39
  const failures: string[] = [];
40
+ for (const p of route.parameters ?? [])
41
+ if (
42
+ SwaggerComponentsExplorer.getParameter(props.swagger.components)(
43
+ p,
44
+ ) === null
45
+ )
46
+ failures.push(
47
+ `parameter "${(p as ISwaggerRouteParameter.IReference).$ref}" is not defined in "components.parameters".`,
48
+ );
49
+ for (const value of Object.values(route.responses ?? {}))
50
+ if (
51
+ SwaggerComponentsExplorer.getResponse(props.swagger.components)(
52
+ value,
53
+ ) === null
54
+ )
55
+ failures.push(
56
+ `response "${(value as ISwaggerRouteResponse.IReference).$ref}" is not defined in "components.responses".`,
57
+ );
58
+ if (
59
+ route.requestBody &&
60
+ SwaggerComponentsExplorer.getRequestBody(props.swagger.components)(
61
+ route.requestBody,
62
+ ) === null
63
+ )
64
+ failures.push(
65
+ `requestBody "${(route.requestBody as ISwaggerRouteParameter.IReference).$ref}" is not defined in "components.requestBodies".`,
66
+ );
28
67
  if (body === false)
29
68
  failures.push(
30
69
  `supports only "application/json", "application/x-www-form-urlencoded", "multipart/form-data" and "text/plain" content type in the request body.`,
@@ -39,17 +78,27 @@ export namespace MigrateMethodAnalzyer {
39
78
  );
40
79
 
41
80
  const [headers, query] = ["header", "query"].map((type) => {
42
- const parameters = (route.parameters ?? []).filter(
43
- (p) => p.in === type,
44
- );
81
+ const parameters: ISwaggerRouteParameter[] = (route.parameters ?? [])
82
+ .filter(
83
+ (p) =>
84
+ SwaggerComponentsExplorer.getParameter(props.swagger.components)(
85
+ p,
86
+ )?.in === type,
87
+ )
88
+ .map(
89
+ (p) =>
90
+ SwaggerComponentsExplorer.getParameter(props.swagger.components)(
91
+ p,
92
+ )!,
93
+ );
45
94
  if (parameters.length === 0) return null;
46
95
 
47
96
  const objects = parameters
48
97
  .map((p) =>
49
- SwaggerSwaggerChecker.isObject(p.schema)
98
+ SwaggerTypeChecker.isObject(p.schema)
50
99
  ? p.schema
51
- : SwaggerSwaggerChecker.isReference(p.schema) &&
52
- SwaggerSwaggerChecker.isObject(
100
+ : SwaggerTypeChecker.isReference(p.schema) &&
101
+ SwaggerTypeChecker.isObject(
53
102
  (props.swagger.components.schemas ?? {})[
54
103
  p.schema.$ref.replace(`#/components/schemas/`, ``)
55
104
  ] ?? {},
@@ -60,11 +109,11 @@ export namespace MigrateMethodAnalzyer {
60
109
  .filter((s) => !!s);
61
110
  const primitives = parameters.filter(
62
111
  (p) =>
63
- SwaggerSwaggerChecker.isBoolean(p.schema) ||
64
- SwaggerSwaggerChecker.isNumber(p.schema) ||
65
- SwaggerSwaggerChecker.isInteger(p.schema) ||
66
- SwaggerSwaggerChecker.isString(p.schema) ||
67
- SwaggerSwaggerChecker.isArray(p.schema),
112
+ SwaggerTypeChecker.isBoolean(p.schema) ||
113
+ SwaggerTypeChecker.isNumber(p.schema) ||
114
+ SwaggerTypeChecker.isInteger(p.schema) ||
115
+ SwaggerTypeChecker.isString(p.schema) ||
116
+ SwaggerTypeChecker.isArray(p.schema),
68
117
  );
69
118
  if (objects.length === 1 && primitives.length === 0) return objects[0];
70
119
  else if (objects.length > 1) {
@@ -75,7 +124,7 @@ export namespace MigrateMethodAnalzyer {
75
124
  }
76
125
 
77
126
  const dto: ISwaggerSchema.IObject | null = objects[0]
78
- ? SwaggerSwaggerChecker.isObject(objects[0])
127
+ ? SwaggerTypeChecker.isObject(objects[0])
79
128
  ? objects[0]
80
129
  : ((props.swagger.components.schemas ?? {})[
81
130
  (objects[0] as ISwaggerSchema.IReference).$ref.replace(
@@ -86,7 +135,7 @@ export namespace MigrateMethodAnalzyer {
86
135
  : null;
87
136
  const entire: ISwaggerSchema.IObject[] = [
88
137
  ...objects.map((o) =>
89
- SwaggerSwaggerChecker.isObject(o)
138
+ SwaggerTypeChecker.isObject(o)
90
139
  ? o
91
140
  : (props.swagger.components.schemas?.[
92
141
  o.$ref.replace(`#/components/schemas/`, ``)
@@ -152,7 +201,11 @@ export namespace MigrateMethodAnalzyer {
152
201
  );
153
202
  if (
154
203
  parameterNames.length !==
155
- (route.parameters ?? []).filter((p) => p.in === "path").length
204
+ (route.parameters ?? []).filter(
205
+ (p) =>
206
+ SwaggerComponentsExplorer.getParameter(props.swagger.components)(p)
207
+ ?.in === "path",
208
+ ).length
156
209
  )
157
210
  failures.push(
158
211
  "number of path parameters are not matched with its full path.",
@@ -179,7 +232,10 @@ export namespace MigrateMethodAnalzyer {
179
232
  }
180
233
  : null,
181
234
  parameters: (route.parameters ?? [])
182
- .filter((p) => p.in === "path")
235
+ .map((p) =>
236
+ SwaggerComponentsExplorer.getParameter(props.swagger.components)(p),
237
+ )
238
+ .filter((p) => p !== null && p.in === "path")
183
239
  .map((p, i) => ({
184
240
  name: parameterNames[i],
185
241
  key: (() => {
@@ -191,8 +247,8 @@ export namespace MigrateMethodAnalzyer {
191
247
  }
192
248
  })(),
193
249
  schema: {
194
- ...p.schema,
195
- description: p.schema.description ?? p.description,
250
+ ...p!.schema,
251
+ description: p!.schema.description ?? p!.description,
196
252
  },
197
253
  })),
198
254
  query: query
@@ -211,74 +267,94 @@ export namespace MigrateMethodAnalzyer {
211
267
  key !== "200" &&
212
268
  key !== "201" &&
213
269
  key !== "default" &&
214
- !!value.content?.["application/json"],
270
+ !!SwaggerComponentsExplorer.getResponse(
271
+ props.swagger.components,
272
+ )(value)?.content?.["application/json"],
215
273
  )
216
- .map(([key, value]) => [
217
- key,
218
- {
219
- description: value.description,
220
- schema: value.content?.["application/json"]?.schema ?? {},
221
- },
222
- ]),
274
+ .map(([key, value]) => {
275
+ const r = SwaggerComponentsExplorer.getResponse(
276
+ props.swagger.components,
277
+ )(value)!;
278
+ return [
279
+ key,
280
+ {
281
+ description: r.description,
282
+ schema: r.content?.["application/json"]?.schema ?? {},
283
+ },
284
+ ];
285
+ }),
223
286
  ),
224
287
  deprecated: route.deprecated ?? false,
225
- comment: () => describe(route),
288
+ comment: () => describe(props.swagger)(route),
226
289
  tags: route.tags ?? [],
227
290
  };
228
291
  };
229
292
 
230
- const describe = (route: ISwaggerRoute): string => {
231
- const commentTags: string[] = [];
232
- const add = (text: string) => {
233
- if (commentTags.every((line) => line !== text)) commentTags.push(text);
234
- };
293
+ const describe =
294
+ (swagger: ISwagger) =>
295
+ (route: ISwaggerRoute): string => {
296
+ const commentTags: string[] = [];
297
+ const add = (text: string) => {
298
+ if (commentTags.every((line) => line !== text)) commentTags.push(text);
299
+ };
235
300
 
236
- let description: string = route.description ?? "";
237
- if (route.summary) {
238
- const emended: string = route.summary.endsWith(".")
239
- ? route.summary
240
- : route.summary + ".";
241
- if (
242
- !!description.length &&
243
- !description.startsWith(route.summary) &&
244
- !route["x-nestia-jsDocTags"]?.some((t) => t.name === "summary")
245
- )
246
- description = `${emended}\n${description}`;
247
- }
248
- for (const p of route.parameters ?? [])
249
- if (p.description) add(`@param ${p.name} ${p.description}`);
250
- if (route.requestBody?.description)
251
- add(`@param body ${route.requestBody.description}`);
252
- for (const security of route.security ?? [])
253
- for (const [name, scopes] of Object.entries(security))
254
- add(`@security ${[name, ...scopes].join("")}`);
255
- if (route.tags) route.tags.forEach((name) => add(`@tag ${name}`));
256
- if (route.deprecated) add("@deprecated");
257
- return description.length
258
- ? commentTags.length
259
- ? `${description}\n\n${commentTags.join("\n")}`
260
- : description
261
- : commentTags.join("\n");
262
- };
301
+ let description: string = route.description ?? "";
302
+ if (route.summary) {
303
+ const emended: string = route.summary.endsWith(".")
304
+ ? route.summary
305
+ : route.summary + ".";
306
+ if (
307
+ !!description.length &&
308
+ !description.startsWith(route.summary) &&
309
+ !route["x-nestia-jsDocTags"]?.some((t) => t.name === "summary")
310
+ )
311
+ description = `${emended}\n${description}`;
312
+ }
313
+ for (const p of route.parameters ?? []) {
314
+ const param: ISwaggerRouteParameter | null = (() => {
315
+ if (!typia.is<ISwaggerRouteParameter.IReference>(p))
316
+ return typia.is<ISwaggerRouteParameter>(p) ? p : null;
317
+ return (
318
+ swagger.components.parameters?.[
319
+ p.$ref.replace(`#/components/parameters/`, ``)
320
+ ] ?? null
321
+ );
322
+ })();
323
+ if (param !== null && param.description)
324
+ add(`@param ${param.name} ${param.description}`);
325
+ }
326
+ if (route.requestBody?.description)
327
+ add(`@param body ${route.requestBody.description}`);
328
+ for (const security of route.security ?? [])
329
+ for (const [name, scopes] of Object.entries(security))
330
+ add(`@security ${[name, ...scopes].join("")}`);
331
+ if (route.tags) route.tags.forEach((name) => add(`@tag ${name}`));
332
+ if (route.deprecated) add("@deprecated");
333
+ return description.length
334
+ ? commentTags.length
335
+ ? `${description}\n\n${commentTags.join("\n")}`
336
+ : description
337
+ : commentTags.join("\n");
338
+ };
263
339
 
264
340
  const isNotObjectLiteral = (schema: ISwaggerSchema): boolean =>
265
- SwaggerSwaggerChecker.isReference(schema) ||
266
- SwaggerSwaggerChecker.isBoolean(schema) ||
267
- SwaggerSwaggerChecker.isNumber(schema) ||
268
- SwaggerSwaggerChecker.isString(schema) ||
269
- SwaggerSwaggerChecker.isUnknown(schema) ||
270
- (SwaggerSwaggerChecker.isAnyOf(schema) &&
341
+ SwaggerTypeChecker.isReference(schema) ||
342
+ SwaggerTypeChecker.isBoolean(schema) ||
343
+ SwaggerTypeChecker.isNumber(schema) ||
344
+ SwaggerTypeChecker.isString(schema) ||
345
+ SwaggerTypeChecker.isUnknown(schema) ||
346
+ (SwaggerTypeChecker.isAnyOf(schema) &&
271
347
  schema.anyOf.every(isNotObjectLiteral)) ||
272
- (SwaggerSwaggerChecker.isOneOf(schema) &&
348
+ (SwaggerTypeChecker.isOneOf(schema) &&
273
349
  schema.oneOf.every(isNotObjectLiteral)) ||
274
- (SwaggerSwaggerChecker.isArray(schema) && isNotObjectLiteral(schema.items));
350
+ (SwaggerTypeChecker.isArray(schema) && isNotObjectLiteral(schema.items));
275
351
 
276
352
  const emplaceBodySchema =
277
353
  (from: "request" | "response") =>
278
354
  (emplacer: (schema: ISwaggerSchema) => ISwaggerSchema.IReference) =>
279
355
  (meta?: {
280
356
  description?: string;
281
- content?: ISwaggerRoute.IContent;
357
+ content?: ISwaggerRouteBodyContent;
282
358
  "x-nestia-encrypted"?: boolean;
283
359
  }): false | null | IMigrateRoute.IBody => {
284
360
  if (!meta?.content) return null;
@@ -47,7 +47,7 @@ export const NEST_TEMPLATE = [
47
47
  {
48
48
  "location": "",
49
49
  "file": "package.json",
50
- "content": "{\r\n \"private\": true,\r\n \"name\": \"@ORGANIZATION/PROJECT\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"Starter kit of Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"scripts\": {\r\n \"test\": \"node bin/test\",\r\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\r\n \"------------------------BUILDS------------------------\": \"\",\r\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\r\n \"build:api\": \"rimraf packages/api/lib && npm run build:sdk && tsc -p packages/api/tsconfig.json\",\r\n \"build:main\": \"rimraf lib && tsc\",\r\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\r\n \"build:swagger\": \"npx nestia swagger\",\r\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"eslint\": \"eslint src && eslint test\",\r\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"prettier\": \"prettier src --write && prettier test --write\",\r\n \"------------------------WEBPACK------------------------\": \"\",\r\n \"webpack\": \"rimraf dist && webpack\",\r\n \"webpack:start\": \"cd dist && node dist/server\",\r\n \"------------------------DEPLOYS------------------------\": \"\",\r\n \"package:api\": \"npm run build:swagger && npm run build:api && cd packages/api && npm publish\",\r\n \"start\": \"node lib/executable/server\",\r\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia-start\"\r\n },\r\n \"keywords\": [\r\n \"nestia\",\r\n \"template\",\r\n \"boilerplate\"\r\n ],\r\n \"author\": \"AUTHOR\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\r\n },\r\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.4.1\",\r\n \"@nestia/sdk\": \"^2.5.15\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/cli\": \"^0.11.21\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"^8.2.5\",\r\n \"@types/node\": \"^18.11.0\",\r\n \"@types/uuid\": \"^8.3.4\",\r\n \"@typescript-eslint/eslint-plugin\": \"^6.19.1\",\r\n \"@typescript-eslint/parser\": \"^6.19.1\",\r\n \"chalk\": \"^4.1.0\",\r\n \"cli\": \"^1.0.1\",\r\n \"copy-webpack-plugin\": \"^11.0.0\",\r\n \"eslint-plugin-deprecation\": \"^2.0.0\",\r\n \"express\": \"^4.18.2\",\r\n \"nestia\": \"^5.3.0\",\r\n \"prettier\": \"^3.2.4\",\r\n \"prettier-plugin-prisma\": \"^5.0.0\",\r\n \"rimraf\": \"^3.0.2\",\r\n \"source-map-support\": \"^0.5.21\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-loader\": \"^9.5.1\",\r\n \"ts-node\": \"^10.9.1\",\r\n \"ts-patch\": \"^3.0.2\",\r\n \"typescript\": \"^5.3.2\",\r\n \"typescript-transform-paths\": \"^3.4.6\",\r\n \"webpack\": \"^5.89.0\",\r\n \"webpack-cli\": \"^5.1.4\",\r\n \"write-file-webpack-plugin\": \"^4.5.1\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/core\": \"^2.5.15\",\r\n \"@nestia/fetcher\": \"^2.5.15\",\r\n \"@nestjs/common\": \"^10.3.3\",\r\n \"@nestjs/core\": \"^10.3.3\",\r\n \"@nestjs/platform-express\": \"^10.3.3\",\r\n \"commander\": \"10.0.0\",\r\n \"dotenv\": \"^16.3.1\",\r\n \"dotenv-expand\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"serialize-error\": \"^4.1.0\",\r\n \"tstl\": \"^2.5.13\",\r\n \"typia\": \"^5.5.3\",\r\n \"uuid\": \"^9.0.0\"\r\n },\r\n \"stackblitz\": {\r\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test\"\r\n }\r\n}"
50
+ "content": "{\r\n \"private\": true,\r\n \"name\": \"@ORGANIZATION/PROJECT\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"Starter kit of Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"scripts\": {\r\n \"test\": \"node bin/test\",\r\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\r\n \"------------------------BUILDS------------------------\": \"\",\r\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\r\n \"build:api\": \"rimraf packages/api/lib && npm run build:sdk && tsc -p packages/api/tsconfig.json\",\r\n \"build:main\": \"rimraf lib && tsc\",\r\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\r\n \"build:swagger\": \"npx nestia swagger\",\r\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"eslint\": \"eslint src && eslint test\",\r\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"prettier\": \"prettier src --write && prettier test --write\",\r\n \"------------------------WEBPACK------------------------\": \"\",\r\n \"webpack\": \"rimraf dist && webpack\",\r\n \"webpack:start\": \"cd dist && node dist/server\",\r\n \"------------------------DEPLOYS------------------------\": \"\",\r\n \"package:api\": \"npm run build:swagger && npm run build:api && cd packages/api && npm publish\",\r\n \"start\": \"node lib/executable/server\",\r\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia-start\"\r\n },\r\n \"keywords\": [\r\n \"nestia\",\r\n \"template\",\r\n \"boilerplate\"\r\n ],\r\n \"author\": \"AUTHOR\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\r\n },\r\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.4.2\",\r\n \"@nestia/sdk\": \"^2.5.16\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/cli\": \"^0.11.21\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"^8.2.5\",\r\n \"@types/node\": \"^18.11.0\",\r\n \"@types/uuid\": \"^8.3.4\",\r\n \"@typescript-eslint/eslint-plugin\": \"^6.19.1\",\r\n \"@typescript-eslint/parser\": \"^6.19.1\",\r\n \"chalk\": \"^4.1.0\",\r\n \"cli\": \"^1.0.1\",\r\n \"copy-webpack-plugin\": \"^11.0.0\",\r\n \"eslint-plugin-deprecation\": \"^2.0.0\",\r\n \"express\": \"^4.18.2\",\r\n \"nestia\": \"^5.3.0\",\r\n \"prettier\": \"^3.2.4\",\r\n \"prettier-plugin-prisma\": \"^5.0.0\",\r\n \"rimraf\": \"^3.0.2\",\r\n \"source-map-support\": \"^0.5.21\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-loader\": \"^9.5.1\",\r\n \"ts-node\": \"^10.9.1\",\r\n \"ts-patch\": \"^3.0.2\",\r\n \"typescript\": \"^5.3.2\",\r\n \"typescript-transform-paths\": \"^3.4.6\",\r\n \"webpack\": \"^5.89.0\",\r\n \"webpack-cli\": \"^5.1.4\",\r\n \"write-file-webpack-plugin\": \"^4.5.1\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/core\": \"^2.5.16\",\r\n \"@nestia/fetcher\": \"^2.5.16\",\r\n \"@nestjs/common\": \"^10.3.5\",\r\n \"@nestjs/core\": \"^10.3.5\",\r\n \"@nestjs/platform-express\": \"^10.3.5\",\r\n \"commander\": \"10.0.0\",\r\n \"dotenv\": \"^16.3.1\",\r\n \"dotenv-expand\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"serialize-error\": \"^4.1.0\",\r\n \"tstl\": \"^2.5.13\",\r\n \"typia\": \"^5.5.7\",\r\n \"uuid\": \"^9.0.0\"\r\n },\r\n \"stackblitz\": {\r\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test\"\r\n }\r\n}"
51
51
  },
52
52
  {
53
53
  "location": "packages/api",
@@ -62,7 +62,7 @@ export const NEST_TEMPLATE = [
62
62
  {
63
63
  "location": "packages/api",
64
64
  "file": "package.json",
65
- "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"npm run build:sdk && npm run compile\",\r\n \"build:sdk\": \"rimraf ../../src/api/functional && cd ../.. && npx nestia sdk && cd packages/api\",\r\n \"compile\": \"rimraf lib && tsc\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"prepare\": \"ts-patch install && typia patch\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"devDependencies\": {\r\n \"rimraf\": \"^5.0.5\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.1.2\",\r\n \"typescript\": \"^5.3.3\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^2.5.15\",\r\n \"typia\": \"^5.5.3\"\r\n }\r\n}"
65
+ "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"npm run build:sdk && npm run compile\",\r\n \"build:sdk\": \"rimraf ../../src/api/functional && cd ../.. && npx nestia sdk && cd packages/api\",\r\n \"compile\": \"rimraf lib && tsc\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"prepare\": \"ts-patch install && typia patch\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"devDependencies\": {\r\n \"rimraf\": \"^5.0.5\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.1.2\",\r\n \"typescript\": \"^5.3.3\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^2.5.16\",\r\n \"typia\": \"^5.5.7\"\r\n }\r\n}"
66
66
  },
67
67
  {
68
68
  "location": "packages/api",
@@ -22,7 +22,7 @@ export const SDK_TEMPLATE = [
22
22
  {
23
23
  "location": "",
24
24
  "file": "package.json",
25
- "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"rimraf lib && tsc\",\r\n \"build:test\": \"rimraf bin && tsc --project test/tsconfig.json\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"start\": \"npx ts-node test/start.ts\",\r\n \"test\": \"npx ts-node test/index.ts\",\r\n \"test:simulate\": \"npx ts-node test/index.ts --simulate true\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.4.1\",\r\n \"@types/inquirer\": \"8.2.5\",\r\n \"commander\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"prettier\": \"^3.2.5\",\r\n \"rimraf\": \"^5.0.5\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.1.2\",\r\n \"typescript\": \"^5.3.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^2.5.15\",\r\n \"typia\": \"^5.5.3\"\r\n }\r\n}"
25
+ "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"rimraf lib && tsc\",\r\n \"build:test\": \"rimraf bin && tsc --project test/tsconfig.json\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"start\": \"npx ts-node test/start.ts\",\r\n \"test\": \"npx ts-node test/index.ts\",\r\n \"test:simulate\": \"npx ts-node test/index.ts --simulate true\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.4.1\",\r\n \"@types/inquirer\": \"8.2.5\",\r\n \"commander\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"prettier\": \"^3.2.5\",\r\n \"rimraf\": \"^5.0.5\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.1.2\",\r\n \"typescript\": \"^5.3.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^2.5.16\",\r\n \"typia\": \"^5.5.7\"\r\n }\r\n}"
26
26
  },
27
27
  {
28
28
  "location": "",
@@ -7,7 +7,7 @@ import { Escaper } from "typia/lib/utils/Escaper";
7
7
  import { ISwaggerComponents } from "../structures/ISwaggerComponents";
8
8
  import { ISwaggerSchema } from "../structures/ISwaggerSchema";
9
9
  import { FilePrinter } from "../utils/FilePrinter";
10
- import { SwaggerSwaggerChecker } from "../utils/SwaggerTypeChecker";
10
+ import { SwaggerTypeChecker } from "../utils/SwaggerTypeChecker";
11
11
  import { MigrateImportProgrammer } from "./MigrateImportProgrammer";
12
12
 
13
13
  export namespace MigrateSchemaProgrammer {
@@ -19,34 +19,32 @@ export namespace MigrateSchemaProgrammer {
19
19
  (importer: MigrateImportProgrammer) =>
20
20
  (schema: ISwaggerSchema): ts.TypeNode => {
21
21
  const union: ts.TypeNode[] = [];
22
- if (SwaggerSwaggerChecker.isUnknown(schema))
22
+ if (SwaggerTypeChecker.isUnknown(schema))
23
23
  return TypeFactory.keyword("any");
24
- else if (SwaggerSwaggerChecker.isNullOnly(schema))
25
- return createNode("null");
26
- else if (SwaggerSwaggerChecker.isNullable(components)(schema))
24
+ else if (SwaggerTypeChecker.isNullOnly(schema)) return createNode("null");
25
+ else if (SwaggerTypeChecker.isNullable(components)(schema))
27
26
  union.push(createNode("null"));
28
27
 
29
28
  const type: ts.TypeNode = (() => {
30
29
  // ATOMIC
31
- if (SwaggerSwaggerChecker.isBoolean(schema))
32
- return writeBoolean(schema);
33
- else if (SwaggerSwaggerChecker.isInteger(schema))
30
+ if (SwaggerTypeChecker.isBoolean(schema)) return writeBoolean(schema);
31
+ else if (SwaggerTypeChecker.isInteger(schema))
34
32
  return writeInteger(importer)(schema);
35
- else if (SwaggerSwaggerChecker.isNumber(schema))
33
+ else if (SwaggerTypeChecker.isNumber(schema))
36
34
  return writeNumber(importer)(schema);
37
35
  // INSTANCES
38
- else if (SwaggerSwaggerChecker.isString(schema))
36
+ else if (SwaggerTypeChecker.isString(schema))
39
37
  return writeString(importer)(schema);
40
- else if (SwaggerSwaggerChecker.isArray(schema))
38
+ else if (SwaggerTypeChecker.isArray(schema))
41
39
  return writeArray(components)(importer)(schema);
42
- else if (SwaggerSwaggerChecker.isObject(schema))
40
+ else if (SwaggerTypeChecker.isObject(schema))
43
41
  return writeObject(components)(importer)(schema);
44
- else if (SwaggerSwaggerChecker.isReference(schema))
42
+ else if (SwaggerTypeChecker.isReference(schema))
45
43
  return writeReference(components)(importer)(schema);
46
44
  // NESTED UNION
47
- else if (SwaggerSwaggerChecker.isAnyOf(schema))
45
+ else if (SwaggerTypeChecker.isAnyOf(schema))
48
46
  return writeUnion(components)(importer)(schema.anyOf);
49
- else if (SwaggerSwaggerChecker.isOneOf(schema))
47
+ else if (SwaggerTypeChecker.isOneOf(schema))
50
48
  return writeUnion(components)(importer)(schema.oneOf);
51
49
  else return TypeFactory.keyword("any");
52
50
  })();
@@ -236,10 +234,15 @@ export namespace MigrateSchemaProgrammer {
236
234
  (
237
235
  schema: ISwaggerSchema.IReference,
238
236
  ): ts.TypeReferenceNode | ts.KeywordTypeNode => {
237
+ if (schema.$ref.startsWith("#/components/schemas") === false)
238
+ return TypeFactory.keyword("any");
239
239
  const name: string = schema.$ref.split("/").at(-1)!;
240
240
  return name === ""
241
241
  ? TypeFactory.keyword("any")
242
- : importer.dto(schema.$ref.split("/").at(-1)!, components.namespace);
242
+ : importer.dto(
243
+ schema.$ref.split("/").at(-1)!,
244
+ components["x-nestia-namespace"],
245
+ );
243
246
  };
244
247
 
245
248
  /* -----------------------------------------------------------
@@ -16,5 +16,8 @@ export namespace ISwagger {
16
16
  url: string;
17
17
  description?: string;
18
18
  }
19
- export type IPath = Record<string, ISwaggerRoute>;
19
+ export type IPath = Record<
20
+ "get" | "post" | "patch" | "put" | "delete",
21
+ ISwaggerRoute | undefined
22
+ >;
20
23
  }
@@ -1,8 +1,14 @@
1
+ import { ISwaggerRouteParameter } from "./ISwaggerRouteParameter";
2
+ import { ISwaggerRouteRequestBody } from "./ISwaggerRouteRequestBody";
3
+ import { ISwaggerRouteResponse } from "./ISwaggerRouteResponse";
1
4
  import { ISwaggerSchema } from "./ISwaggerSchema";
2
5
  import { ISwaggerSecurityScheme } from "./ISwaggerSecurityScheme";
3
6
 
4
7
  export interface ISwaggerComponents {
8
+ parameters?: Record<string, ISwaggerRouteParameter>;
9
+ requestBodies?: Record<string, ISwaggerRouteRequestBody>;
10
+ responses?: Record<string, ISwaggerRouteResponse>;
5
11
  schemas?: Record<string, ISwaggerSchema>;
6
12
  securitySchemes?: Record<string, ISwaggerSecurityScheme>;
7
- namespace?: string;
13
+ "x-nestia-namespace"?: string;
8
14
  }
@@ -1,11 +1,16 @@
1
1
  import { IJsDocTagInfo } from "typia/lib/schemas/metadata/IJsDocTagInfo";
2
2
 
3
- import { ISwaggerSchema } from "./ISwaggerSchema";
3
+ import { ISwaggerRouteParameter } from "./ISwaggerRouteParameter";
4
+ import { ISwaggerRouteRequestBody } from "./ISwaggerRouteRequestBody";
5
+ import { ISwaggerRouteResponse } from "./ISwaggerRouteResponse";
4
6
 
5
7
  export interface ISwaggerRoute {
6
- parameters?: ISwaggerRoute.IParameter[];
7
- requestBody?: ISwaggerRoute.IRequestBody;
8
- responses?: ISwaggerRoute.IResponseBody;
8
+ parameters?: (ISwaggerRouteParameter | ISwaggerRouteParameter.IReference)[];
9
+ requestBody?: ISwaggerRouteRequestBody;
10
+ responses?: Record<
11
+ string,
12
+ ISwaggerRouteResponse | ISwaggerRouteResponse.IReference
13
+ >;
9
14
  summary?: string;
10
15
  description?: string;
11
16
  deprecated?: boolean;
@@ -13,43 +18,3 @@ export interface ISwaggerRoute {
13
18
  tags?: string[];
14
19
  "x-nestia-jsDocTags"?: IJsDocTagInfo[];
15
20
  }
16
- export namespace ISwaggerRoute {
17
- export interface IParameter {
18
- name?: string;
19
- in: "path" | "query" | "header" | "cookie";
20
- schema: ISwaggerSchema;
21
- required?: boolean;
22
- description?: string;
23
- }
24
- export interface IRequestBody {
25
- description?: string;
26
- content: IContent;
27
- required?: boolean;
28
- "x-nestia-encrypted"?: boolean;
29
- }
30
- export type IResponseBody = Record<
31
- string,
32
- {
33
- description?: string;
34
- content?: IContent;
35
- "x-nestia-encrypted"?: boolean;
36
- }
37
- >;
38
- export interface IContent {
39
- "text/plain"?: {
40
- schema: ISwaggerSchema;
41
- };
42
- "application/json"?: {
43
- schema: ISwaggerSchema;
44
- };
45
- "application/x-www-form-urlencoded"?: {
46
- schema: ISwaggerSchema;
47
- };
48
- "multipart/form-data"?: {
49
- schema: ISwaggerSchema;
50
- };
51
- "*/*"?: {
52
- schema: ISwaggerSchema;
53
- };
54
- }
55
- }
@@ -0,0 +1,15 @@
1
+ import { ISwaggerSchema } from "./ISwaggerSchema";
2
+
3
+ export interface ISwaggerRouteBodyContent {
4
+ "text/plain"?: ISwaggerRouteBodyContent.IMediaType;
5
+ "application/json"?: ISwaggerRouteBodyContent.IMediaType;
6
+ "application/x-www-form-urlencoded"?: ISwaggerRouteBodyContent.IMediaType;
7
+ "multipart/form-data"?: ISwaggerRouteBodyContent.IMediaType;
8
+ "*/*"?: ISwaggerRouteBodyContent.IMediaType;
9
+ }
10
+ export namespace ISwaggerRouteBodyContent {
11
+ export interface IMediaType {
12
+ schema?: ISwaggerSchema;
13
+ "x-nestia-encrypted"?: boolean;
14
+ }
15
+ }
File without changes
@@ -0,0 +1,14 @@
1
+ import { ISwaggerSchema } from "./ISwaggerSchema";
2
+
3
+ export interface ISwaggerRouteParameter {
4
+ name?: string;
5
+ in: "path" | "query" | "header" | "cookie";
6
+ schema: ISwaggerSchema;
7
+ required?: boolean;
8
+ description?: string;
9
+ }
10
+ export namespace ISwaggerRouteParameter {
11
+ export interface IReference {
12
+ $ref: `#/components/parameters/${string}`;
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ import { ISwaggerRouteBodyContent } from "./ISwaggerRouteBodyContent";
2
+
3
+ export interface ISwaggerRouteRequestBody {
4
+ description?: string;
5
+ required?: boolean;
6
+ content?: ISwaggerRouteBodyContent;
7
+ }
8
+ export namespace ISwaggerRouteRequestBody {
9
+ export interface IReference {
10
+ $ref: `#/components/requestBodies/${string}`;
11
+ }
12
+ }
@@ -0,0 +1,11 @@
1
+ import { ISwaggerRouteBodyContent } from "./ISwaggerRouteBodyContent";
2
+
3
+ export interface ISwaggerRouteResponse {
4
+ description?: string;
5
+ content?: ISwaggerRouteBodyContent;
6
+ }
7
+ export namespace ISwaggerRouteResponse {
8
+ export interface IReference {
9
+ $ref: `#/components/responses/${string}`;
10
+ }
11
+ }