@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
@@ -1,115 +1,148 @@
1
- import path from "path";
2
- import ts from "typescript";
3
-
4
- import { IController } from "../structures/IController";
5
- import { INestiaProject } from "../structures/INestiaProject";
6
- import { IRoute } from "../structures/IRoute";
7
- import { ITypeTuple } from "../structures/ITypeTuple";
8
- import { GenericAnalyzer } from "./GenericAnalyzer";
9
- import { ImportAnalyzer } from "./ImportAnalyzer";
10
-
11
- export namespace ExceptionAnalyzer {
12
- export const analyze =
13
- (project: INestiaProject) =>
14
- (
15
- genericDict: GenericAnalyzer.Dictionary,
16
- importDict: ImportAnalyzer.Dictionary,
17
- ) =>
18
- (controller: IController, func: IController.IFunction) =>
19
- (
20
- declaration: ts.MethodDeclaration,
21
- ): Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput> => {
22
- const output: Record<
23
- number | "2XX" | "3XX" | "4XX" | "5XX",
24
- IRoute.IOutput
25
- > = {} as any;
26
- for (const decorator of declaration.modifiers ?? [])
27
- if (ts.isDecorator(decorator))
28
- analyzeTyped(project)(genericDict, importDict)(controller, func)(
29
- output,
30
- )(decorator);
31
- return output;
32
- };
33
-
34
- const analyzeTyped =
35
- (project: INestiaProject) =>
36
- (
37
- genericDict: GenericAnalyzer.Dictionary,
38
- importDict: ImportAnalyzer.Dictionary,
39
- ) =>
40
- (controller: IController, func: IController.IFunction) =>
41
- (output: Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput>) =>
42
- (decorator: ts.Decorator): boolean => {
43
- // CHECK DECORATOR
44
- if (!ts.isCallExpression(decorator.expression)) return false;
45
- else if ((decorator.expression.typeArguments ?? []).length !== 1)
46
- return false;
47
-
48
- // CHECK SIGNATURE
49
- const signature: ts.Signature | undefined =
50
- project.checker.getResolvedSignature(decorator.expression);
51
- if (!signature || !signature.declaration) return false;
52
- else if (
53
- path
54
- .resolve(signature.declaration.getSourceFile().fileName)
55
- .indexOf(TYPED_EXCEPTION_PATH) === -1
56
- )
57
- return false;
58
-
59
- // GET TYPE INFO
60
- const node: ts.TypeNode = decorator.expression.typeArguments![0];
61
- const type: ts.Type = project.checker.getTypeFromTypeNode(node);
62
- if (type.isTypeParameter()) {
63
- project.errors.push({
64
- file: controller.file,
65
- controller: controller.name,
66
- function: func.name,
67
- message: "TypedException() without generic argument specification.",
68
- });
69
- return false;
70
- }
71
-
72
- const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
73
- project.checker,
74
- genericDict,
75
- importDict,
76
- type,
77
- );
78
- if (tuple === null || tuple.typeName === "__type") {
79
- project.errors.push({
80
- file: controller.file,
81
- controller: controller.name,
82
- function: func.name,
83
- message: "TypeException() with implicit (unnamed) type.",
84
- });
85
- return false;
86
- }
87
-
88
- // DO ASSIGN
89
- const matched: IController.IException[] = Object.entries(func.exceptions)
90
- .filter(([_key, value]) =>
91
- value.type.includes(" | ") && tuple.typeName.includes(" | ")
92
- ? value.type.split(" | ").sort().join(" | ") ===
93
- tuple.typeName.split(" | ").sort().join(" | ")
94
- : value.type === tuple.typeName,
95
- )
96
- .map(([_key, value]) => value);
97
- for (const m of matched)
98
- output[m.status] = {
99
- type: tuple.type,
100
- typeName: tuple.typeName,
101
- contentType: "application/json",
102
- description: m.description,
103
- };
104
- return true;
105
- };
106
- }
107
-
108
- const TYPED_EXCEPTION_PATH = path.join(
109
- "node_modules",
110
- "@nestia",
111
- "core",
112
- "lib",
113
- "decorators",
114
- "TypedException.d.ts",
115
- );
1
+ import path from "path";
2
+ import ts from "typescript";
3
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
4
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
5
+ import { Metadata } from "typia/lib/schemas/metadata/Metadata";
6
+
7
+ import { IController } from "../structures/IController";
8
+ import { INestiaProject } from "../structures/INestiaProject";
9
+ import { IRoute } from "../structures/IRoute";
10
+ import { ITypeTuple } from "../structures/ITypeTuple";
11
+ import { GenericAnalyzer } from "./GenericAnalyzer";
12
+ import { ImportAnalyzer } from "./ImportAnalyzer";
13
+
14
+ export namespace ExceptionAnalyzer {
15
+ export const analyze =
16
+ (project: INestiaProject) =>
17
+ (
18
+ genericDict: GenericAnalyzer.Dictionary,
19
+ importDict: ImportAnalyzer.Dictionary,
20
+ ) =>
21
+ (controller: IController, func: IController.IFunction) =>
22
+ (
23
+ declaration: ts.MethodDeclaration,
24
+ ): Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput> => {
25
+ const output: Record<
26
+ number | "2XX" | "3XX" | "4XX" | "5XX",
27
+ IRoute.IOutput
28
+ > = {} as any;
29
+ for (const decorator of declaration.modifiers ?? [])
30
+ if (ts.isDecorator(decorator))
31
+ analyzeTyped(project)(genericDict, importDict)(controller, func)(
32
+ output,
33
+ )(decorator);
34
+ return output;
35
+ };
36
+
37
+ const analyzeTyped =
38
+ (project: INestiaProject) =>
39
+ (
40
+ genericDict: GenericAnalyzer.Dictionary,
41
+ importDict: ImportAnalyzer.Dictionary,
42
+ ) =>
43
+ (controller: IController, func: IController.IFunction) =>
44
+ (output: Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput>) =>
45
+ (decorator: ts.Decorator): boolean => {
46
+ // CHECK DECORATOR
47
+ if (!ts.isCallExpression(decorator.expression)) return false;
48
+ else if ((decorator.expression.typeArguments ?? []).length !== 1)
49
+ return false;
50
+
51
+ // CHECK SIGNATURE
52
+ const signature: ts.Signature | undefined =
53
+ project.checker.getResolvedSignature(decorator.expression);
54
+ if (!signature || !signature.declaration) return false;
55
+ else if (
56
+ path
57
+ .resolve(signature.declaration.getSourceFile().fileName)
58
+ .indexOf(TYPED_EXCEPTION_PATH) === -1
59
+ )
60
+ return false;
61
+
62
+ // GET TYPE INFO
63
+ const status: string | null = getStatus(project.checker)(
64
+ decorator.expression.arguments[0] ?? null,
65
+ );
66
+ if (status === null) return false;
67
+
68
+ const node: ts.TypeNode = decorator.expression.typeArguments![0];
69
+ const type: ts.Type = project.checker.getTypeFromTypeNode(node);
70
+ if (type.isTypeParameter()) {
71
+ project.errors.push({
72
+ file: controller.file,
73
+ controller: controller.name,
74
+ function: func.name,
75
+ message: "TypedException() without generic argument specification.",
76
+ });
77
+ return false;
78
+ }
79
+
80
+ const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
81
+ project.checker,
82
+ genericDict,
83
+ importDict,
84
+ type,
85
+ );
86
+ if (
87
+ tuple === null ||
88
+ (project.config.clone !== true &&
89
+ (tuple.typeName === "__type" || tuple.typeName === "__object"))
90
+ ) {
91
+ project.errors.push({
92
+ file: controller.file,
93
+ controller: controller.name,
94
+ function: func.name,
95
+ message: "TypeException() with implicit (unnamed) type.",
96
+ });
97
+ return false;
98
+ }
99
+
100
+ // DO ASSIGN
101
+ const matched: IController.IException[] = Object.entries(func.exceptions)
102
+ .filter(([key]) => status === key)
103
+ .map(([_key, value]) => value);
104
+ for (const m of matched)
105
+ output[m.status] = {
106
+ type: tuple.type,
107
+ typeName: tuple.typeName,
108
+ contentType: "application/json",
109
+ description: m.description,
110
+ };
111
+ return true;
112
+ };
113
+
114
+ const getStatus =
115
+ (checker: ts.TypeChecker) =>
116
+ (expression: ts.Expression | null): string | null => {
117
+ if (expression === null) return null;
118
+
119
+ const type: ts.Type = checker.getTypeAtLocation(expression);
120
+ const result = MetadataFactory.analyze(checker)({
121
+ escape: true,
122
+ constant: true,
123
+ absorb: true,
124
+ })(new MetadataCollection())(type);
125
+ if (false === result.success) return null;
126
+
127
+ const meta: Metadata = result.data;
128
+ if (meta.constants.length === 1)
129
+ return meta.constants[0].values[0].value.toString();
130
+ else if (meta.escaped && meta.escaped.returns.constants.length === 1)
131
+ return meta.escaped.returns.constants[0].values[0].value.toString();
132
+ else if (ts.isStringLiteral(expression)) return expression.text;
133
+ else if (ts.isNumericLiteral(expression)) {
134
+ const value: number = Number(expression.text.split("_").join(""));
135
+ if (false === isNaN(value)) return value.toString();
136
+ }
137
+ return null;
138
+ };
139
+ }
140
+
141
+ const TYPED_EXCEPTION_PATH = path.join(
142
+ "node_modules",
143
+ "@nestia",
144
+ "core",
145
+ "lib",
146
+ "decorators",
147
+ "TypedException.d.ts",
148
+ );
@@ -1,51 +1,51 @@
1
- import ts from "typescript";
2
-
3
- export namespace GenericAnalyzer {
4
- export type Dictionary = WeakMap<ts.Type, ts.Type>;
5
-
6
- export function analyze(
7
- checker: ts.TypeChecker,
8
- classNode: ts.ClassDeclaration,
9
- ): Dictionary {
10
- const dict: Dictionary = new WeakMap();
11
- explore(checker, dict, classNode);
12
- return dict;
13
- }
14
-
15
- function explore(
16
- checker: ts.TypeChecker,
17
- dict: Dictionary,
18
- classNode: ts.ClassDeclaration,
19
- ): void {
20
- if (classNode.heritageClauses === undefined) return;
21
-
22
- for (const heritage of classNode.heritageClauses)
23
- for (const hType of heritage.types) {
24
- // MUST BE CLASS
25
- const expression: ts.Type = checker.getTypeAtLocation(hType.expression);
26
- const superNode: ts.Declaration | undefined =
27
- expression.symbol.getDeclarations()?.[0];
28
-
29
- if (superNode === undefined || !ts.isClassDeclaration(superNode))
30
- continue;
31
-
32
- // SPECIFY GENERICS
33
- const usages: ReadonlyArray<ts.TypeNode> = hType.typeArguments || [];
34
- const parameters: ReadonlyArray<ts.TypeParameterDeclaration> =
35
- superNode.typeParameters || [];
36
-
37
- parameters.forEach((param, index) => {
38
- const paramType: ts.Type = checker.getTypeAtLocation(param);
39
- const usageType: ts.Type =
40
- usages[index] !== undefined
41
- ? checker.getTypeAtLocation(usages[index])
42
- : checker.getTypeAtLocation(param.default!);
43
-
44
- dict.set(paramType, usageType);
45
- });
46
-
47
- // RECUSRIVE EXPLORATION
48
- explore(checker, dict, superNode);
49
- }
50
- }
51
- }
1
+ import ts from "typescript";
2
+
3
+ export namespace GenericAnalyzer {
4
+ export type Dictionary = WeakMap<ts.Type, ts.Type>;
5
+
6
+ export function analyze(
7
+ checker: ts.TypeChecker,
8
+ classNode: ts.ClassDeclaration,
9
+ ): Dictionary {
10
+ const dict: Dictionary = new WeakMap();
11
+ explore(checker, dict, classNode);
12
+ return dict;
13
+ }
14
+
15
+ function explore(
16
+ checker: ts.TypeChecker,
17
+ dict: Dictionary,
18
+ classNode: ts.ClassDeclaration,
19
+ ): void {
20
+ if (classNode.heritageClauses === undefined) return;
21
+
22
+ for (const heritage of classNode.heritageClauses)
23
+ for (const hType of heritage.types) {
24
+ // MUST BE CLASS
25
+ const expression: ts.Type = checker.getTypeAtLocation(hType.expression);
26
+ const superNode: ts.Declaration | undefined =
27
+ expression.symbol.getDeclarations()?.[0];
28
+
29
+ if (superNode === undefined || !ts.isClassDeclaration(superNode))
30
+ continue;
31
+
32
+ // SPECIFY GENERICS
33
+ const usages: ReadonlyArray<ts.TypeNode> = hType.typeArguments || [];
34
+ const parameters: ReadonlyArray<ts.TypeParameterDeclaration> =
35
+ superNode.typeParameters || [];
36
+
37
+ parameters.forEach((param, index) => {
38
+ const paramType: ts.Type = checker.getTypeAtLocation(param);
39
+ const usageType: ts.Type =
40
+ usages[index] !== undefined
41
+ ? checker.getTypeAtLocation(usages[index])
42
+ : checker.getTypeAtLocation(param.default!);
43
+
44
+ dict.set(paramType, usageType);
45
+ });
46
+
47
+ // RECUSRIVE EXPLORATION
48
+ explore(checker, dict, superNode);
49
+ }
50
+ }
51
+ }
@@ -1,5 +1,4 @@
1
- import { HashMap } from "tstl/container/HashMap";
2
- import { HashSet } from "tstl/container/HashSet";
1
+ import { HashMap, HashSet } from "tstl";
3
2
  import ts from "typescript";
