@nestia/sdk 0.2.0 → 1.0.1

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 (38) hide show
  1. package/assets/config/nestia.config.ts +79 -70
  2. package/lib/INestiaConfig.d.ts +18 -14
  3. package/lib/executable/sdk.js +16 -16
  4. package/lib/generates/FunctionGenerator.js +9 -9
  5. package/lib/generates/FunctionGenerator.js.map +1 -1
  6. package/lib/generates/SwaggerGenerator.js +9 -9
  7. package/package.json +3 -3
  8. package/src/INestiaConfig.ts +124 -120
  9. package/src/NestiaSdkApplication.ts +183 -183
  10. package/src/analyses/ControllerAnalyzer.ts +203 -203
  11. package/src/analyses/GenericAnalyzer.ts +53 -53
  12. package/src/analyses/ImportAnalyzer.ts +143 -143
  13. package/src/analyses/PathAnalyzer.ts +58 -58
  14. package/src/analyses/ReflectAnalyzer.ts +279 -279
  15. package/src/analyses/SourceFinder.ts +59 -59
  16. package/src/executable/internal/CommandParser.ts +15 -15
  17. package/src/executable/internal/NestiaConfigCompilerOptions.ts +18 -18
  18. package/src/executable/internal/NestiaSdkCommand.ts +174 -174
  19. package/src/executable/internal/NestiaSdkConfig.ts +35 -35
  20. package/src/executable/internal/nestia.config.getter.ts +12 -12
  21. package/src/executable/sdk.ts +74 -74
  22. package/src/generates/FileGenerator.ts +156 -156
  23. package/src/generates/FunctionGenerator.ts +284 -287
  24. package/src/generates/SdkGenerator.ts +50 -50
  25. package/src/generates/SwaggerGenerator.ts +393 -393
  26. package/src/index.ts +3 -3
  27. package/src/module.ts +2 -2
  28. package/src/structures/IController.ts +27 -27
  29. package/src/structures/IRoute.ts +29 -29
  30. package/src/structures/ISwagger.ts +55 -55
  31. package/src/structures/ITypeTuple.ts +6 -6
  32. package/src/structures/MethodType.ts +11 -11
  33. package/src/structures/ParamCategory.ts +1 -1
  34. package/src/structures/TypeEntry.ts +22 -22
  35. package/src/utils/ArrayUtil.ts +26 -26
  36. package/src/utils/ImportDictionary.ts +56 -56
  37. package/src/utils/MapUtil.ts +14 -14
  38. package/src/utils/StripEnums.ts +10 -10
