@nestia/sdk 3.0.5-dev.20240418 → 3.1.0-dev.20240426

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 (174) hide show
  1. package/lib/NestiaSdkApplication.d.ts +1 -0
  2. package/lib/NestiaSdkApplication.js +17 -17
  3. package/lib/NestiaSdkApplication.js.map +1 -1
  4. package/lib/analyses/AccessorAnalyzer.d.ts +3 -2
  5. package/lib/analyses/AccessorAnalyzer.js.map +1 -1
  6. package/lib/analyses/ExceptionAnalyzer.d.ts +11 -3
  7. package/lib/analyses/ExceptionAnalyzer.js +23 -18
  8. package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
  9. package/lib/analyses/GenericAnalyzer.d.ts +1 -0
  10. package/lib/analyses/ImportAnalyzer.d.ts +6 -1
  11. package/lib/analyses/ImportAnalyzer.js +27 -29
  12. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  13. package/lib/analyses/PathAnalyzer.d.ts +0 -5
  14. package/lib/analyses/PathAnalyzer.js +0 -32
  15. package/lib/analyses/PathAnalyzer.js.map +1 -1
  16. package/lib/analyses/{ReflectAnalyzer.d.ts → ReflectControllerAnalyzer.d.ts} +3 -4
  17. package/lib/analyses/ReflectControllerAnalyzer.js +145 -0
  18. package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -0
  19. package/lib/analyses/ReflectHttpOperationAnalyzer.d.ts +10 -0
  20. package/lib/analyses/ReflectHttpOperationAnalyzer.js +224 -0
  21. package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -0
  22. package/lib/analyses/ReflectMetadataAnalyzer.d.ts +8 -0
  23. package/lib/analyses/ReflectMetadataAnalyzer.js +34 -0
  24. package/lib/analyses/ReflectMetadataAnalyzer.js.map +1 -0
  25. package/lib/analyses/ReflectWebSocketOperationAnalyzer.d.ts +10 -0
  26. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js +78 -0
  27. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js.map +1 -0
  28. package/lib/analyses/SecurityAnalyzer.js +1 -1
  29. package/lib/analyses/SecurityAnalyzer.js.map +1 -1
  30. package/lib/analyses/TypedControllerAnalyzer.d.ts +9 -0
  31. package/lib/analyses/TypedControllerAnalyzer.js +77 -0
  32. package/lib/analyses/TypedControllerAnalyzer.js.map +1 -0
  33. package/lib/analyses/TypedHttpOperationAnalyzer.d.ts +16 -0
  34. package/lib/analyses/TypedHttpOperationAnalyzer.js +251 -0
  35. package/lib/analyses/TypedHttpOperationAnalyzer.js.map +1 -0
  36. package/lib/analyses/TypedWebSocketOperationAnalyzer.d.ts +16 -0
  37. package/lib/analyses/TypedWebSocketOperationAnalyzer.js +218 -0
  38. package/lib/analyses/TypedWebSocketOperationAnalyzer.js.map +1 -0
  39. package/lib/executable/internal/NestiaConfigLoader.d.ts +1 -0
  40. package/lib/generates/CloneGenerator.d.ts +3 -4
  41. package/lib/generates/CloneGenerator.js +8 -8
  42. package/lib/generates/CloneGenerator.js.map +1 -1
  43. package/lib/generates/E2eGenerator.d.ts +3 -4
  44. package/lib/generates/E2eGenerator.js +7 -7
  45. package/lib/generates/E2eGenerator.js.map +1 -1
  46. package/lib/generates/SdkGenerator.d.ts +4 -4
  47. package/lib/generates/SdkGenerator.js +8 -8
  48. package/lib/generates/SdkGenerator.js.map +1 -1
  49. package/lib/generates/SwaggerGenerator.d.ts +5 -2
  50. package/lib/generates/SwaggerGenerator.js +15 -13
  51. package/lib/generates/SwaggerGenerator.js.map +1 -1
  52. package/lib/generates/internal/E2eFileProgrammer.d.ts +4 -5
  53. package/lib/generates/internal/E2eFileProgrammer.js +13 -12
  54. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  55. package/lib/generates/internal/FilePrinter.d.ts +1 -0
  56. package/lib/generates/internal/ImportDictionary.d.ts +1 -0
  57. package/lib/generates/internal/SdkAliasCollection.d.ts +9 -8
  58. package/lib/generates/internal/SdkAliasCollection.js +20 -20
  59. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  60. package/lib/generates/internal/SdkDistributionComposer.d.ts +1 -1
  61. package/lib/generates/internal/SdkDistributionComposer.js +36 -2
  62. package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
  63. package/lib/generates/internal/SdkFileProgrammer.d.ts +4 -4
  64. package/lib/generates/internal/SdkFileProgrammer.js +10 -7
  65. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  66. package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +13 -0
  67. package/lib/generates/internal/{SdkCloneProgrammer.js → SdkHttpCloneProgrammer.js} +14 -14
  68. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -0
  69. package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +12 -0
  70. package/lib/generates/internal/{SdkFunctionProgrammer.js → SdkHttpFunctionProgrammer.js} +12 -12
  71. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -0
  72. package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +12 -0
  73. package/lib/generates/internal/{SdkNamespaceProgrammer.js → SdkHttpNamespaceProgrammer.js} +26 -26
  74. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -0
  75. package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +8 -0
  76. package/lib/generates/internal/{SdkRouteProgrammer.js → SdkHttpRouteProgrammer.js} +11 -11
  77. package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -0
  78. package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +13 -0
  79. package/lib/generates/internal/{SdkSimulationProgrammer.js → SdkHttpSimulationProgrammer.js} +18 -18
  80. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -0
  81. package/lib/generates/internal/SdkRouteDirectory.d.ts +3 -2
  82. package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
  83. package/lib/generates/internal/SdkTypeProgrammer.d.ts +4 -3
  84. package/lib/generates/internal/SdkTypeProgrammer.js +33 -33
  85. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
  86. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +8 -0
  87. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +115 -0
  88. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -0
  89. package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +8 -0
  90. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +79 -0
  91. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -0
  92. package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +6 -5
  93. package/lib/generates/internal/SwaggerSchemaGenerator.js +3 -1
  94. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  95. package/lib/structures/INestiaProject.d.ts +1 -0
  96. package/lib/structures/IReflectController.d.ts +15 -0
  97. package/lib/structures/{IRoute.js → IReflectController.js} +1 -1
  98. package/lib/structures/IReflectController.js.map +1 -0
  99. package/lib/structures/{IController.d.ts → IReflectHttpOperation.d.ts} +15 -25
  100. package/lib/structures/IReflectHttpOperation.js +3 -0
  101. package/lib/structures/IReflectHttpOperation.js.map +1 -0
  102. package/lib/structures/IReflectWebSocketOperation.d.ts +16 -0
  103. package/lib/structures/IReflectWebSocketOperation.js +3 -0
  104. package/lib/structures/IReflectWebSocketOperation.js.map +1 -0
  105. package/lib/structures/ISwaggerError.d.ts +2 -2
  106. package/lib/structures/ITypeTuple.d.ts +1 -0
  107. package/lib/structures/{IRoute.d.ts → ITypedHttpRoute.d.ts} +12 -12
  108. package/lib/structures/{IController.js → ITypedHttpRoute.js} +1 -1
  109. package/lib/structures/ITypedHttpRoute.js.map +1 -0
  110. package/lib/structures/ITypedWebSocketRoute.d.ts +54 -0
  111. package/lib/structures/ITypedWebSocketRoute.js +3 -0
  112. package/lib/structures/ITypedWebSocketRoute.js.map +1 -0
  113. package/lib/structures/TypeEntry.d.ts +1 -0
  114. package/lib/utils/VersioningStrategy.d.ts +6 -0
  115. package/lib/utils/VersioningStrategy.js +22 -0
  116. package/lib/utils/VersioningStrategy.js.map +1 -0
  117. package/package.json +9 -7
  118. package/src/NestiaSdkApplication.ts +36 -34
  119. package/src/analyses/AccessorAnalyzer.ts +12 -5
  120. package/src/analyses/ExceptionAnalyzer.ts +49 -39
  121. package/src/analyses/ImportAnalyzer.ts +123 -104
  122. package/src/analyses/PathAnalyzer.ts +0 -41
  123. package/src/analyses/ReflectControllerAnalyzer.ts +155 -0
  124. package/src/analyses/ReflectHttpOperationAnalyzer.ts +290 -0
  125. package/src/analyses/ReflectMetadataAnalyzer.ts +53 -0
  126. package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +96 -0
  127. package/src/analyses/SecurityAnalyzer.ts +2 -1
  128. package/src/analyses/TypedControllerAnalyzer.ts +92 -0
  129. package/src/analyses/TypedHttpOperationAnalyzer.ts +352 -0
  130. package/src/analyses/TypedWebSocketOperationAnalyzer.ts +368 -0
  131. package/src/generates/CloneGenerator.ts +17 -15
  132. package/src/generates/E2eGenerator.ts +10 -12
  133. package/src/generates/SdkGenerator.ts +19 -12
  134. package/src/generates/SwaggerGenerator.ts +31 -21
  135. package/src/generates/internal/E2eFileProgrammer.ts +20 -24
  136. package/src/generates/internal/SdkAliasCollection.ts +38 -33
  137. package/src/generates/internal/SdkDistributionComposer.ts +13 -4
  138. package/src/generates/internal/SdkFileProgrammer.ts +17 -13
  139. package/src/generates/internal/{SdkCloneProgrammer.ts → SdkHttpCloneProgrammer.ts} +14 -15
  140. package/src/generates/internal/{SdkFunctionProgrammer.ts → SdkHttpFunctionProgrammer.ts} +24 -23
  141. package/src/generates/internal/{SdkNamespaceProgrammer.ts → SdkHttpNamespaceProgrammer.ts} +44 -49
  142. package/src/generates/internal/{SdkRouteProgrammer.ts → SdkHttpRouteProgrammer.ts} +12 -13
  143. package/src/generates/internal/{SdkSimulationProgrammer.ts → SdkHttpSimulationProgrammer.ts} +23 -25
  144. package/src/generates/internal/SdkRouteDirectory.ts +3 -2
  145. package/src/generates/internal/SdkTypeProgrammer.ts +43 -37
  146. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +378 -0
  147. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +248 -0
  148. package/src/generates/internal/SwaggerSchemaGenerator.ts +26 -21
  149. package/src/structures/IReflectController.ts +17 -0
  150. package/src/structures/{IController.ts → IReflectHttpOperation.ts} +78 -94
  151. package/src/structures/IReflectWebSocketOperation.ts +17 -0
  152. package/src/structures/ISwaggerError.ts +2 -2
  153. package/src/structures/{IRoute.ts → ITypedHttpRoute.ts} +14 -12
  154. package/src/structures/ITypedWebSocketRoute.ts +67 -0
  155. package/src/utils/VersioningStrategy.ts +28 -0
  156. package/lib/analyses/ControllerAnalyzer.d.ts +0 -7
  157. package/lib/analyses/ControllerAnalyzer.js +0 -269
  158. package/lib/analyses/ControllerAnalyzer.js.map +0 -1
  159. package/lib/analyses/ReflectAnalyzer.js +0 -377
  160. package/lib/analyses/ReflectAnalyzer.js.map +0 -1
  161. package/lib/generates/internal/SdkCloneProgrammer.d.ts +0 -12
  162. package/lib/generates/internal/SdkCloneProgrammer.js.map +0 -1
  163. package/lib/generates/internal/SdkFunctionProgrammer.d.ts +0 -11
  164. package/lib/generates/internal/SdkFunctionProgrammer.js.map +0 -1
  165. package/lib/generates/internal/SdkNamespaceProgrammer.d.ts +0 -11
  166. package/lib/generates/internal/SdkNamespaceProgrammer.js.map +0 -1
  167. package/lib/generates/internal/SdkRouteProgrammer.d.ts +0 -7
  168. package/lib/generates/internal/SdkRouteProgrammer.js.map +0 -1
  169. package/lib/generates/internal/SdkSimulationProgrammer.d.ts +0 -12
  170. package/lib/generates/internal/SdkSimulationProgrammer.js.map +0 -1
  171. package/lib/structures/IController.js.map +0 -1
  172. package/lib/structures/IRoute.js.map +0 -1
  173. package/src/analyses/ControllerAnalyzer.ts +0 -402
  174. package/src/analyses/ReflectAnalyzer.ts +0 -471