4
3
 
5
4
  import { ITypeTuple } from "../structures/ITypeTuple";
@@ -1,98 +1,110 @@
1
- import { RequestMethod } from "@nestjs/common";
2
- import path from "path";
3
- import { Token, parse } from "path-to-regexp";
4
-
5
- import { INormalizedInput } from "../structures/INormalizedInput";
6
-
7
- export namespace PathAnalyzer {
8
- export const combinate =
9
- (globalPrefix: INormalizedInput["globalPrefix"]) =>
10
- (versions: Array<string | null>) =>
11
- (props: { path: string; method: string }): string[] => {
12
- const out = (str: string) =>
13
- versions.map((v) => (v === null ? str : join(v, str)));
14
- if (!globalPrefix?.prefix.length) return out(props.path);
15
- else if (!globalPrefix.exclude?.length)
16
- return out(props.path).map((str) => join(globalPrefix.prefix, str));
17
- return globalPrefix.exclude.some((exclude) =>
18
- typeof exclude === "string"
19
- ? RegExp(exclude).test(props.path)
20
- : METHOD(exclude.method) === props.method &&
21
- RegExp(exclude.path).test(props.path),
22
- )
23
- ? out(props.path)
24
- : out(props.path).map((str) => join(globalPrefix.prefix, str));
25
- };
26
-
27
- export const join = (...args: string[]) =>
28
- "/" +
29
- _Trim(
30
- path
31
- .join(...args.filter((s) => !!s.length))
32
- .split("\\")
33
- .join("/"),
34
- );
35
-
36
- export const escape = (str: string, method: () => string) =>
37
- "/" +
38
- _Parse(str, method)
39
- .map((arg) => (arg.type === "param" ? `:${arg.value}` : arg.value))
40
- .join("/");
41
-
42
- export const parameters = (str: string, method: () => string) =>
43
- _Parse(str, method)
44
- .filter((arg) => arg.type === "param")
45
- .map((arg) => arg.value);
46
-
47
- function _Parse(str: string, method: () => string): IArgument[] {
48
- const tokens: Token[] = parse(path.join(str).split("\\").join("/"));
49
- const output: IArgument[] = [];
50
-
51
- for (const key of tokens) {
52
- if (typeof key === "string")
53
- output.push({
54
- type: "path",
55
- value: _Trim(key),
56
- });
57
- else if (typeof key.name === "number" || _Trim(key.name) === "")
58
- throw new Error(`Error on ${method}: ${ERROR_MESSAGE}.`);
59
- else
60
- output.push({
61
- type: "param",
62
- value: _Trim(key.name),
63
- });
64
- }
65
- return output;
66
- }
67
-
68
- function _Trim(str: string): string {
69
- if (str[0] === "/") str = str.substring(1);
70
- if (str[str.length - 1] === "/") str = str.substring(0, str.length - 1);
71
- return str;
72
- }
73
-
74
- interface IArgument {
75
- type: "param" | "path";
76
- value: string;
77
- }
78
- }
79
-
80
- const ERROR_MESSAGE = "nestia supports only string typed parameter on path";
81
- const METHOD = (value: RequestMethod) =>
82
- value === RequestMethod.ALL
83
- ? "all"
84
- : value === RequestMethod.DELETE
85
- ? "delete"
86
- : value === RequestMethod.GET
87
- ? "get"
88
- : value === RequestMethod.HEAD
89
- ? "head"
90
- : value === RequestMethod.OPTIONS
91
- ? "options"
92
- : value === RequestMethod.PATCH
93
- ? "patch"
94
- : value === RequestMethod.POST
95
- ? "post"
96
- : value === RequestMethod.PUT
97
- ? "put"
98
- : "unknown";
1
+ import { RequestMethod } from "@nestjs/common";
2
+ import path from "path";
3
+ import { Token, parse } from "path-to-regexp";
4
+
5
+ import { INormalizedInput } from "../structures/INormalizedInput";
6
+
7
+ export namespace PathAnalyzer {
8
+ export const combinate =
9
+ (globalPrefix: INormalizedInput["globalPrefix"]) =>
10
+ (versions: Array<string | null>) =>
11
+ (props: { path: string; method: string }): string[] => {
12
+ const out = (str: string) =>
13
+ versions.map((v) => (v === null ? str : join(v, str)));
14
+ if (!globalPrefix?.prefix.length) return out(props.path);
15
+ else if (!globalPrefix.exclude?.length)
16
+ return out(props.path).map((str) => join(globalPrefix.prefix, str));
17
+ return globalPrefix.exclude.some((exclude) =>
18
+ typeof exclude === "string"
19
+ ? RegExp(exclude).test(props.path)
20
+ : METHOD(exclude.method) === props.method &&
21
+ RegExp(exclude.path).test(props.path),
22
+ )
23
+ ? out(props.path)
24
+ : out(props.path).map((str) => join(globalPrefix.prefix, str));
25
+ };
26
+
27
+ export const join = (...args: string[]) =>
28
+ "/" +
29
+ _Trim(
30
+ path
31
+ .join(...args.filter((s) => !!s.length))
32
+ .split("\\")
33
+ .join("/"),
34
+ );
35
+
36
+ export const escape = (str: string): string | null => {
37
+ const args = _Parse(str);
38
+ if (args === null) return null;
39
+ return (
40
+ "/" +
41
+ args
42
+ .map((arg) => (arg.type === "param" ? `:${arg.value}` : arg.value))
43
+ .join("/")
44
+ );
45
+ };
46
+
47
+ export const parameters = (str: string): string[] | null => {
48
+ const args = _Parse(str);
49
+ if (args === null) return null;
50
+ return args.filter((arg) => arg.type === "param").map((arg) => arg.value);
51
+ };
52
+
53
+ function _Parse(str: string): IArgument[] | null {
54
+ const tokens: Token[] | null = (() => {
55
+ try {
56
+ return parse(path.join(str).split("\\").join("/"));
57
+ } catch {
58
+ return null;
59
+ }
60
+ })();
61
+ if (tokens === null) return null;
62
+
63
+ const output: IArgument[] = [];
64
+ for (const key of tokens) {
65
+ if (typeof key === "string")
66
+ output.push({
67
+ type: "path",
68
+ value: _Trim(key),
69
+ });
70
+ else if (typeof key.name === "number" || _Trim(key.name) === "")
71
+ return null;
72
+ else
73
+ output.push({
74
+ type: "param",
75
+ value: _Trim(key.name),
76
+ });
77
+ }
78
+ return output;
79
+ }
80
+
81
+ function _Trim(str: string): string {
82
+ if (str[0] === "/") str = str.substring(1);
83
+ if (str[str.length - 1] === "/") str = str.substring(0, str.length - 1);
84
+ return str;
85
+ }
86
+
87
+ interface IArgument {
88
+ type: "param" | "path";
89
+ value: string;
90
+ }
91
+ }
92
+
93
+ const METHOD = (value: RequestMethod) =>
94
+ value === RequestMethod.ALL
95
+ ? "all"
96
+ : value === RequestMethod.DELETE
97
+ ? "delete"
98
+ : value === RequestMethod.GET
99
+ ? "get"
100
+ : value === RequestMethod.HEAD
101
+ ? "head"
102
+ : value === RequestMethod.OPTIONS
103
+ ? "options"
104
+ : value === RequestMethod.PATCH
105
+ ? "patch"
106
+ : value === RequestMethod.POST
107
+ ? "post"
108
+ : value === RequestMethod.PUT
109
+ ? "put"
110
+ : "unknown";