@@ -1,203 +1,203 @@
1
- import { HashMap } from "tstl/container/HashMap";
2
- import ts from "typescript";
3
-
4
- import { IController } from "../structures/IController";
5
- import { IRoute } from "../structures/IRoute";
6
- import { ITypeTuple } from "../structures/ITypeTuple";
7
- import { GenericAnalyzer } from "./GenericAnalyzer";
8
- import { ImportAnalyzer } from "./ImportAnalyzer";
9
- import { PathAnalyzer } from "./PathAnalyzer";
10
-
11
- export namespace ControllerAnalyzer {
12
- export function analyze(
13
- checker: ts.TypeChecker,
14
- sourceFile: ts.SourceFile,
15
- controller: IController,
16
- ): IRoute[] {
17
- // FIND CONTROLLER CLASS
18
- const ret: IRoute[] = [];
19
- ts.forEachChild(sourceFile, (node) => {
20
- if (
21
- ts.isClassDeclaration(node) &&
22
- node.name?.escapedText === controller.name
23
- ) {
24
- // ANALYZE THE CONTROLLER
25
- ret.push(..._Analyze_controller(checker, controller, node));
26
- return;
27
- }
28
- });
29
- return ret;
30
- }
31
-
32
- /* ---------------------------------------------------------
33
- CLASS
34
- --------------------------------------------------------- */
35
- function _Analyze_controller(
36
- checker: ts.TypeChecker,
37
- controller: IController,
38
- classNode: ts.ClassDeclaration,
39
- ): IRoute[] {
40
- const classType: ts.InterfaceType = checker.getTypeAtLocation(
41
- classNode,
42
- ) as ts.InterfaceType;
43
- const genericDict: GenericAnalyzer.Dictionary = GenericAnalyzer.analyze(
44
- checker,
45
- classNode,
46
- );
47
-
48
- const ret: IRoute[] = [];
49
- for (const property of classType.getProperties()) {
50
- // GET METHOD DECLARATION
51
- const declaration: ts.Declaration | undefined =
52
- (property.declarations || [])[0];
53
- if (!declaration || !ts.isMethodDeclaration(declaration)) continue;
54
-
55
- // IDENTIFIER MUST BE
56
- const identifier = declaration.name;
57
- if (!ts.isIdentifier(identifier)) continue;
58
-
59
- // ANALYZED WITH THE REFLECTED-FUNCTION
60
- const runtime: IController.IFunction | undefined =
61
- controller.functions.find(
62
- (f) => f.name === identifier.escapedText,
63
- );
64
- if (runtime === undefined) continue;
65
-
66
- const routes: IRoute[] = _Analyze_function(
67
- checker,
68
- controller,
69
- genericDict,
70
- runtime,
71
- property,
72
- );
73
- ret.push(...routes);
74
- }
75
- return ret;
76
- }
77
-
78
- /* ---------------------------------------------------------
79
- FUNCTION
80
- --------------------------------------------------------- */
81
- function _Analyze_function(
82
- checker: ts.TypeChecker,
83
- controller: IController,
84
- genericDict: GenericAnalyzer.Dictionary,
85
- func: IController.IFunction,
86
- symbol: ts.Symbol,
87
- ): IRoute[] {
88
- // PREPARE ASSETS
89
- const type: ts.Type = checker.getTypeOfSymbolAtLocation(
90
- symbol,
91
- symbol.valueDeclaration!,
92
- );
93
- const signature: ts.Signature | undefined = checker.getSignaturesOfType(
94
- type,
95
- ts.SignatureKind.Call,
96
- )[0];
97
-
98
- if (signature === undefined)
99
- throw new Error(
100
- `Error on ControllerAnalyzer.analyze(): unable to get the signature from the ${controller.name}.${func.name}().`,
101
- );
102
-
103
- const importDict: ImportAnalyzer.Dictionary = new HashMap();
104
-
105
- // EXPLORE CHILDREN TYPES
106
- const parameters: IRoute.IParameter[] = func.parameters.map((param) =>
107
- _Analyze_parameter(
108
- checker,
109
- genericDict,
110
- importDict,
111
- controller,
112
- func.name,
113
- param,
114
- signature.getParameters()[param.index],
115
- ),
116
- );
117
- const output: ITypeTuple = ImportAnalyzer.analyze(
118
- checker,
119
- genericDict,
120
- importDict,
121
- signature.getReturnType(),
122
- );
123
- const imports: [string, string[]][] = importDict
124
- .toJSON()
125
- .map((pair) => [pair.first, pair.second.toJSON()]);
126
-
127
- // CONSTRUCT COMMON DATA
128
- const common: Omit<IRoute, "path"> = {
129
- ...func,
130
- parameters,
131
- output,
132
- imports,
133
-
134
- symbol: `${controller.name}.${func.name}()`,
135
- comments: signature.getDocumentationComment(undefined),
136
- tags: signature.getJsDocTags(),
137
- };
138
-
139
- // CONFIGURE PATHS
140
- const pathList: string[] = [];
141
- for (const controllerPath of controller.paths)
142
- for (const filePath of func.paths) {
143
- const path: string = PathAnalyzer.join(
144
- controllerPath,
145
- filePath,
146
- );
147
- pathList.push(
148
- PathAnalyzer.espace(
149
- path,
150
- () => "ControllerAnalyzer.analyze()",
151
- ),
152
- );
153
- }
154
-
155
- // RETURNS
156
- return pathList.map((path) => ({
157
- ...common,
158
- path,
159
- }));
160
- }
161
-
162
- /* ---------------------------------------------------------
163
- PARAMETER
164
- --------------------------------------------------------- */
165
- function _Analyze_parameter(
166
- checker: ts.TypeChecker,
167
- genericDict: GenericAnalyzer.Dictionary,
168
- importDict: ImportAnalyzer.Dictionary,
169
- controller: IController,
170
- funcName: string,
171
- param: IController.IParameter,
172
- symbol: ts.Symbol,
173
- ): IRoute.IParameter {
174
- const type: ts.Type = checker.getTypeOfSymbolAtLocation(
175
- symbol,
176
- symbol.valueDeclaration!,
177
- );
178
- const name: string = symbol.getEscapedName().toString();
179
-
180
- // DO NOT SUPPORT BODY PARAMETER
181
- if (param.category === "body" && param.field !== undefined) {
182
- const method: string = `${controller.name}.${funcName}()`;
183
- throw new Error(
184
- `Error on ${method}: nestia does not support body field specification. ` +
185
- `Therefore, erase the ${method}#${name} parameter and ` +
186
- `re-define a new body decorator accepting full structured message.`,
187
- );
188
- }
189
-
190
- return {
191
- name,
192
- category: param.category,
193
- field: param.field,
194
- encrypted: param.encrypted,
195
- type: ImportAnalyzer.analyze(
196
- checker,
197
- genericDict,
198
- importDict,
199
- type,
200
- ),
201
- };
202
- }
203
- }
1
+ import { HashMap } from "tstl/container/HashMap";
2
+ import ts from "typescript";
3
+
4
+ import { IController } from "../structures/IController";
5
+ import { IRoute } from "../structures/IRoute";
6
+ import { ITypeTuple } from "../structures/ITypeTuple";
7
+ import { GenericAnalyzer } from "./GenericAnalyzer";
8
+ import { ImportAnalyzer } from "./ImportAnalyzer";
9
+ import { PathAnalyzer } from "./PathAnalyzer";
10
+
11
+ export namespace ControllerAnalyzer {
12
+ export function analyze(
13
+ checker: ts.TypeChecker,
14
+ sourceFile: ts.SourceFile,
15
+ controller: IController,
16
+ ): IRoute[] {
17
+ // FIND CONTROLLER CLASS
18
+ const ret: IRoute[] = [];
19
+ ts.forEachChild(sourceFile, (node) => {
20
+ if (
21
+ ts.isClassDeclaration(node) &&
22
+ node.name?.escapedText === controller.name
23
+ ) {
24
+ // ANALYZE THE CONTROLLER
25
+ ret.push(..._Analyze_controller(checker, controller, node));
26
+ return;
27
+ }
28
+ });
29
+ return ret;
30
+ }
31
+
32
+ /* ---------------------------------------------------------
33
+ CLASS
34
+ --------------------------------------------------------- */
35
+ function _Analyze_controller(
36
+ checker: ts.TypeChecker,
37
+ controller: IController,
38
+ classNode: ts.ClassDeclaration,
39
+ ): IRoute[] {
40
+ const classType: ts.InterfaceType = checker.getTypeAtLocation(
41
+ classNode,
42
+ ) as ts.InterfaceType;
43
+ const genericDict: GenericAnalyzer.Dictionary = GenericAnalyzer.analyze(
44
+ checker,
45
+ classNode,
46
+ );
47
+
48
+ const ret: IRoute[] = [];
49
+ for (const property of classType.getProperties()) {
50
+ // GET METHOD DECLARATION
51
+ const declaration: ts.Declaration | undefined =
52
+ (property.declarations || [])[0];
53
+ if (!declaration || !ts.isMethodDeclaration(declaration)) continue;
54
+
55
+ // IDENTIFIER MUST BE
56
+ const identifier = declaration.name;
57
+ if (!ts.isIdentifier(identifier)) continue;
58
+
59
+ // ANALYZED WITH THE REFLECTED-FUNCTION
60
+ const runtime: IController.IFunction | undefined =
61
+ controller.functions.find(
62
+ (f) => f.name === identifier.escapedText,
63
+ );
64
+ if (runtime === undefined) continue;
65
+
66
+ const routes: IRoute[] = _Analyze_function(
67
+ checker,
68
+ controller,
69
+ genericDict,
70
+ runtime,
71
+ property,
72
+ );
73
+ ret.push(...routes);
74
+ }
75
+ return ret;
76
+ }
77
+
78
+ /* ---------------------------------------------------------
79
+ FUNCTION
80
+ --------------------------------------------------------- */
81
+ function _Analyze_function(
82
+ checker: ts.TypeChecker,
83
+ controller: IController,
84
+ genericDict: GenericAnalyzer.Dictionary,
85
+ func: IController.IFunction,
86
+ symbol: ts.Symbol,
87
+ ): IRoute[] {
88
+ // PREPARE ASSETS
89
+ const type: ts.Type = checker.getTypeOfSymbolAtLocation(
90
+ symbol,
91
+ symbol.valueDeclaration!,
92
+ );
93
+ const signature: ts.Signature | undefined = checker.getSignaturesOfType(
94
+ type,
95
+ ts.SignatureKind.Call,
96
+ )[0];
97
+
98
+ if (signature === undefined)
99
+ throw new Error(
100
+ `Error on ControllerAnalyzer.analyze(): unable to get the signature from the ${controller.name}.${func.name}().`,
101
+ );
102
+
103
+ const importDict: ImportAnalyzer.Dictionary = new HashMap();
104
+
105
+ // EXPLORE CHILDREN TYPES
106
+ const parameters: IRoute.IParameter[] = func.parameters.map((param) =>
107
+ _Analyze_parameter(
108
+ checker,
109
+ genericDict,
110
+ importDict,
111
+ controller,
112
+ func.name,
113
+ param,
114
+ signature.getParameters()[param.index],
115
+ ),
116
+ );
117
+ const output: ITypeTuple = ImportAnalyzer.analyze(
118
+ checker,
119
+ genericDict,
120
+ importDict,
121
+ signature.getReturnType(),
122
+ );
123
+ const imports: [string, string[]][] = importDict
124
+ .toJSON()
125
+ .map((pair) => [pair.first, pair.second.toJSON()]);
126
+
127
+ // CONSTRUCT COMMON DATA
128
+ const common: Omit<IRoute, "path"> = {
129
+ ...func,
130
+ parameters,
131
+ output,
132
+ imports,
133
+
134
+ symbol: `${controller.name}.${func.name}()`,
135
+ comments: signature.getDocumentationComment(undefined),
136
+ tags: signature.getJsDocTags(),
137
+ };
138
+
139
+ // CONFIGURE PATHS
140
+ const pathList: string[] = [];
141
+ for (const controllerPath of controller.paths)
142
+ for (const filePath of func.paths) {
143
+ const path: string = PathAnalyzer.join(
144
+ controllerPath,
145
+ filePath,
146
+ );
147
+ pathList.push(
148
+ PathAnalyzer.espace(
149
+ path,
150
+ () => "ControllerAnalyzer.analyze()",
151
+ ),
152
+ );
153
+ }
154
+
155
+ // RETURNS
156
+ return pathList.map((path) => ({
157
+ ...common,
158
+ path,
159
+ }));
160
+ }
161
+
162
+ /* ---------------------------------------------------------
163
+ PARAMETER
164
+ --------------------------------------------------------- */
165
+ function _Analyze_parameter(
166
+ checker: ts.TypeChecker,
167
+ genericDict: GenericAnalyzer.Dictionary,
168
+ importDict: ImportAnalyzer.Dictionary,
169
+ controller: IController,
170
+ funcName: string,
171
+ param: IController.IParameter,
172
+ symbol: ts.Symbol,
173
+ ): IRoute.IParameter {
174
+ const type: ts.Type = checker.getTypeOfSymbolAtLocation(
175
+ symbol,
176
+ symbol.valueDeclaration!,
177
+ );
178
+ const name: string = symbol.getEscapedName().toString();
179
+
180
+ // DO NOT SUPPORT BODY PARAMETER
181
+ if (param.category === "body" && param.field !== undefined) {
182
+ const method: string = `${controller.name}.${funcName}()`;
183
+ throw new Error(
184
+ `Error on ${method}: nestia does not support body field specification. ` +
185
+ `Therefore, erase the ${method}#${name} parameter and ` +
186
+ `re-define a new body decorator accepting full structured message.`,
187
+ );
188
+ }
189
+
190
+ return {
191
+ name,
192
+ category: param.category,
193
+ field: param.field,
194
+ encrypted: param.encrypted,
195
+ type: ImportAnalyzer.analyze(
196
+ checker,
197
+ genericDict,
198
+ importDict,
199
+ type,
200
+ ),
201
+ };
202
+ }
203
+ }
@@ -1,53 +1,53 @@
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(
26
- hType.expression,
27
- );
28
- const superNode: ts.Declaration =
29
- expression.symbol.getDeclarations()![0];
30
-
31
- if (!ts.isClassDeclaration(superNode)) continue;
32
-
33
- // SPECIFY GENERICS
34
- const usages: ReadonlyArray<ts.TypeNode> =
35
- hType.typeArguments || [];
36
- const parameters: ReadonlyArray<ts.TypeParameterDeclaration> =
37
- superNode.typeParameters || [];
38
-
39
- parameters.forEach((param, index) => {
40
- const paramType: ts.Type = checker.getTypeAtLocation(param);
41
- const usageType: ts.Type =
42
- usages[index] !== undefined
43
- ? checker.getTypeAtLocation(usages[index])
44
- : checker.getTypeAtLocation(param.default!);
45
-
46
- dict.set(paramType, usageType);
47
- });
48
-
49
- // RECUSRIVE EXPLORATION
50
- explore(checker, dict, superNode);
51
- }
52
- }
53
- }
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(
26
+ hType.expression,
27
+ );
28
+ const superNode: ts.Declaration =
29
+ expression.symbol.getDeclarations()![0];
30
+
31
+ if (!ts.isClassDeclaration(superNode)) continue;
32
+
33
+ // SPECIFY GENERICS
34
+ const usages: ReadonlyArray<ts.TypeNode> =
35
+ hType.typeArguments || [];
36
+ const parameters: ReadonlyArray<ts.TypeParameterDeclaration> =
37
+ superNode.typeParameters || [];
38
+
39
+ parameters.forEach((param, index) => {
40
+ const paramType: ts.Type = checker.getTypeAtLocation(param);
41
+ const usageType: ts.Type =
42
+ usages[index] !== undefined
43
+ ? checker.getTypeAtLocation(usages[index])
44
+ : checker.getTypeAtLocation(param.default!);
45
+
46
+ dict.set(paramType, usageType);
47
+ });
48
+
49
+ // RECUSRIVE EXPLORATION
50
+ explore(checker, dict, superNode);
51
+ }
52
+ }
53
+ }