@nestia/sdk 3.0.0-dev.20231209 → 3.0.0-dev.20240412

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 (168) hide show
  1. package/README.md +12 -9
  2. package/assets/config/nestia.config.ts +82 -79
  3. package/lib/INestiaConfig.d.ts +28 -6
  4. package/lib/NestiaSdkApplication.js +12 -10
  5. package/lib/NestiaSdkApplication.js.map +1 -1
  6. package/lib/analyses/ConfigAnalyzer.js +1 -1
  7. package/lib/analyses/ConfigAnalyzer.js.map +1 -1
  8. package/lib/analyses/ControllerAnalyzer.js +30 -15
  9. package/lib/analyses/ControllerAnalyzer.js.map +1 -1
  10. package/lib/analyses/ExceptionAnalyzer.js +35 -6
  11. package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
  12. package/lib/analyses/ImportAnalyzer.d.ts +1 -2
  13. package/lib/analyses/ImportAnalyzer.js +2 -2
  14. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  15. package/lib/analyses/PathAnalyzer.d.ts +2 -4
  16. package/lib/analyses/PathAnalyzer.js +27 -11
  17. package/lib/analyses/PathAnalyzer.js.map +1 -1
  18. package/lib/analyses/ReflectAnalyzer.js +34 -22
  19. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  20. package/lib/analyses/SecurityAnalyzer.js +13 -8
  21. package/lib/analyses/SecurityAnalyzer.js.map +1 -1
  22. package/lib/executable/internal/NestiaConfigLoader.js +300 -220
  23. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  24. package/lib/executable/sdk.js +11 -11
  25. package/lib/generates/CloneGenerator.d.ts +6 -0
  26. package/lib/generates/CloneGenerator.js +62 -0
  27. package/lib/generates/CloneGenerator.js.map +1 -0
  28. package/lib/generates/E2eGenerator.d.ts +2 -1
  29. package/lib/generates/E2eGenerator.js +2 -2
  30. package/lib/generates/E2eGenerator.js.map +1 -1
  31. package/lib/generates/SdkGenerator.js +3 -11
  32. package/lib/generates/SdkGenerator.js.map +1 -1
  33. package/lib/generates/SwaggerGenerator.d.ts +2 -0
  34. package/lib/generates/SwaggerGenerator.js +119 -62
  35. package/lib/generates/SwaggerGenerator.js.map +1 -1
  36. package/lib/generates/internal/E2eFileProgrammer.d.ts +2 -1
  37. package/lib/generates/internal/E2eFileProgrammer.js +49 -53
  38. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  39. package/lib/generates/internal/FilePrinter.d.ts +10 -0
  40. package/lib/generates/internal/FilePrinter.js +46 -0
  41. package/lib/generates/internal/FilePrinter.js.map +1 -0
  42. package/lib/{utils → generates/internal}/ImportDictionary.d.ts +2 -1
  43. package/lib/{utils → generates/internal}/ImportDictionary.js +20 -14
  44. package/lib/generates/internal/ImportDictionary.js.map +1 -0
  45. package/lib/generates/internal/SdkAliasCollection.d.ts +12 -0
  46. package/lib/generates/internal/SdkAliasCollection.js +97 -0
  47. package/lib/generates/internal/SdkAliasCollection.js.map +1 -0
  48. package/lib/generates/internal/SdkCloneProgrammer.d.ts +12 -0
  49. package/lib/generates/internal/SdkCloneProgrammer.js +99 -0
  50. package/lib/generates/internal/SdkCloneProgrammer.js.map +1 -0
  51. package/lib/generates/internal/SdkFileProgrammer.d.ts +2 -1
  52. package/lib/generates/internal/SdkFileProgrammer.js +27 -28
  53. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  54. package/lib/generates/internal/SdkFunctionProgrammer.d.ts +7 -2
  55. package/lib/generates/internal/SdkFunctionProgrammer.js +115 -322
  56. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  57. package/lib/generates/internal/SdkImportWizard.d.ts +1 -1
  58. package/lib/generates/internal/SdkNamespaceProgrammer.d.ts +11 -0
  59. package/lib/generates/internal/SdkNamespaceProgrammer.js +180 -0
  60. package/lib/generates/internal/SdkNamespaceProgrammer.js.map +1 -0
  61. package/lib/generates/internal/SdkRouteProgrammer.d.ts +7 -0
  62. package/lib/generates/internal/SdkRouteProgrammer.js +55 -0
  63. package/lib/generates/internal/SdkRouteProgrammer.js.map +1 -0
  64. package/lib/generates/internal/SdkSimulationProgrammer.d.ts +8 -2
  65. package/lib/generates/internal/SdkSimulationProgrammer.js +103 -89
  66. package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
  67. package/lib/generates/internal/SdkTypeProgrammer.d.ts +9 -0
  68. package/lib/generates/internal/SdkTypeProgrammer.js +228 -0
  69. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -0
  70. package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +4 -4
  71. package/lib/generates/internal/SwaggerSchemaGenerator.js +30 -28
  72. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  73. package/lib/structures/IController.d.ts +4 -2
  74. package/lib/structures/IRoute.d.ts +5 -4
  75. package/lib/structures/ISwaggerLazyProperty.d.ts +2 -2
  76. package/lib/structures/ISwaggerLazySchema.d.ts +2 -2
  77. package/lib/structures/ParamCategory.d.ts +1 -1
  78. package/lib/structures/TypeEntry.js +2 -2
  79. package/lib/structures/TypeEntry.js.map +1 -1
  80. package/lib/utils/StringUtil.d.ts +3 -0
  81. package/lib/utils/StringUtil.js +8 -0
  82. package/lib/utils/StringUtil.js.map +1 -0
  83. package/package.json +12 -16
  84. package/src/INestiaConfig.ts +30 -6
  85. package/src/NestiaSdkApplication.ts +255 -253
  86. package/src/analyses/AccessorAnalyzer.ts +60 -60
  87. package/src/analyses/ConfigAnalyzer.ts +147 -147
  88. package/src/analyses/ControllerAnalyzer.ts +42 -19
  89. package/src/analyses/ExceptionAnalyzer.ts +148 -115
  90. package/src/analyses/GenericAnalyzer.ts +51 -51
  91. package/src/analyses/ImportAnalyzer.ts +1 -2
  92. package/src/analyses/PathAnalyzer.ts +110 -98
  93. package/src/analyses/ReflectAnalyzer.ts +39 -35
  94. package/src/analyses/SecurityAnalyzer.ts +24 -20
  95. package/src/executable/internal/CommandParser.ts +15 -15
  96. package/src/executable/internal/NestiaConfigLoader.ts +67 -67
  97. package/src/executable/internal/NestiaSdkCommand.ts +60 -60
  98. package/src/executable/sdk.ts +73 -73
  99. package/src/generates/CloneGenerator.ts +62 -0
  100. package/src/generates/E2eGenerator.ts +66 -64
  101. package/src/generates/SdkGenerator.ts +84 -96
  102. package/src/generates/SwaggerGenerator.ts +145 -53
  103. package/src/generates/internal/E2eFileProgrammer.ts +182 -123
  104. package/src/generates/internal/FilePrinter.ts +53 -0
  105. package/src/{utils → generates/internal}/ImportDictionary.ts +35 -13
  106. package/src/generates/internal/SdkAliasCollection.ts +152 -0
  107. package/src/generates/internal/SdkCloneProgrammer.ts +155 -0
  108. package/src/generates/internal/SdkDistributionComposer.ts +91 -91
  109. package/src/generates/internal/SdkFileProgrammer.ts +115 -106
  110. package/src/generates/internal/SdkFunctionProgrammer.ts +298 -518
  111. package/src/generates/internal/SdkImportWizard.ts +55 -55
  112. package/src/generates/internal/SdkNamespaceProgrammer.ts +510 -0
  113. package/src/generates/internal/SdkRouteDirectory.ts +17 -17
  114. package/src/generates/internal/SdkRouteProgrammer.ts +83 -0
  115. package/src/generates/internal/SdkSimulationProgrammer.ts +365 -133
  116. package/src/generates/internal/SdkTypeProgrammer.ts +386 -0
  117. package/src/generates/internal/SwaggerSchemaGenerator.ts +437 -427
  118. package/src/generates/internal/SwaggerSchemaValidator.ts +198 -198
  119. package/src/index.ts +4 -4
  120. package/src/module.ts +2 -2
  121. package/src/structures/IController.ts +94 -95
  122. package/src/structures/IErrorReport.ts +6 -6
  123. package/src/structures/INestiaProject.ts +13 -13
  124. package/src/structures/INormalizedInput.ts +20 -20
  125. package/src/structures/IRoute.ts +53 -53
  126. package/src/structures/ISwaggerLazyProperty.ts +2 -2
  127. package/src/structures/ISwaggerLazySchema.ts +2 -2
  128. package/src/structures/ITypeTuple.ts +6 -6
  129. package/src/structures/MethodType.ts +5 -5
  130. package/src/structures/ParamCategory.ts +1 -1
  131. package/src/structures/TypeEntry.ts +1 -1
  132. package/src/utils/ArrayUtil.ts +26 -26
  133. package/src/utils/FileRetriever.ts +22 -22
  134. package/src/utils/MapUtil.ts +14 -14
  135. package/src/utils/PathUtil.ts +10 -10
  136. package/src/utils/SourceFinder.ts +66 -66
  137. package/src/utils/StringUtil.ts +6 -0
  138. package/src/utils/StripEnums.ts +5 -5
  139. package/assets/bundle/api/utils/NestiaSimulator.ts +0 -70
  140. package/lib/generates/internal/SdkDtoGenerator.d.ts +0 -9
  141. package/lib/generates/internal/SdkDtoGenerator.js +0 -294
  142. package/lib/generates/internal/SdkDtoGenerator.js.map +0 -1
  143. package/lib/generates/internal/SdkTypeDefiner.d.ts +0 -11
  144. package/lib/generates/internal/SdkTypeDefiner.js +0 -82
  145. package/lib/generates/internal/SdkTypeDefiner.js.map +0 -1
  146. package/lib/structures/ISwagger.d.ts +0 -72
  147. package/lib/structures/ISwagger.js +0 -3
  148. package/lib/structures/ISwagger.js.map +0 -1
  149. package/lib/structures/ISwaggerComponents.d.ts +0 -26
  150. package/lib/structures/ISwaggerComponents.js +0 -3
  151. package/lib/structures/ISwaggerComponents.js.map +0 -1
  152. package/lib/structures/ISwaggerInfo.d.ts +0 -71
  153. package/lib/structures/ISwaggerInfo.js +0 -3
  154. package/lib/structures/ISwaggerInfo.js.map +0 -1
  155. package/lib/structures/ISwaggerRoute.d.ts +0 -47
  156. package/lib/structures/ISwaggerRoute.js +0 -3
  157. package/lib/structures/ISwaggerRoute.js.map +0 -1
  158. package/lib/structures/ISwaggerSecurityScheme.d.ts +0 -56
  159. package/lib/structures/ISwaggerSecurityScheme.js +0 -3
  160. package/lib/structures/ISwaggerSecurityScheme.js.map +0 -1
  161. package/lib/utils/ImportDictionary.js.map +0 -1
  162. package/src/generates/internal/SdkDtoGenerator.ts +0 -424
  163. package/src/generates/internal/SdkTypeDefiner.ts +0 -119
  164. package/src/structures/ISwagger.ts +0 -91
  165. package/src/structures/ISwaggerComponents.ts +0 -29
  166. package/src/structures/ISwaggerInfo.ts +0 -80
  167. package/src/structures/ISwaggerRoute.ts +0 -51
  168. package/src/structures/ISwaggerSecurityScheme.ts +0 -65
