@nestia/sdk 2.0.0-dev.20230904-2 → 2.0.0-dev.20230906

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 (45) hide show
  1. package/lib/INestiaConfig.d.ts +8 -0
  2. package/lib/NestiaSdkApplication.d.ts +1 -1
  3. package/lib/NestiaSdkApplication.js +5 -5
  4. package/lib/NestiaSdkApplication.js.map +1 -1
  5. package/lib/analyses/ControllerAnalyzer.js +4 -4
  6. package/lib/analyses/ControllerAnalyzer.js.map +1 -1
  7. package/lib/analyses/ReflectAnalyzer.js +9 -1
  8. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  9. package/lib/executable/internal/NestiaConfigLoader.js +5 -1
  10. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  11. package/lib/generates/SdkGenerator.d.ts +2 -1
  12. package/lib/generates/SdkGenerator.js +5 -1
  13. package/lib/generates/SdkGenerator.js.map +1 -1
  14. package/lib/generates/SwaggerGenerator.js +9 -6
  15. package/lib/generates/SwaggerGenerator.js.map +1 -1
  16. package/lib/generates/internal/E2eFileProgrammer.js +15 -10
  17. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  18. package/lib/generates/internal/SdkDtoGenerator.d.ts +9 -0
  19. package/lib/generates/internal/SdkDtoGenerator.js +264 -0
  20. package/lib/generates/internal/SdkDtoGenerator.js.map +1 -0
  21. package/lib/generates/internal/SdkFileProgrammer.js +8 -7
  22. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  23. package/lib/generates/internal/SdkFunctionProgrammer.js +11 -7
  24. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  25. package/lib/generates/internal/SdkSimulationProgrammer.js +5 -1
  26. package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
  27. package/lib/generates/internal/SwaggerSchemaGenerator.js +2 -2
  28. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  29. package/lib/structures/IController.d.ts +2 -0
  30. package/lib/structures/IRoute.d.ts +5 -1
  31. package/package.json +5 -5
  32. package/src/INestiaConfig.ts +9 -0
  33. package/src/NestiaSdkApplication.ts +5 -9
  34. package/src/analyses/ControllerAnalyzer.ts +5 -5
  35. package/src/analyses/ReflectAnalyzer.ts +8 -0
  36. package/src/generates/SdkGenerator.ts +7 -0
  37. package/src/generates/SwaggerGenerator.ts +11 -7
  38. package/src/generates/internal/E2eFileProgrammer.ts +24 -11
  39. package/src/generates/internal/SdkDtoGenerator.ts +384 -0
  40. package/src/generates/internal/SdkFileProgrammer.ts +8 -7
  41. package/src/generates/internal/SdkFunctionProgrammer.ts +35 -7
  42. package/src/generates/internal/SdkSimulationProgrammer.ts +10 -1
  43. package/src/generates/internal/SwaggerSchemaGenerator.ts +2 -2
  44. package/src/structures/IController.ts +2 -0
  45. package/src/structures/IRoute.ts +7 -2