@@ -0,0 +1,368 @@
1
+ import path from "path";
2
+ import { HashMap } from "tstl";
3
+ import ts from "typescript";
4
+ import { CommentFactory } from "typia/lib/factories/CommentFactory";
5
+
6
+ import { IErrorReport } from "../structures/IErrorReport";
7
+ import { INestiaProject } from "../structures/INestiaProject";
8
+ import { IReflectController } from "../structures/IReflectController";
9
+ import { IReflectWebSocketOperation } from "../structures/IReflectWebSocketOperation";
10
+ import { ITypeTuple } from "../structures/ITypeTuple";
11
+ import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
12
+ import { PathUtil } from "../utils/PathUtil";
13
+ import { VersioningStrategy } from "../utils/VersioningStrategy";
14
+ import { GenericAnalyzer } from "./GenericAnalyzer";
15
+ import { ImportAnalyzer } from "./ImportAnalyzer";
16
+ import { PathAnalyzer } from "./PathAnalyzer";
17
+
18
+ export namespace TypedWebSocketOperationAnalyzer {
19
+ export const analyze =
20
+ (project: INestiaProject) =>
21
+ (props: {
22
+ controller: IReflectController;
23
+ operation: IReflectWebSocketOperation;
24
+ declaration: ts.MethodDeclaration;
25
+ symbol: ts.Symbol;
26
+ generics: GenericAnalyzer.Dictionary;
27
+ }): ITypedWebSocketRoute[] => {
28
+ // CHECK TYPE
29
+ const type: ts.Type = project.checker.getTypeOfSymbolAtLocation(
30
+ props.symbol,
31
+ props.symbol.valueDeclaration!,
32
+ );
33
+ const signature: ts.Signature | undefined =
34
+ project.checker.getSignaturesOfType(type, ts.SignatureKind.Call)[0];
35
+ if (signature === undefined) {
36
+ project.errors.push({
37
+ file: props.controller.file,
38
+ controller: props.controller.name,
39
+ function: props.operation.name,
40
+ message: "unable to get the type signature.",
41
+ });
42
+ return [];
43
+ }
44
+
45
+ // SKIP @IGNORE TAG
46
+ const jsDocTags = signature.getJsDocTags();
47
+ if (jsDocTags.some((tag) => tag.name === "ignore")) return [];
48
+
49
+ // EXPLORE CHILDREN TYPES
50
+ const importDict: ImportAnalyzer.Dictionary = new HashMap();
51
+ const errors: IErrorReport[] = [];
52
+ const parameters: Array<ITypedWebSocketRoute.IParameter> =
53
+ props.operation.parameters.map(
54
+ (param) =>
55
+ _Analyze_parameter({
56
+ ...project,
57
+ errors,
58
+ })({
59
+ generics: props.generics,
60
+ imports: importDict,
61
+ controller: props.controller,
62
+ function: props.operation.name,
63
+ parameter: param,
64
+ symbol: signature.getParameters()[param.index],
65
+ })!,
66
+ );
67
+ if (errors.length) {
68
+ project.errors.push(...errors);
69
+ return [];
70
+ }
71
+
72
+ const imports: [string, string[]][] = importDict
73
+ .toJSON()
74
+ .map((pair) => [pair.first, pair.second.toJSON()]);
75
+ const common: Omit<ITypedWebSocketRoute, "path" | "accessors"> = {
76
+ ...props.operation,
77
+ controller: props.controller,
78
+ parameters,
79
+ imports,
80
+ location: (() => {
81
+ const file = props.declaration.getSourceFile();
82
+ const { line, character } = file.getLineAndCharacterOfPosition(
83
+ props.declaration.pos,
84
+ );
85
+ return `${path.relative(process.cwd(), file.fileName)}:${line + 1}:${
86
+ character + 1
87
+ }`;
88
+ })(),
89
+ description: CommentFactory.description(props.symbol),
90
+ };
91
+
92
+ // CONFIGURE PATHS
93
+ const pathList: Set<string> = new Set();
94
+ const versions: string[] = VersioningStrategy.merge(project)([
95
+ ...(props.controller.versions ?? []),
96
+ ...(props.operation.versions ?? []),
97
+ ]);
98
+ for (const v of versions)
99
+ for (const prefix of wrapPaths(props.controller.prefixes))
100
+ for (const cPath of wrapPaths(props.controller.paths))
101
+ for (const filePath of wrapPaths(props.operation.paths))
102
+ pathList.add(
103
+ PathAnalyzer.join(
104
+ project.input.globalPrefix?.prefix ?? "",
105
+ v,
106
+ prefix,
107
+ cPath,
108
+ filePath,
109
+ ),
110
+ );
111
+
112
+ return [...pathList]
113
+ .filter((path) => {
114
+ const escaped: string | null = PathAnalyzer.escape(path);
115
+ if (escaped === null)
116
+ project.errors.push({
117
+ file: props.controller.file,
118
+ controller: props.controller.name,
119
+ function: props.operation.name,
120
+ message: `unable to escape the path "${path}".`,
121
+ });
122
+ return escaped !== null;
123
+ })
124
+ .map((path) => ({
125
+ ...common,
126
+ path: PathAnalyzer.escape(path)!,
127
+ accessors: [...PathUtil.accessors(path), props.operation.name],
128
+ }));
129
+ };
130
+
131
+ const _Analyze_parameter =
132
+ (project: INestiaProject) =>
133
+ (props: {
134
+ generics: GenericAnalyzer.Dictionary;
135
+ imports: ImportAnalyzer.Dictionary;
136
+ controller: IReflectController;
137
+ function: string;
138
+ parameter: IReflectWebSocketOperation.IParameter;
139
+ symbol: ts.Symbol;
140
+ }): ITypedWebSocketRoute.IParameter => {
141
+ if (props.parameter.category === "acceptor")
142
+ return _Analyze_acceptor(project)(props);
143
+ else if (props.parameter.category === "driver")
144
+ return _Analyze_driver(project)(props);
145
+
146
+ const type: ts.Type = project.checker.getTypeOfSymbolAtLocation(
147
+ props.symbol,
148
+ props.symbol.valueDeclaration!,
149
+ );
150
+ const name: string = props.symbol.getEscapedName().toString();
151
+
152
+ // VALIDATIONS
153
+ const errors: IErrorReport[] = [];
154
+ const tuple: ITypeTuple | null = ImportAnalyzer.analyze(project.checker)({
155
+ generics: props.generics,
156
+ imports: props.imports,
157
+ type,
158
+ });
159
+ if (
160
+ tuple === null ||
161
+ tuple.typeName === "__type" ||
162
+ tuple.typeName === "__object"
163
+ )
164
+ errors.push({
165
+ file: props.controller.file,
166
+ controller: props.controller.name,
167
+ function: props.function,
168
+ message: `implicit (unnamed) parameter type from ${JSON.stringify(name)}.`,
169
+ });
170
+ _Check_optional({
171
+ ...project,
172
+ errors,
173
+ })({
174
+ ...props,
175
+ parameter: {
176
+ name,
177
+ symbol: props.symbol,
178
+ },
179
+ });
180
+ if (errors.length) {
181
+ project.errors.push(...errors);
182
+ return null!;
183
+ }
184
+ return {
185
+ ...props.parameter,
186
+ category: props.parameter.category,
187
+ name,
188
+ type: tuple!.type,
189
+ typeName: tuple!.typeName,
190
+ };
191
+ };
192
+
193
+ const _Analyze_acceptor =
194
+ (project: INestiaProject) =>
195
+ (props: {
196
+ generics: GenericAnalyzer.Dictionary;
197
+ imports: ImportAnalyzer.Dictionary;
198
+ controller: IReflectController;
199
+ function: string;
200
+ parameter: IReflectWebSocketOperation.IParameter;
201
+ symbol: ts.Symbol;
202
+ }): ITypedWebSocketRoute.IAcceptorParameter => {
203
+ // VALIDATIONS
204
+ const type: ts.Type = project.checker.getTypeOfSymbolAtLocation(
205
+ props.symbol,
206
+ props.symbol.valueDeclaration!,
207
+ );
208
+ const name: string = props.symbol.getEscapedName().toString();
209
+ const generics: readonly ts.Type[] =
210
+ type.aliasTypeArguments ??
211
+ project.checker.getTypeArguments(type as ts.TypeReference) ??
212
+ [];
213
+
214
+ const errors: IErrorReport[] = [];
215
+ _Check_optional({
216
+ ...project,
217
+ errors,
218
+ })({
219
+ ...props,
220
+ parameter: {
221
+ name,
222
+ symbol: props.symbol,
223
+ },
224
+ });
225
+ if (generics.length !== 3)
226
+ errors.push({
227
+ file: props.controller.file,
228
+ controller: props.controller.name,
229
+ function: props.function,
230
+ message: `@WebSocketRoute.Acceptor() must have three type arguments of WebAcceptor<Header, Provider, Listener>`,
231
+ });
232
+ const [header, provider, listener] = [
233
+ "header",
234
+ "provider",
235
+ "listener",
236
+ ].map((key, i) => {
237
+ const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
238
+ project.checker,
239
+ )({
240
+ generics: props.generics,
241
+ imports: props.imports,
242
+ type: generics[i],
243
+ });
244
+ if (tuple === null)
245
+ errors.push({
246
+ file: props.controller.file,
247
+ controller: props.controller.name,
248
+ function: props.function,
249
+ message: `unable to analyze the "${key}" argument type of WebAcceptor<Header, Provider, Listener>.`,
250
+ });
251
+ return tuple!;
252
+ });
253
+
254
+ if (errors.length) {
255
+ project.errors.push(...errors);
256
+ return null!;
257
+ }
258
+ return {
259
+ ...props.parameter,
260
+ category: "acceptor",
261
+ name,
262
+ header,
263
+ provider,
264
+ listener: listener,
265
+ };
266
+ };
267
+
268
+ const _Analyze_driver =
269
+ (project: INestiaProject) =>
270
+ (props: {
271
+ generics: GenericAnalyzer.Dictionary;
272
+ imports: ImportAnalyzer.Dictionary;
273
+ controller: IReflectController;
274
+ function: string;
275
+ parameter: IReflectWebSocketOperation.IParameter;
276
+ symbol: ts.Symbol;
277
+ }): ITypedWebSocketRoute.IDriverParameter => {
278
+ // VALIDATIONS
279
+ const type: ts.Type = project.checker.getTypeOfSymbolAtLocation(
280
+ props.symbol,
281
+ props.symbol.valueDeclaration!,
282
+ );
283
+ const name: string = props.symbol.getEscapedName().toString();
284
+ const generics: readonly ts.Type[] =
285
+ type.aliasTypeArguments ??
286
+ project.checker.getTypeArguments(type as ts.TypeReference) ??
287
+ [];
288
+
289
+ const errors: IErrorReport[] = [];
290
+ _Check_optional({
291
+ ...project,
292
+ errors,
293
+ })({
294
+ ...props,
295
+ parameter: {
296
+ name,
297
+ symbol: props.symbol,
298
+ },
299
+ });
300
+ const tuple: ITypeTuple = (() => {
301
+ if (generics.length !== 1) {
302
+ errors.push({
303
+ file: props.controller.file,
304
+ controller: props.controller.name,
305
+ function: props.function,
306
+ message: `@WebSocketRoute.Driver() must have one type argument of WebDriver<T>`,
307
+ });
308
+ return null!;
309
+ } else {
310
+ const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
311
+ project.checker,
312
+ )({
313
+ generics: props.generics,
314
+ imports: props.imports,
315
+ type: generics[0],
316
+ });
317
+ if (tuple === null)
318
+ errors.push({
319
+ file: props.controller.file,
320
+ controller: props.controller.name,
321
+ function: props.function,
322
+ message: `unable to analyze the "type" argument of WebDriver<T>.`,
323
+ });
324
+ return tuple!;
325
+ }
326
+ })();
327
+ if (errors.length) {
328
+ project.errors.push(...errors);
329
+ return null!;
330
+ }
331
+ return {
332
+ ...props.parameter,
333
+ category: "driver",
334
+ name,
335
+ type: tuple.type,
336
+ typeName: tuple.typeName,
337
+ };
338
+ };
339
+
340
+ const _Check_optional =
341
+ (project: INestiaProject) =>
342
+ (props: {
343
+ controller: IReflectController;
344
+ function: string;
345
+ parameter: {
346
+ name: string;
347
+ symbol: ts.Symbol;
348
+ };
349
+ }) => {
350
+ const optional: boolean = !!project.checker.symbolToParameterDeclaration(
351
+ props.parameter.symbol,
352
+ undefined,
353
+ undefined,
354
+ )?.questionToken;
355
+ if (optional === true)
356
+ project.errors.push({
357
+ file: props.controller.file,
358
+ controller: props.controller.name,
359
+ function: props.function,
360
+ message: `@WebSocketRoute() does not allow optional parameter, but be detected from ${JSON.stringify(
361
+ props.parameter.symbol.getEscapedName().toString(),
362
+ )}.`,
363
+ });
364
+ };
365
+ }
366
+
367
+ const wrapPaths = (paths: string[]): string[] =>
368
+ paths.length === 0 ? [""] : paths;
@@ -1,30 +1,32 @@
1
1
  import fs from "fs";