@@ -0,0 +1,83 @@
1
+ import ts from "typescript";
2
+ import { IJsDocTagInfo } from "typia";
3
+
4
+ import { INestiaConfig } from "../../INestiaConfig";
5
+ import { IRoute } from "../../structures/IRoute";
6
+ import { FilePrinter } from "./FilePrinter";
7
+ import { ImportDictionary } from "./ImportDictionary";
8
+ import { SdkFunctionProgrammer } from "./SdkFunctionProgrammer";
9
+ import { SdkNamespaceProgrammer } from "./SdkNamespaceProgrammer";
10
+
11
+ export namespace SdkRouteProgrammer {
12
+ export const generate =
13
+ (checker: ts.TypeChecker) =>
14
+ (config: INestiaConfig) =>
15
+ (importer: ImportDictionary) =>
16
+ (route: IRoute): ts.Statement[] => {
17
+ const props = {
18
+ headers: route.parameters.find(
19
+ (p) => p.category === "headers" && p.field === undefined,
20
+ ),
21
+ query: route.parameters.find(
22
+ (p) => p.category === "query" && p.field === undefined,
23
+ ),
24
+ input: route.parameters.find((p) => p.category === "body"),
25
+ };
26
+ return [
27
+ FilePrinter.description(
28
+ SdkFunctionProgrammer.write(config)(importer)(route, props),
29
+ describe(route),
30
+ ),
31
+ SdkNamespaceProgrammer.write(checker)(config)(importer)(route, props),
32
+ ];
33
+ };
34
+
35
+ const describe = (route: IRoute): string => {
36
+ // MAIN DESCRIPTION
37
+ const comments: string[] = route.description
38
+ ? route.description.split("\n")
39
+ : [];
40
+
41
+ // COMMENT TAGS
42
+ const tags: IJsDocTagInfo[] = route.jsDocTags.filter(
43
+ (tag) =>
44
+ tag.name !== "param" ||
45
+ route.parameters
46
+ .filter((p) => p.category !== "headers")
47
+ .some((p) => p.name === tag.text?.[0]?.text),
48
+ );
49
+ if (tags.length !== 0) {
50
+ const content: string[] = tags.map((t) =>
51
+ t.text?.length
52
+ ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
53
+ : `@${t.name}`,
54
+ );
55
+ comments.push("", ...new Set(content));
56
+ }
57
+
58
+ // EXCEPTIONS
59
+ for (const [key, value] of Object.entries(route.exceptions)) {
60
+ if (
61
+ comments.some(
62
+ (str) =>
63
+ str.startsWith(`@throw ${key}`) || str.startsWith(`@throws ${key}`),
64
+ )
65
+ )
66
+ continue;
67
+ comments.push(
68
+ value.description?.length
69
+ ? `@throws ${key} ${value.description.split("\n")[0]}`
70
+ : `@throws ${key}`,
71
+ );
72
+ }
73
+
74
+ // POSTFIX
75
+ if (!!comments.length) comments.push("");
76
+ comments.push(
77
+ `@controller ${route.target.class.name}.${route.target.function.name}`,
78
+ `@path ${route.method} ${route.path}`,
79
+ `@nestia Generated by Nestia - https://github.com/samchon/nestia`,
80
+ );
81
+ return comments.join("\n");
82
+ };
83
+ }
@@ -1,133 +1,365 @@
1
- import { INestiaConfig } from "../../INestiaConfig";
2
- import { IRoute } from "../../structures/IRoute";
3
- import { ImportDictionary } from "../../utils/ImportDictionary";
4
- import { SdkImportWizard } from "./SdkImportWizard";
5
- import { SdkTypeDefiner } from "./SdkTypeDefiner";
6
-
7
- export namespace SdkSimulationProgrammer {
8
- export const generate =
9
- (config: INestiaConfig) =>
10
- (importer: ImportDictionary) =>
11
- (route: IRoute): string => {
12
- const output: boolean =
13
- config.propagate === true || route.output.typeName !== "void";
14
- const body: string[] = [
15
- ...(route.parameters.filter((p) => p.category !== "headers").length !==
16
- 0
17
- ? assert(config)(importer)(route)
18
- : []),
19
- ...(output ? returns(config)(route) : []),
20
- ];
21
- return [
22
- `export const simulate = async (`,
23
- ` ${
24
- route.parameters.filter((p) => p.category !== "headers").length ===
25
- 0 && route.output.typeName === "void"
26
- ? "_connection"
27
- : "connection"
28
- }: ${
29
- route.parameters.some(
30
- (p) => p.category === "headers" && p.field === undefined,
31
- )
32
- ? `${SdkImportWizard.IConnection(importer)}<${route.name}.Headers>`
33
- : SdkImportWizard.IConnection(importer)
34
- },`,
35
- ...route.parameters
36
- .filter((p) => p.category !== "headers")
37
- .map(
38
- (p) =>
39
- ` ${p.name}: ${
40
- p.category === "query" || p.category === "body"
41
- ? `${route.name}.${
42
- p.category === "query" ? "Query" : "Input"
43
- }`
44
- : SdkTypeDefiner.name(config)(importer)(p)
45
- },`,
46
- ),
47
- `): Promise<${output ? "Output" : "void"}> => {`,
48
- ...body.map((l) => ` ${l}`),
49
- `}`,
50
- ]
51
- .map((line) => ` ${line}`)
52
- .join("\n");
53
- };
54
-
55
- const assert =
56
- (config: INestiaConfig) =>
57
- (importer: ImportDictionary) =>
58
- (route: IRoute): string[] => {
59
- const typia = SdkImportWizard.typia(importer);
60
- const func: string[] = [
61
- `const assert = ${importer.internal({
62
- file: `${config.output}/utils/NestiaSimulator.ts`,
63
- instance: "NestiaSimulator",
64
- type: false,
65
- })}.assert({`,
66
- ` method: METADATA.method,`,
67
- ` host: connection.host,`,
68
- ` path: path(${route.parameters
69
- .filter((p) => p.category === "param" || p.category === "query")
70
- .map((p) => p.name)
71
- .join(", ")}),`,
72
- ` contentType: ${JSON.stringify(route.output.contentType)},`,
73
- `});`,
74
- ];
75
- const individual: string[] = route.parameters
76
- .filter((p) => p.category !== "headers")
77
- .map((p) =>
78
- p.category === "body"
79
- ? `assert.body(() => ${typia}.assert(${p.name}));`
80
- : p.category === "query"
81
- ? `assert.query(() => ${typia}.assert(${p.name}));`
82
- : p.category === "headers"
83
- ? `assert.headers(() => ${typia}.assert(connection.headers);`
84
- : `assert.param("${p.field}")(() => ${typia}.assert(${p.name}));`,
85
- );
86
- if (config.propagate !== true) return [...func, ...individual];
87
-
88
- return [
89
- ...func,
90
- `try {`,
91
- ...individual.map((l) => ` ${l}`),
92
- `} catch (exp) {`,
93
- ` if (!${typia}.is<${SdkImportWizard.HttpError(
94
- importer,
95
- )}>(exp)) throw exp;`,
96
- ` return {`,
97
- ` success: false,`,
98
- ` status: exp.status,`,
99
- ` headers: exp.headers,`,
100
- ` data: exp.toJSON().message,`,
101
- ` } as any;`,
102
- `}`,
103
- ];
104
- };
105
-
106
- const returns =
107
- (config: INestiaConfig) =>
108
- (route: IRoute): string[] => {
109
- const random = (prefix: string, postfix: string) =>
110
- route.output.typeName === "void"
111
- ? [`${prefix} undefined${postfix}`]
112
- : [
113
- `${prefix} random(`,
114
- ` typeof connection.simulate === 'object' &&`,
115
- ` connection.simulate !== null`,
116
- ` ? connection.simulate`,
117
- ` : undefined`,
118
- `)${postfix}`,
119
- ];
120
- if (config.propagate !== true) return random("return", ";");
121
-
122
- return [
123
- `return {`,
124
- ` success: true,`,
125
- ` status: ${route.status ?? (route.method === "POST" ? 201 : 200)},`,
126
- ` headers: {`,
127
- ` "Content-Type": "${route.output.contentType}",`,
128
- ` },`,
129
- ...random("data:", ",").map((r) => ` ${r}`),
130
- `}`,
131
- ];
132
- };
133
- }
1
+ import ts from "typescript";
2
+ import { ExpressionFactory } from "typia/lib/factories/ExpressionFactory";
3
+ import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
4
+ import { LiteralFactory } from "typia/lib/factories/LiteralFactory";
5
+ import { StatementFactory } from "typia/lib/factories/StatementFactory";
6
+ import { TypeFactory } from "typia/lib/factories/TypeFactory";
7
+
8
+ import { INestiaConfig } from "../../INestiaConfig";
9
+ import { IRoute } from "../../structures/IRoute";
10
+ import { ImportDictionary } from "./ImportDictionary";
11
+ import { SdkAliasCollection } from "./SdkAliasCollection";
12
+ import { SdkImportWizard } from "./SdkImportWizard";
13
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
14
+
15
+ export namespace SdkSimulationProgrammer {
16
+ export const random =
17
+ (checker: ts.TypeChecker) =>
18
+ (config: INestiaConfig) =>
19
+ (importer: ImportDictionary) =>
20
+ (route: IRoute): ts.VariableStatement => {
21
+ const output =
22
+ SdkAliasCollection.responseBody(checker)(config)(importer)(route);
23
+ return constant("random")(
24
+ ts.factory.createArrowFunction(
25
+ undefined,
26
+ undefined,
27
+ [
28
+ ts.factory.createParameterDeclaration(
29
+ undefined,
30
+ undefined,
31
+ "g",
32
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
33
+ ts.factory.createTypeReferenceNode(
34
+ ts.factory.createIdentifier("Partial"),
35
+ [
36
+ ts.factory.createTypeReferenceNode(
37
+ `${SdkImportWizard.typia(importer)}.IRandomGenerator`,
38
+ ),
39
+ ],
40
+ ),
41
+ ),
42
+ ],
43
+ config.primitive === false
44
+ ? output
45
+ : ts.factory.createTypeReferenceNode(
46
+ SdkImportWizard.Resolved(importer),
47
+ [output],
48
+ ),
49
+ undefined,
50
+ ts.factory.createCallExpression(
51
+ IdentifierFactory.access(
52
+ ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
53
+ )("random"),
54
+ [output],
55
+ [ts.factory.createIdentifier("g")],
56
+ ),
57
+ ),
58
+ );
59
+ };
60
+
61
+ export const simulate =
62
+ (config: INestiaConfig) =>
63
+ (importer: ImportDictionary) =>
64
+ (
65
+ route: IRoute,
66
+ props: {
67
+ headers: IRoute.IParameter | undefined;
68
+ query: IRoute.IParameter | undefined;
69
+ input: IRoute.IParameter | undefined;
70
+ },
71
+ ): ts.VariableStatement => {
72
+ const output: boolean =
73
+ config.propagate === true || route.output.typeName !== "void";
74
+ const caller = () =>
75
+ ts.factory.createCallExpression(
76
+ ts.factory.createIdentifier("random"),
77
+ undefined,
78
+ [
79
+ ts.factory.createConditionalExpression(
80
+ ts.factory.createLogicalAnd(
81
+ ts.factory.createStrictEquality(
82
+ ts.factory.createStringLiteral("object"),
83
+ ts.factory.createTypeOfExpression(
84
+ ts.factory.createIdentifier("connection.simulate"),
85
+ ),
86
+ ),
87
+ ts.factory.createStrictInequality(
88
+ ts.factory.createNull(),
89
+ ts.factory.createIdentifier("connection.simulate"),
90
+ ),
91
+ ),
92
+ undefined,
93
+ ts.factory.createIdentifier("connection.simulate"),
94
+ undefined,
95
+ ts.factory.createIdentifier("undefined"),
96
+ ),
97
+ ],
98
+ );
99
+
100
+ return constant("simulate")(
101
+ ts.factory.createArrowFunction(
102
+ undefined,
103
+ undefined,
104
+ [
105
+ IdentifierFactory.parameter(
106
+ "connection",
107
+ ts.factory.createTypeReferenceNode(
108
+ SdkImportWizard.IConnection(importer),
109
+ route.parameters.some(
110
+ (p) => p.category === "headers" && p.field === undefined,
111
+ )
112
+ ? [
113
+ ts.factory.createTypeReferenceNode(
114
+ `${route.name}.Headers`,
115
+ ),
116
+ ]
117
+ : [],
118
+ ),
119
+ ),
120
+ ...route.parameters
121
+ .filter((p) => p.category !== "headers")
122
+ .map((p) =>
123
+ ts.factory.createParameterDeclaration(
124
+ [],
125
+ undefined,
126
+ p.name,
127
+ p.optional
128
+ ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
129
+ : undefined,
130
+ config.primitive !== false &&
131
+ (p === props.query || p === props.input)
132
+ ? ts.factory.createTypeReferenceNode(
133
+ `${route.name}.${p === props.query ? "Query" : "Input"}`,
134
+ )
135
+ : getTypeName(config)(importer)(p),
136
+ ),
137
+ ),
138
+ ],
139
+ ts.factory.createTypeReferenceNode(output ? "Output" : "void"),
140
+ undefined,
141
+ ts.factory.createBlock(
142
+ [
143
+ ...assert(config)(importer)(route),
144
+ ts.factory.createReturnStatement(
145
+ config.propagate
146
+ ? ts.factory.createObjectLiteralExpression(
147
+ [
148
+ ts.factory.createPropertyAssignment(
149
+ "success",
150
+ ts.factory.createTrue(),
151
+ ),
152
+ ts.factory.createPropertyAssignment(
153
+ "status",
154
+ ExpressionFactory.number(
155
+ route.status ??
156
+ (route.method === "POST" ? 201 : 200),
157
+ ),
158
+ ),
159
+ ts.factory.createPropertyAssignment(
160
+ "headers",
161
+ LiteralFactory.generate({
162
+ "Content-Type": route.output.contentType,
163
+ }),
164
+ ),
165
+ ts.factory.createPropertyAssignment("data", caller()),
166
+ ],
167
+ true,
168
+ )
169
+ : caller(),
170
+ ),
171
+ ],
172
+ true,
173
+ ),
174
+ ),
175
+ );
176
+ };
177
+
178
+ const assert =
179
+ (config: INestiaConfig) =>
180
+ (importer: ImportDictionary) =>
181
+ (route: IRoute): ts.Statement[] => {
182
+ const parameters = route.parameters.filter(
183
+ (p) => p.category !== "headers",
184
+ );
185
+ if (parameters.length === 0) return [];
186
+
187
+ const typia = SdkImportWizard.typia(importer);
188
+ const validator = StatementFactory.constant(
189
+ "assert",
190
+ ts.factory.createCallExpression(
191
+ IdentifierFactory.access(
192
+ ts.factory.createIdentifier(
193
+ importer.external({
194
+ type: false,
195
+ library: `@nestia/fetcher/lib/NestiaSimulator`,
196
+ instance: "NestiaSimulator",
197
+ }),
198
+ ),
199
+ )("assert"),
200
+ undefined,
201
+ [
202
+ ts.factory.createObjectLiteralExpression(
203
+ [
204
+ ts.factory.createPropertyAssignment(
205
+ "method",
206
+ ts.factory.createIdentifier("METADATA.method"),
207
+ ),
208
+ ts.factory.createPropertyAssignment(
209
+ "host",
210
+ ts.factory.createIdentifier("connection.host"),
211
+ ),
212
+ ts.factory.createPropertyAssignment(
213
+ "path",
214
+ ts.factory.createCallExpression(
215
+ ts.factory.createIdentifier("path"),
216
+ undefined,
217
+ route.parameters
218
+ .filter(
219
+ (p) => p.category === "param" || p.category === "query",
220
+ )
221
+ .map((p) => ts.factory.createIdentifier(p.name)),
222
+ ),
223
+ ),
224
+ ts.factory.createPropertyAssignment(
225
+ "contentType",
226
+ ts.factory.createIdentifier(
227
+ JSON.stringify(route.output.contentType),
228
+ ),
229
+ ),
230
+ ],
231
+ true,
232
+ ),
233
+ ],
234
+ ),
235
+ );
236
+ const individual = parameters
237
+ .map((p) =>
238
+ ts.factory.createCallExpression(
239
+ (() => {
240
+ const base = IdentifierFactory.access(
241
+ ts.factory.createIdentifier("assert"),
242
+ )(p.category);
243
+ if (p.category !== "param") return base;
244
+ return ts.factory.createCallExpression(base, undefined, [
245
+ ts.factory.createStringLiteral(p.name),
246
+ ]);
247
+ })(),
248
+ undefined,
249
+ [
250
+ ts.factory.createArrowFunction(
251
+ undefined,
252
+ undefined,
253
+ [],
254
+ undefined,
255
+ undefined,
256
+ ts.factory.createCallExpression(
257
+ IdentifierFactory.access(ts.factory.createIdentifier(typia))(
258
+ "assert",
259
+ ),
260
+ undefined,
261
+ [
262
+ ts.factory.createIdentifier(
263
+ p.category === "headers" ? "connection.headers" : p.name,
264
+ ),
265
+ ],
266
+ ),
267
+ ),
268
+ ],
269
+ ),
270
+ )
271
+ .map(ts.factory.createExpressionStatement);
272
+
273
+ return [
274
+ validator,
275
+ ...(config.propagate !== true
276
+ ? individual
277
+ : [tryAndCatch(importer)(individual)]),
278
+ ];
279
+ };
280
+
281
+ const tryAndCatch =
282
+ (importer: ImportDictionary) => (individual: ts.Statement[]) =>
283
+ ts.factory.createTryStatement(
284
+ ts.factory.createBlock(individual, true),
285
+ ts.factory.createCatchClause(
286
+ "exp",
287
+ ts.factory.createBlock(
288
+ [
289
+ ts.factory.createIfStatement(
290
+ ts.factory.createLogicalNot(
291
+ ts.factory.createCallExpression(
292
+ IdentifierFactory.access(
293
+ ts.factory.createIdentifier(
294
+ SdkImportWizard.typia(importer),
295
+ ),
296
+ )("is"),
297
+ [
298
+ ts.factory.createTypeReferenceNode(
299
+ SdkImportWizard.HttpError(importer),
300
+ ),
301
+ ],
302
+ [ts.factory.createIdentifier("exp")],
303
+ ),
304
+ ),
305
+ ts.factory.createThrowStatement(
306
+ ts.factory.createIdentifier("exp"),
307
+ ),
308
+ ),
309
+ ts.factory.createReturnStatement(
310
+ ts.factory.createAsExpression(
311
+ ts.factory.createObjectLiteralExpression(
312
+ [
313
+ ts.factory.createPropertyAssignment(
314
+ "success",
315
+ ts.factory.createFalse(),
316
+ ),
317
+ ts.factory.createPropertyAssignment(
318
+ "status",
319
+ ts.factory.createIdentifier("exp.status"),
320
+ ),
321
+ ts.factory.createPropertyAssignment(
322
+ "headers",
323
+ ts.factory.createIdentifier("exp.headers"),
324
+ ),
325
+ ts.factory.createPropertyAssignment(
326
+ "data",
327
+ ts.factory.createIdentifier("exp.toJSON().message"),
328
+ ),
329
+ ],
330
+ true,
331
+ ),
332
+ TypeFactory.keyword("any"),
333
+ ),
334
+ ),
335
+ ],
336
+ true,
337
+ ),
338
+ ),
339
+ undefined,
340
+ );
341
+ }
342
+
343
+ const constant = (name: string) => (expression: ts.Expression) =>
344
+ ts.factory.createVariableStatement(
345
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
346
+ ts.factory.createVariableDeclarationList(
347
+ [
348
+ ts.factory.createVariableDeclaration(
349
+ ts.factory.createIdentifier(name),
350
+ undefined,
351
+ undefined,
352
+ expression,
353
+ ),
354
+ ],
355
+ ts.NodeFlags.Const,
356
+ ),
357
+ );
358
+
359
+ const getTypeName =
360
+ (config: INestiaConfig) =>
361
+ (importer: ImportDictionary) =>
362
+ (p: IRoute.IParameter | IRoute.IOutput) =>
363
+ p.metadata
364
+ ? SdkTypeProgrammer.write(config)(importer)(p.metadata)
365
+ : ts.factory.createTypeReferenceNode(p.typeName);