@@ -0,0 +1,384 @@
1
+ import fs from "fs";
2
+ import ts from "typescript";
3
+
4
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
5
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
6
+ import { IJsDocTagInfo } from "typia/lib/schemas/metadata/IJsDocTagInfo";
7
+ import { IMetadataTypeTag } from "typia/lib/schemas/metadata/IMetadataTypeTag";
8
+ import { Metadata } from "typia/lib/schemas/metadata/Metadata";
9
+ import { MetadataAlias } from "typia/lib/schemas/metadata/MetadataAlias";
10
+ import { MetadataArray } from "typia/lib/schemas/metadata/MetadataArray";
11
+ import { MetadataAtomic } from "typia/lib/schemas/metadata/MetadataAtomic";
12
+ import { MetadataConstant } from "typia/lib/schemas/metadata/MetadataConstant";
13
+ import { MetadataObject } from "typia/lib/schemas/metadata/MetadataObject";
14
+ import { MetadataProperty } from "typia/lib/schemas/metadata/MetadataProperty";
15
+ import { MetadataTuple } from "typia/lib/schemas/metadata/MetadataTuple";
16
+ import { Escaper } from "typia/lib/utils/Escaper";
17
+
18
+ import { INestiaConfig } from "../../INestiaConfig";
19
+ import { IRoute } from "../../structures/IRoute";
20
+ import { ImportDictionary } from "../../utils/ImportDictionary";
21
+ import { MapUtil } from "../../utils/MapUtil";
22
+
23
+ export namespace SdkDtoGenerator {
24
+ export const generate =
25
+ (checker: ts.TypeChecker) =>
26
+ (config: INestiaConfig) =>
27
+ async (routes: IRoute[]): Promise<void> => {
28
+ try {
29
+ await fs.promises.mkdir(`${config.output}/structures`);
30
+ } catch {}
31
+
32
+ const collection = new MetadataCollection({
33
+ replace: MetadataCollection.replace,
34
+ });
35
+ for (const r of routes) {
36
+ for (const p of r.parameters) {
37
+ const res = MetadataFactory.analyze(checker)({
38
+ escape: false,
39
+ constant: true,
40
+ absorb: false,
41
+ })(collection)(p.type);
42
+ if (res.success) p.metadata = res.data;
43
+ }
44
+ const res = MetadataFactory.analyze(checker)({
45
+ escape: true,
46
+ constant: true,
47
+ absorb: false,
48
+ })(collection)(r.output.type);
49
+ if (res.success) r.output.metadata = res.data;
50
+ }
51
+
52
+ const modules: Map<string, IModule> = new Map();
53
+ for (const alias of collection.aliases())
54
+ prepare(modules)(alias.name)((importer) =>
55
+ defineAlias(config)(importer)(alias),
56
+ );
57
+ for (const object of collection.objects())
58
+ prepare(modules)(object.name)((importer) =>
59
+ defineObject(config)(importer)(object),
60
+ );
61
+
62
+ for (const module of modules.values())
63
+ await generateFile(config)(module);
64
+ };
65
+
66
+ const prepare =
67
+ (dict: Map<string, IModule>) =>
68
+ (name: string) =>
69
+ (programmer: (importer: ImportDictionary) => string) => {
70
+ const accessors: string[] = name.split(".");
71
+ let module: IModule;
72
+
73
+ accessors.forEach((acc, i) => {
74
+ module = MapUtil.take(dict, acc, () => ({
75
+ name: accessors.slice(0, i + 1).join("."),
76
+ children: new Map(),
77
+ }));
78
+ module.programmer = programmer;
79
+ dict = module.children;
80
+ });
81
+ return module!;
82
+ };
83
+
84
+ const generateFile =
85
+ (config: INestiaConfig) =>
86
+ async (module: IModule): Promise<void> => {
87
+ const importer: ImportDictionary = new ImportDictionary();
88
+
89
+ const body: string = writeModule(importer)(module);
90
+ const content: string[] = [];
91
+ if (!importer.empty())
92
+ content.push(
93
+ importer.toScript(`${config.output}/structures`),
94
+ "",
95
+ );
96
+ content.push(body);
97
+
98
+ const location: string = `${config.output}/structures/${module.name}.ts`;
99
+ await fs.promises.writeFile(location, content.join("\n"), "utf8");
100
+ };
101
+
102
+ const writeModule =
103
+ (importer: ImportDictionary) =>
104
+ (module: IModule): string => {
105
+ const content: string[] = [];
106
+ if (module.programmer) content.push(module.programmer(importer));
107
+ if (module.children.size) {
108
+ content.push(
109
+ `export namespace ${module.name.split(".").at(-1)} {`,
110
+ );
111
+ for (const child of module.children.values())
112
+ content.push(
113
+ writeModule(importer)(child)
114
+ .split("\n")
115
+ .map((l) => ` ${l}`)
116
+ .join("\n"),
117
+ );
118
+ content.push("}");
119
+ }
120
+ return content.join("\n");
121
+ };
122
+
123
+ const defineAlias =
124
+ (config: INestiaConfig) =>
125
+ (importer: ImportDictionary) =>
126
+ (alias: MetadataAlias) =>
127
+ [
128
+ ...writeComment(alias.description, alias.jsDocTags),
129
+ `export type ${alias.name.split(".").pop()!} = ${decode(config)(
130
+ importer,
131
+ )(alias.value)};`,
132
+ ].join("\n");
133
+
134
+ const defineObject =
135
+ (config: INestiaConfig) =>
136
+ (importer: ImportDictionary) =>
137
+ (object: MetadataObject) => {
138
+ const top: string = [
139
+ ...writeComment(object.description ?? null, object.jsDocTags),
140
+ `export type ${object.name.split(".").pop()!} = `,
141
+ ].join("\n");
142
+ if (object.properties.length === 0) return top + "{};";
143
+
144
+ const regular: MetadataProperty[] = object.properties.filter((p) =>
145
+ p.key.isSoleLiteral(),
146
+ );
147
+ const dynamic: MetadataProperty[] = object.properties.filter(
148
+ (p) => !p.key.isSoleLiteral(),
149
+ );
150
+
151
+ const brackets: string[][] = [];
152
+ if (regular.length) {
153
+ const row: string[] = ["{"];
154
+ for (const p of regular) {
155
+ const key: string = p.key.constants[0].values[0] as string;
156
+ const identifier: string = Escaper.variable(key)
157
+ ? key
158
+ : JSON.stringify(key);
159
+ row.push(
160
+ ...writeComment(p.description, p.jsDocTags).map(
161
+ (l) => ` ${l}`,
162
+ ),
163
+ ` ${identifier}: ${decode(config)(importer)(
164
+ p.value,
165
+ )};`,
166
+ );
167
+ }
168
+ row.push("}");
169
+ brackets.push(row);
170
+ }
171
+ for (const p of dynamic) {
172
+ const row: string[] = ["{"];
173
+ row.push(
174
+ ...writeComment(p.description, p.jsDocTags).map(
175
+ (l) => ` ${l}`,
176
+ ),
177
+ ` [key: ${decode(config)(importer)(p.key)}]: ${decode(
178
+ config,
179
+ )(importer)(p.value)};`,
180
+ );
181
+ row.push("}");
182
+ brackets.push(row);
183
+ }
184
+ return top + brackets.map((row) => row.join("\n")).join(" & ");
185
+ };
186
+
187
+ const writeComment = (
188
+ description: string | null,
189
+ jsDocTags: IJsDocTagInfo[],
190
+ ): string[] => {
191
+ const lines: string[] = [];
192
+ if (description?.length)
193
+ lines.push(...description.split("\n").map((s) => `${s}`));
194
+ if (description?.length && jsDocTags?.length) lines.push("");
195
+ if (jsDocTags?.length)
196
+ lines.push(
197
+ ...jsDocTags.map((t) =>
198
+ t.text?.length
199
+ ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
200
+ : `@${t.name}`,
201
+ ),
202
+ );
203
+ if (lines.length === 0) return [];
204
+ return ["/**", ...lines.map((s) => ` * ${s}`), " */"];
205
+ };
206
+
207
+ export const decode =
208
+ (config: INestiaConfig) =>
209
+ (importer: ImportDictionary) =>
210
+ (meta: Metadata): string => {
211
+ const union: string[] = [];
212
+
213
+ // COALESCES
214
+ if (meta.nullable) union.push("null");
215
+ if (meta.required === false) union.push("undefined");
216
+
217
+ // ATOMICS
218
+ for (const atomic of meta.atomics)
219
+ union.push(decodeAtomic(importer)(atomic));
220
+ for (const constant of meta.constants)
221
+ union.push(decodeConstant(constant));
222
+ for (const tpl of meta.templates)
223
+ union.push(decodeTemplate(config)(importer)(tpl));
224
+
225
+ // ARRAYS
226
+ for (const array of meta.arrays)
227
+ union.push(decodeArray(config)(importer)(array));
228
+ for (const tuple of meta.tuples)
229
+ union.push(decodeTuple(config)(importer)(tuple));
230
+
231
+ // OBJECTS
232
+ for (const obj of meta.objects)
233
+ union.push(decodeObject(config)(importer)(obj));
234
+ for (const alias of meta.aliases)
235
+ union.push(decodeAlias(config)(importer)(alias));
236
+
237
+ return union.join(" | ");
238
+ };
239
+
240
+ const decodeTypeTag =
241
+ (importer: ImportDictionary) =>
242
+ (tag: IMetadataTypeTag): string => {
243
+ const front: string = tag.name.split("<")[0];
244
+ if (NATIVE_TYPE_TAGS.has(front)) {
245
+ importer.external({
246
+ type: true,
247
+ library: `typia/lib/tags/${front}`,
248
+ instance: front,
249
+ });
250
+ return tag.name;
251
+ }
252
+ importer.external({
253
+ type: true,
254
+ library: `typia/lib/tags/TagBase`,
255
+ instance: "TagBase",
256
+ });
257
+ return `TagBase<${JSON.stringify(tag)}>`;
258
+ };
259
+
260
+ const decodeTypeTagMatrix =
261
+ (importer: ImportDictionary) =>
262
+ (base: string, tags: IMetadataTypeTag[][]): string => {
263
+ if (tags.length === 0) return base;
264
+ else if (tags.length === 1)
265
+ return `(${base} & ${tags[0]
266
+ .map((t) => decodeTypeTag(importer)(t))
267
+ .join(" & ")})`;
268
+ return (
269
+ "(" +
270
+ [
271
+ base,
272
+ ...tags.map(
273
+ (row) =>
274
+ `(${row
275
+ .map((t) => decodeTypeTag(importer)(t))
276
+ .join(" & ")})`,
277
+ ),
278
+ ] +
279
+ ")"
280
+ );
281
+ };
282
+
283
+ const decodeAtomic =
284
+ (importer: ImportDictionary) =>
285
+ (atomic: MetadataAtomic): string =>
286
+ decodeTypeTagMatrix(importer)(atomic.type, atomic.tags);
287
+
288
+ const decodeTemplate =
289
+ (config: INestiaConfig) =>
290
+ (importer: ImportDictionary) =>
291
+ (template: Metadata[]): string =>
292
+ "`" +
293
+ template
294
+ .map((meta) =>
295
+ meta.size() === 1 &&
296
+ meta.isRequired() &&
297
+ meta.nullable === false &&
298
+ meta.constants.length === 1
299
+ ? String(meta.constants[0].values[0])
300
+ .split("`")
301
+ .join("\\`")
302
+ : `\${${decode(config)(importer)(meta)}}`,
303
+ )
304
+ .join("") +
305
+ "`";
306
+
307
+ const decodeConstant = (constant: MetadataConstant): string => {
308
+ if (constant.values.length === 0)
309
+ return JSON.stringify(constant.values[0]);
310
+ return `(${constant.values
311
+ .map((val) => JSON.stringify(val))
312
+ .join(" | ")})`;
313
+ };
314
+
315
+ const decodeArray =
316
+ (config: INestiaConfig) =>
317
+ (importer: ImportDictionary) =>
318
+ (array: MetadataArray): string =>
319
+ decodeTypeTagMatrix(importer)(
320
+ `Array<${decode(config)(importer)(array.type.value)}>`,
321
+ array.tags,
322
+ );
323
+
324
+ const decodeTuple =
325
+ (config: INestiaConfig) =>
326
+ (importer: ImportDictionary) =>
327
+ (tuple: MetadataTuple): string =>
328
+ "[" +
329
+ tuple.type.elements.map((e) =>
330
+ e.rest
331
+ ? `...${decode(config)(importer)(e.rest)}`
332
+ : decode(config)(importer)(e),
333
+ ) +
334
+ "]";
335
+
336
+ const decodeAlias =
337
+ (config: INestiaConfig) =>
338
+ (importer: ImportDictionary) =>
339
+ (alias: MetadataAlias) => {
340
+ importInternalFile(config)(importer)(alias.name);
341
+ return alias.name;
342
+ };
343
+
344
+ const decodeObject =
345
+ (config: INestiaConfig) =>
346
+ (importer: ImportDictionary) =>
347
+ (object: MetadataObject) => {
348
+ importInternalFile(config)(importer)(object.name);
349
+ return object.name;
350
+ };
351
+
352
+ const importInternalFile =
353
+ (config: INestiaConfig) =>
354
+ (importer: ImportDictionary) =>
355
+ (name: string) => {
356
+ const top = name.split(".")[0];
357
+ importer.internal({
358
+ type: true,
359
+ file: `${config.output}/structures/${name.split(".")[0]}`,
360
+ instance: top,
361
+ });
362
+ };
363
+ }
364
+
365
+ const NATIVE_TYPE_TAGS = new Set([
366
+ "ExclusiveMinimum",
367
+ "ExclusiveMaximum",
368
+ "Format",
369
+ "Maximum",
370
+ "MaxItems",
371
+ "MaxLength",
372
+ "Minimum",
373
+ "MinItems",
374
+ "MinLength",
375
+ "MultipleOf",
376
+ "Pattern",
377
+ "Type",
378
+ ]);
379
+
380
+ interface IModule {
381
+ name: string;
382
+ children: Map<string, IModule>;
383
+ programmer?: (importer: ImportDictionary) => string;
384
+ }
@@ -73,13 +73,14 @@ export namespace SdkFileProgrammer {
73
73
  type: false,
74
74
  });