2
2
  import ts from "typescript";
3
3
 
4
- import { INestiaConfig } from "../INestiaConfig";
5
- import { IRoute } from "../structures/IRoute";
4
+ import { INestiaProject } from "../structures/INestiaProject";
5
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
6
6
  import { FilePrinter } from "./internal/FilePrinter";
7
7
  import { ImportDictionary } from "./internal/ImportDictionary";
8
- import { SdkCloneProgrammer } from "./internal/SdkCloneProgrammer";
8
+ import { SdkHttpCloneProgrammer } from "./internal/SdkHttpCloneProgrammer";
9
9
 
10
10
  export namespace CloneGenerator {
11
11
  export const write =
12
- (checker: ts.TypeChecker) =>
13
- (config: INestiaConfig) =>
14
- async (routes: IRoute[]): Promise<void> => {
15
- const dict: Map<string, SdkCloneProgrammer.IModule> =
16
- SdkCloneProgrammer.write(checker)(config)(routes);
12
+ (project: INestiaProject) =>
13
+ async (routes: ITypedHttpRoute[]): Promise<void> => {
14
+ const dict: Map<string, SdkHttpCloneProgrammer.IModule> =
15
+ SdkHttpCloneProgrammer.write(project)(routes);
17
16
  if (dict.size === 0) return;
18
17
  try {
19
- await fs.promises.mkdir(`${config.output}/structures`);
18
+ await fs.promises.mkdir(`${project.config.output}/structures`);
20
19
  } catch {}
21
- for (const [key, value] of dict) await writeDtoFile(config)(key, value);
20
+ for (const [key, value] of dict) await writeDtoFile(project)(key, value);
22
21
  };
23
22
 
24
23
  const writeDtoFile =
25
- (config: INestiaConfig) =>
26
- async (key: string, value: SdkCloneProgrammer.IModule): Promise<void> => {
27
- const location: string = `${config.output}/structures/${key}.ts`;
24
+ (project: INestiaProject) =>
25
+ async (
26
+ key: string,
27
+ value: SdkHttpCloneProgrammer.IModule,
28
+ ): Promise<void> => {
29
+ const location: string = `${project.config.output}/structures/${key}.ts`;
28
30
  const importer: ImportDictionary = new ImportDictionary(location);
29
31
  const statements: ts.Statement[] = iterate(importer)(value);
30
32
  if (statements.length === 0) return;
@@ -32,7 +34,7 @@ export namespace CloneGenerator {
32
34
  await FilePrinter.write({
33
35
  location,
34
36
  statements: [
35
- ...importer.toStatements(`${config.output}/structures`),
37
+ ...importer.toStatements(`${project.config.output}/structures`),
36
38
  ...(importer.empty() ? [] : [FilePrinter.enter()]),
37
39
  ...statements,
38
40
  ],
@@ -41,7 +43,7 @@ export namespace CloneGenerator {
41
43
 
42
44
  const iterate =
43
45
  (importer: ImportDictionary) =>
44
- (modulo: SdkCloneProgrammer.IModule): ts.Statement[] => {
46
+ (modulo: SdkHttpCloneProgrammer.IModule): ts.Statement[] => {
45
47
  const output: ts.Statement[] = [];
46
48
  if (modulo.programmer !== null) output.push(modulo.programmer(importer));
47
49
  if (modulo.children.size) {
@@ -1,39 +1,37 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import ts from "typescript";
4
3
 
5
- import { INestiaConfig } from "../INestiaConfig";
6
4
  import { ConfigAnalyzer } from "../analyses/ConfigAnalyzer";
7
- import { IRoute } from "../structures/IRoute";
5
+ import { INestiaProject } from "../structures/INestiaProject";
6
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
8
7
  import { E2eFileProgrammer } from "./internal/E2eFileProgrammer";
9
8
 
10
9
  export namespace E2eGenerator {
11
10
  export const generate =
12
- (checker: ts.TypeChecker) =>
13
- (config: INestiaConfig) =>
14
- async (routeList: IRoute[]): Promise<void> => {
11
+ (project: INestiaProject) =>
12
+ async (routeList: ITypedHttpRoute[]): Promise<void> => {
15
13
  console.log("Generating E2E Test Functions");
16
14
 
17
15
  // PREPARE DIRECTORIES
18
- const output: string = path.resolve(config.e2e!);
16
+ const output: string = path.resolve(project.config.e2e!);
19
17
  await mkdir(output);
20
18
  await mkdir(path.join(output, "features"));
21
19
  await mkdir(path.join(output, "features", "api"));
22
20
  await mkdir(path.join(output, "features", "api", "automated"));
23
21
 
24
22
  // GENERATE TEST INDEX FILE
25
- await index(config)(path.join(config.e2e!, "index.ts"));
23
+ await index(project)(path.join(project.config.e2e!, "index.ts"));
26
24
 
27
25
  // GENERATE EACH TEST FILES
28
26
  for (const route of routeList)
29
- await E2eFileProgrammer.generate(checker)(config)({
30
- api: path.resolve(config.output!),
27
+ await E2eFileProgrammer.generate(project)({
28
+ api: path.resolve(project.config.output!),
31
29
  current: path.join(output, "features", "api", "automated"),
32
30
  })(route);
33
31
  };
34
32
 
35
33
  const index =
36
- (config: INestiaConfig) =>
34
+ (project: INestiaProject) =>
37
35
  async (output: string): Promise<void> => {
38
36
  if (fs.existsSync(output)) return;
39
37
 
@@ -52,7 +50,7 @@ export namespace E2eGenerator {
52
50
  output,
53
51
  content.replace(
54
52
  "${input}",
55
- JSON.stringify(await ConfigAnalyzer.input(config)),
53
+ JSON.stringify(await ConfigAnalyzer.input(project.config)),
56
54
  ),
57
55
  "utf8",
58
56
  );
@@ -1,31 +1,32 @@
1
1
  import fs from "fs";
2
2
  import NodePath from "path";
3
3
  import { IPointer } from "tstl";
4
- import ts from "typescript";
5
4
 
6
- import { INestiaConfig } from "../INestiaConfig";
7
- import { IRoute } from "../structures/IRoute";
5
+ import { INestiaProject } from "../structures/INestiaProject";
6
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
7
+ import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
8
8
  import { CloneGenerator } from "./CloneGenerator";
9
9
  import { SdkDistributionComposer } from "./internal/SdkDistributionComposer";
10
10
  import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
11
11
 
12
12
  export namespace SdkGenerator {
13
13
  export const generate =
14
- (checker: ts.TypeChecker) =>
15
- (config: INestiaConfig) =>
16
- async (routes: IRoute[]): Promise<void> => {
14
+ (project: INestiaProject) =>
15
+ async (
16
+ routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
17
+ ): Promise<void> => {
17
18
  console.log("Generating SDK Library");
18
19
 
19
20
  // PREPARE NEW DIRECTORIES
20
21
  try {
21
- await fs.promises.mkdir(config.output!);
22
+ await fs.promises.mkdir(project.config.output!);
22
23
  } catch {}
23
24
 
24
25
  // BUNDLING
25
26
  const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
26
27
  for (const file of bundle) {
27
28
  const current: string = `${BUNDLE_PATH}/${file}`;
28
- const target: string = `${config.output}/${file}`;
29
+ const target: string = `${project.config.output}/${file}`;
29
30
  const stats: fs.Stats = await fs.promises.stat(current);
30
31
 
31
32
  if (stats.isFile() === true) {
@@ -44,14 +45,20 @@ export namespace SdkGenerator {
44
45
  }
45
46
 
46
47
  // STRUCTURES
47
- if (config.clone) await CloneGenerator.write(checker)(config)(routes);
48
+ if (project.config.clone)
49
+ await CloneGenerator.write(project)(
50
+ routes.filter((r) => r.protocol === "http") as ITypedHttpRoute[],
51
+ );
48
52
 
49
53
  // FUNCTIONAL
50
- await SdkFileProgrammer.generate(checker)(config)(routes);
54
+ await SdkFileProgrammer.generate(project)(routes);
51
55
 
52
56
  // DISTRIBUTION
53
- if (config.distribute !== undefined)
54
- await SdkDistributionComposer.compose(config);
57
+ if (project.config.distribute !== undefined)
58
+ await SdkDistributionComposer.compose(
59
+ project.config,
60
+ routes.some((r) => r.protocol === "websocket"),
61
+ );
55
62
  };
56
63
 
57
64
  export const BUNDLE_PATH = NodePath.join(