75
75
  directory.routes.forEach((route, i) => {
76
- for (const tuple of route.imports)
77
- for (const instance of tuple[1])
78
- importer.internal({
79
- file: tuple[0],
80
- instance,
81
- type: true,
82
- });
76
+ if (config.clone !== true)
77
+ for (const tuple of route.imports)
78
+ for (const instance of tuple[1])
79
+ importer.internal({
80
+ file: tuple[0],
81
+ instance,
82
+ type: true,
83
+ });
83
84
 
84
85
  content.push(
85
86
  SdkFunctionProgrammer.generate(config)(importer)(route),
@@ -7,6 +7,7 @@ import { INestiaConfig } from "../../INestiaConfig";
7
7
  import { IController } from "../../structures/IController";
8
8
  import { IRoute } from "../../structures/IRoute";
9
9
  import { ImportDictionary } from "../../utils/ImportDictionary";
10
+ import { SdkDtoGenerator } from "./SdkDtoGenerator";
10
11
  import { SdkImportWizard } from "./SdkImportWizard";
11
12
  import { SdkSimulationProgrammer } from "./SdkSimulationProgrammer";
12
13
 
@@ -221,7 +222,7 @@ export namespace SdkFunctionProgrammer {
221
222
  : [];
222
223
 
223
224
  // COMMENT TAGS
224
- const tags: IJsDocTagInfo[] = route.tags.filter(
225
+ const tags: IJsDocTagInfo[] = route.jsDocTags.filter(
225
226
  (tag) =>
226
227
  tag.name !== "param" ||
227
228
  route.parameters
@@ -283,7 +284,7 @@ export namespace SdkFunctionProgrammer {
283
284
  ? `${route.name}.${
284
285
  param === props.query ? "Query" : "Input"
285
286
  }`
286
- : param.typeName;
287
+ : getTypeName(config)(importer)(param);
287
288
  return `${param.name}${
288
289
  param.optional ? "?" : ""
289
290
  }: ${type}`;
@@ -321,13 +322,33 @@ export namespace SdkFunctionProgrammer {
321
322
  // LIST UP TYPES
322
323
  const types: Pair<string, string>[] = [];
323
324
  if (props.headers !== undefined)
324
- types.push(new Pair("Headers", props.headers.typeName));
325
+ types.push(
326
+ new Pair(
327
+ "Headers",
328
+ getTypeName(config)(importer)(props.headers),
329
+ ),
330
+ );
325
331
  if (props.query !== undefined)
326
- types.push(new Pair("Query", props.query.typeName));
332
+ types.push(
333
+ new Pair(
334
+ "Query",
335
+ getTypeName(config)(importer)(props.query),
336
+ ),
337
+ );
327
338
  if (props.input !== undefined)
328
- types.push(new Pair("Input", props.input.typeName));
339
+ types.push(
340
+ new Pair(
341
+ "Input",
342
+ getTypeName(config)(importer)(props.input),
343
+ ),
344
+ );
329
345
  if (route.output.typeName !== "void")
330
- types.push(new Pair("Output", route.output.typeName));
346
+ types.push(
347
+ new Pair(
348
+ "Output",
349
+ getTypeName(config)(importer)(route.output),
350
+ ),
351
+ );
331
352
 
332
353
  // PATH WITH PARAMETERS
333
354
  const parameters: IRoute.IParameter[] = filter_path_parameters(
@@ -401,7 +422,7 @@ export namespace SdkFunctionProgrammer {
401
422
  param.category === "query" &&
402
423
  param.typeName === props.query?.typeName
403
424
  ? `${route.name}.Query`
404
- : param.typeName
425
+ : getTypeName(config)(importer)(param)
405
426
  }`,
406
427
  )
407
428
  .join(", ")}): string => {\n` +
@@ -507,3 +528,10 @@ export namespace SdkFunctionProgrammer {
507
528
  }
508
529
 
509
530
  const space = (count: number) => " ".repeat(count);
531
+ const getTypeName =
532
+ (config: INestiaConfig) =>
533
+ (importer: ImportDictionary) =>
534
+ (p: IRoute.IParameter | IRoute.IOutput) =>
535
+ p.metadata
536
+ ? SdkDtoGenerator.decode(config)(importer)(p.metadata)
537
+ : p.typeName;
@@ -1,6 +1,7 @@
1
1
  import { INestiaConfig } from "../../INestiaConfig";
2
2
  import { IRoute } from "../../structures/IRoute";
3
3
  import { ImportDictionary } from "../../utils/ImportDictionary";
4
+ import { SdkDtoGenerator } from "./SdkDtoGenerator";
4
5
  import { SdkImportWizard } from "./SdkImportWizard";
5
6
 
6
7
  export namespace SdkSimulationProgrammer {
@@ -52,7 +53,7 @@ export namespace SdkSimulationProgrammer {
52
53
  ? "Query"
53
54
  : "Input"
54
55
  }`
55
- : p.typeName
56
+ : getTypeName(config)(importer)(p)
56
57
  },`,
57
58
  ),
58
59
  `): Promise<${output ? "Output" : "void"}> => {`,
@@ -106,3 +107,11 @@ export namespace SdkSimulationProgrammer {
106
107
  ];
107
108
  };
108
109
  }
110
+
111
+ const getTypeName =
112
+ (config: INestiaConfig) =>
113
+ (importer: ImportDictionary) =>
114
+ (p: IRoute.IParameter | IRoute.IOutput) =>
115
+ p.metadata
116
+ ? SdkDtoGenerator.decode(config)(importer)(p.metadata)
117
+ : p.typeName;
@@ -64,7 +64,7 @@ export namespace SwaggerSchemaGenerator {
64
64
  }
65
65
 
66
66
  // FROM COMMENT TAGS -> ANY
67
- for (const tag of route.tags) {
67
+ for (const tag of route.jsDocTags) {
68
68
  if (tag.name !== "throw" && tag.name !== "throws") continue;
69
69
 
70
70
  const text: string | undefined = tag.text?.find(
@@ -363,7 +363,7 @@ export namespace SwaggerSchemaGenerator {
363
363
  ) !== undefined
364
364
  : () => true;
365
365
 
366
- const tag: ts.JSDocTagInfo | undefined = route.tags.find(
366
+ const tag: ts.JSDocTagInfo | undefined = route.jsDocTags.find(
367
367
  (tag) => tag.name === tagName && tag.text && parametric(tag),
368
368
  );
369
369
  return tag && tag.text
@@ -6,6 +6,7 @@ export interface IController {
6
6
  paths: string[];
7
7
  functions: IController.IFunction[];
8
8
  security: Record<string, string[]>[];
9
+ swaggerTgas: string[];
9
10
  }
10
11
 
11
12
  export namespace IController {
@@ -23,6 +24,7 @@ export namespace IController {
23
24
  number | "2XX" | "3XX" | "4XX" | "5XX",
24
25
  IController.IException
25
26
  >;
27
+ swaggerTags: string[];
26
28
  }
27
29
 
28
30
  export type IParameter =
@@ -1,5 +1,7 @@
1
1
  import ts from "typescript";
2
2
 
3
+ import { Metadata } from "typia/lib/schemas/metadata/Metadata";
4
+
3
5
  import { IController } from "./IController";
4
6
 
5
7
  export interface IRoute {
@@ -18,16 +20,17 @@ export interface IRoute {
18
20
  symbol: {
19
21
  class: string;
20
22
  function: string;
21
- }
23
+ };
22
24
  description?: string;
23
25
  operationId?: string;
24
- tags: ts.JSDocTagInfo[];
26
+ jsDocTags: ts.JSDocTagInfo[];
25
27
  setHeaders: Array<
26
28
  | { type: "setter"; source: string; target?: string }
27
29
  | { type: "assigner"; source: string }
28
30
  >;
29
31
  security: Record<string, string[]>[];
30
32
  exceptions: Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput>;
33
+ swaggerTags: string[];
31
34
  }
32
35
 
33
36
  export namespace IRoute {
@@ -35,10 +38,12 @@ export namespace IRoute {
35
38
  optional: boolean;
36
39
  type: ts.Type;
37
40
  typeName: string;
41
+ metadata?: Metadata;
38
42
  };
39
43
  export interface IOutput {
40
44
  type: ts.Type;
41
45
  typeName: string;
46
+ metadata?: Metadata;
42
47
  description?: string;
43
48
  contentType: "application/json" | "text/plain";
44
49
  }