@nestia/sdk 2.3.0-dev.20231019 → 2.3.0
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.
- package/assets/config/nestia.config.ts +3 -3
- package/lib/INestiaConfig.d.ts +1 -1
- package/lib/NestiaSdkApplication.js +41 -4
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.d.ts +2 -2
- package/lib/analyses/ControllerAnalyzer.js +107 -65
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ExceptionAnalyzer.d.ts +2 -1
- package/lib/analyses/ExceptionAnalyzer.js +23 -9
- package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectAnalyzer.d.ts +2 -1
- package/lib/analyses/ReflectAnalyzer.js +51 -37
- package/lib/analyses/ReflectAnalyzer.js.map +1 -1
- package/lib/executable/sdk.js +1 -0
- package/lib/executable/sdk.js.map +1 -1
- package/lib/structures/IErrorReport.d.ts +6 -0
- package/lib/structures/IErrorReport.js +3 -0
- package/lib/structures/IErrorReport.js.map +1 -0
- package/lib/structures/INestiaProject.d.ts +10 -0
- package/lib/structures/INestiaProject.js +3 -0
- package/lib/structures/INestiaProject.js.map +1 -0
- package/package.json +5 -5
- package/src/INestiaConfig.ts +1 -1
- package/src/NestiaSdkApplication.ts +45 -9
- package/src/analyses/ControllerAnalyzer.ts +336 -307
- package/src/analyses/ExceptionAnalyzer.ts +31 -15
- package/src/analyses/ReflectAnalyzer.ts +235 -211
- package/src/executable/sdk.ts +1 -0
- package/src/structures/IErrorReport.ts +6 -0
- package/src/structures/INestiaProject.ts +12 -0
|
@@ -2,6 +2,7 @@ import path from "path";
|
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
|
|
4
4
|
import { IController } from "../structures/IController";
|
|
5
|
+
import { INestiaProject } from "../structures/INestiaProject";
|
|
5
6
|
import { IRoute } from "../structures/IRoute";
|
|
6
7
|
import { ITypeTuple } from "../structures/ITypeTuple";
|
|
7
8
|
import { GenericAnalyzer } from "./GenericAnalyzer";
|
|
@@ -9,12 +10,12 @@ import { ImportAnalyzer } from "./ImportAnalyzer";
|
|
|
9
10
|
|
|
10
11
|
export namespace ExceptionAnalyzer {
|
|
11
12
|
export const analyze =
|
|
12
|
-
(
|
|
13
|
+
(project: INestiaProject) =>
|
|
13
14
|
(
|
|
14
15
|
genericDict: GenericAnalyzer.Dictionary,
|
|
15
16
|
importDict: ImportAnalyzer.Dictionary,
|
|
16
17
|
) =>
|
|
17
|
-
(func: IController.IFunction) =>
|
|
18
|
+
(controller: IController, func: IController.IFunction) =>
|
|
18
19
|
(
|
|
19
20
|
declaration: ts.MethodDeclaration,
|
|
20
21
|
): Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput> => {
|
|
@@ -24,19 +25,20 @@ export namespace ExceptionAnalyzer {
|
|
|
24
25
|
> = {} as any;
|
|
25
26
|
for (const decorator of declaration.modifiers ?? [])
|
|
26
27
|
if (ts.isDecorator(decorator))
|
|
27
|
-
analyzeTyped(
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
analyzeTyped(project)(genericDict, importDict)(
|
|
29
|
+
controller,
|
|
30
|
+
func,
|
|
31
|
+
)(output)(decorator);
|
|
30
32
|
return output;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
const analyzeTyped =
|
|
34
|
-
(
|
|
36
|
+
(project: INestiaProject) =>
|
|
35
37
|
(
|
|
36
38
|
genericDict: GenericAnalyzer.Dictionary,
|
|
37
39
|
importDict: ImportAnalyzer.Dictionary,
|
|
38
40
|
) =>
|
|
39
|
-
(func: IController.IFunction) =>
|
|
41
|
+
(controller: IController, func: IController.IFunction) =>
|
|
40
42
|
(
|
|
41
43
|
output: Record<
|
|
42
44
|
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
@@ -51,7 +53,7 @@ export namespace ExceptionAnalyzer {
|
|
|
51
53
|
|
|
52
54
|
// CHECK SIGNATURE
|
|
53
55
|
const signature: ts.Signature | undefined =
|
|
54
|
-
checker.getResolvedSignature(decorator.expression);
|
|
56
|
+
project.checker.getResolvedSignature(decorator.expression);
|
|
55
57
|
if (!signature || !signature.declaration) return false;
|
|
56
58
|
else if (
|
|
57
59
|
path
|
|
@@ -62,19 +64,33 @@ export namespace ExceptionAnalyzer {
|
|
|
62
64
|
|
|
63
65
|
// GET TYPE INFO
|
|
64
66
|
const node: ts.TypeNode = decorator.expression.typeArguments![0];
|
|
65
|
-
const type: ts.Type = checker.getTypeFromTypeNode(node);
|
|
66
|
-
if (type.isTypeParameter())
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const type: ts.Type = project.checker.getTypeFromTypeNode(node);
|
|
68
|
+
if (type.isTypeParameter()) {
|
|
69
|
+
project.errors.push({
|
|
70
|
+
file: controller.file,
|
|
71
|
+
controller: controller.name,
|
|
72
|
+
function: func.name,
|
|
73
|
+
message:
|
|
74
|
+
"TypedException() without generic argument specification.",
|
|
75
|
+
});
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
70
78
|
|
|
71
79
|
const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
|
|
72
|
-
checker,
|
|
80
|
+
project.checker,
|
|
73
81
|
genericDict,
|
|
74
82
|
importDict,
|
|
75
83
|
type,
|
|
76
84
|
);
|
|
77
|
-
if (tuple === null)
|
|
85
|
+
if (tuple === null || tuple.typeName === "__type") {
|
|
86
|
+
project.errors.push({
|
|
87
|
+
file: controller.file,
|
|
88
|
+
controller: controller.name,
|
|
89
|
+
function: func.name,
|
|
90
|
+
message: "TypeException() with implicit (unnamed) type.",
|
|
91
|
+
});
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
78
94
|
|
|
79
95
|
// DO ASSIGN
|
|
80
96
|
const matched: IController.IException[] = Object.entries(
|
|
@@ -4,6 +4,8 @@ import "reflect-metadata";
|
|
|
4
4
|
import { equal } from "tstl/ranges/module";
|
|
5
5
|
|
|
6
6
|
import { IController } from "../structures/IController";
|
|
7
|
+
import { IErrorReport } from "../structures/IErrorReport";
|
|
8
|
+
import { INestiaProject } from "../structures/INestiaProject";
|
|
7
9
|
import { ParamCategory } from "../structures/ParamCategory";
|
|
8
10
|
import { ArrayUtil } from "../utils/ArrayUtil";
|
|
9
11
|
import { PathAnalyzer } from "./PathAnalyzer";
|
|
@@ -14,105 +16,107 @@ type IModule = {
|
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
export namespace ReflectAnalyzer {
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
export const analyze =
|
|
20
|
+
(project: INestiaProject) =>
|
|
21
|
+
async (
|
|
22
|
+
unique: WeakSet<any>,
|
|
23
|
+
file: string,
|
|
24
|
+
prefixes: string[],
|
|
25
|
+
target?: Function,
|
|
26
|
+
): Promise<IController[]> => {
|
|
27
|
+
const module: IModule = await (async () => {
|
|
28
|
+
try {
|
|
29
|
+
return await import(file);
|
|
30
|
+
} catch (exp) {
|
|
31
|
+
console.log(
|
|
32
|
+
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",
|
|
33
|
+
);
|
|
34
|
+
console.log(`Error on "${file}" file. Check your code.`);
|
|
35
|
+
console.log(exp);
|
|
36
|
+
console.log(
|
|
37
|
+
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",
|
|
38
|
+
);
|
|
39
|
+
process.exit(-1);
|
|
40
|
+
}
|
|
41
|
+
})();
|
|
42
|
+
const ret: IController[] = [];
|
|
43
|
+
|
|
44
|
+
for (const [key, value] of Object.entries(module)) {
|
|
45
|
+
if (typeof value !== "function" || unique.has(value)) continue;
|
|
46
|
+
else if ((target ?? value) !== value) continue;
|
|
47
|
+
else unique.add(value);
|
|
48
|
+
|
|
49
|
+
const result: IController | null = _Analyze_controller(project)(
|
|
50
|
+
file,
|
|
51
|
+
key,
|
|
52
|
+
value,
|
|
53
|
+
prefixes,
|
|
34
54
|
);
|
|
35
|
-
|
|
55
|
+
if (result !== null) ret.push(result);
|
|
36
56
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
for (const [key, value] of Object.entries(module)) {
|
|
41
|
-
if (typeof value !== "function" || unique.has(value)) continue;
|
|
42
|
-
else if ((target ?? value) !== value) continue;
|
|
43
|
-
else unique.add(value);
|
|
44
|
-
|
|
45
|
-
const result: IController | null = _Analyze_controller(
|
|
46
|
-
file,
|
|
47
|
-
key,
|
|
48
|
-
value,
|
|
49
|
-
prefixes,
|
|
50
|
-
);
|
|
51
|
-
if (result !== null) ret.push(result);
|
|
52
|
-
}
|
|
53
|
-
return ret;
|
|
54
|
-
}
|
|
57
|
+
return ret;
|
|
58
|
+
};
|
|
55
59
|
|
|
56
60
|
/* ---------------------------------------------------------
|
|
57
61
|
CONTROLLER
|
|
58
62
|
--------------------------------------------------------- */
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
const _Analyze_controller =
|
|
64
|
+
(project: INestiaProject) =>
|
|
65
|
+
(
|
|
66
|
+
file: string,
|
|
67
|
+
name: string,
|
|
68
|
+
creator: any,
|
|
69
|
+
prefixes: string[],
|
|
70
|
+
): IController | null => {
|
|
71
|
+
//----
|
|
72
|
+
// VALIDATIONS
|
|
73
|
+
//----
|
|
74
|
+
// MUST BE TYPE OF A CREATOR WHO HAS THE CONSTRUCTOR
|
|
75
|
+
if (
|
|
76
|
+
!(
|
|
77
|
+
creator instanceof Function &&
|
|
78
|
+
creator.constructor instanceof Function
|
|
79
|
+
)
|
|
73
80
|
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
return null;
|
|
86
|
-
|
|
87
|
-
//----
|
|
88
|
-
// CONSTRUCTION
|
|
89
|
-
//----
|
|
90
|
-
// BASIC INFO
|
|
91
|
-
const meta: IController = {
|
|
92
|
-
file,
|
|
93
|
-
name,
|
|
94
|
-
functions: [],
|
|
95
|
-
prefixes,
|
|
96
|
-
paths: _Get_paths(creator),
|
|
97
|
-
versions: _Get_versions(creator),
|
|
98
|
-
security: _Get_securities(creator),
|
|
99
|
-
swaggerTgas:
|
|
100
|
-
Reflect.getMetadata("swagger/apiUseTags", creator) ?? [],
|
|
101
|
-
};
|
|
81
|
+
return null;
|
|
82
|
+
// MUST HAVE THOSE MATADATA
|
|
83
|
+
else if (
|
|
84
|
+
ArrayUtil.has(
|
|
85
|
+
Reflect.getMetadataKeys(creator),
|
|
86
|
+
Constants.PATH_METADATA,
|
|
87
|
+
Constants.HOST_METADATA,
|
|
88
|
+
Constants.SCOPE_OPTIONS_METADATA,
|
|
89
|
+
) === false
|
|
90
|
+
)
|
|
91
|
+
return null;
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
93
|
+
//----
|
|
94
|
+
// CONSTRUCTION
|
|
95
|
+
//----
|
|
96
|
+
// BASIC INFO
|
|
97
|
+
const meta: IController = {
|
|
98
|
+
file,
|
|
99
|
+
name,
|
|
100
|
+
functions: [],
|
|
101
|
+
prefixes,
|
|
102
|
+
paths: _Get_paths(creator),
|
|
103
|
+
versions: _Get_versions(creator),
|
|
104
|
+
security: _Get_securities(creator),
|
|
105
|
+
swaggerTgas:
|
|
106
|
+
Reflect.getMetadata("swagger/apiUseTags", creator) ?? [],
|
|
107
|
+
};
|
|
112
108
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
// PARSE CHILDREN DATA
|
|
110
|
+
for (const tuple of _Get_prototype_entries(creator)) {
|
|
111
|
+
const child: IController.IFunction | null = _Analyze_function(
|
|
112
|
+
project,
|
|
113
|
+
)(creator.prototype, meta, ...tuple);
|
|
114
|
+
if (child !== null) meta.functions.push(child);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// RETURNS
|
|
118
|
+
return meta;
|
|
119
|
+
};
|
|
116
120
|
|
|
117
121
|
function _Get_prototype_entries(creator: any): Array<[string, unknown]> {
|
|
118
122
|
const keyList = Object.getOwnPropertyNames(creator.prototype);
|
|
@@ -172,132 +176,152 @@ export namespace ReflectAnalyzer {
|
|
|
172
176
|
/* ---------------------------------------------------------
|
|
173
177
|
FUNCTION
|
|
174
178
|
--------------------------------------------------------- */
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
?.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
`Error on ${controller.name}.${name}(): "body" parameter cannot be used in the "GET" or "HEAD" method`,
|
|
179
|
+
const _Analyze_function =
|
|
180
|
+
(project: INestiaProject) =>
|
|
181
|
+
(
|
|
182
|
+
classProto: any,
|
|
183
|
+
controller: IController,
|
|
184
|
+
name: string,
|
|
185
|
+
proto: any,
|
|
186
|
+
): IController.IFunction | null => {
|
|
187
|
+
//----
|
|
188
|
+
// VALIDATIONS
|
|
189
|
+
//----
|
|
190
|
+
// MUST BE TYPE OF A FUNCTION
|
|
191
|
+
if (!(proto instanceof Function)) return null;
|
|
192
|
+
// MUST HAVE THOSE METADATE
|
|
193
|
+
else if (
|
|
194
|
+
ArrayUtil.has(
|
|
195
|
+
Reflect.getMetadataKeys(proto),
|
|
196
|
+
Constants.PATH_METADATA,
|
|
197
|
+
Constants.METHOD_METADATA,
|
|
198
|
+
) === false
|
|
199
|
+
)
|
|
200
|
+
return null;
|
|
201
|
+
|
|
202
|
+
const errors: IErrorReport[] = [];
|
|
203
|
+
|
|
204
|
+
//----
|
|
205
|
+
// CONSTRUCTION
|
|
206
|
+
//----
|
|
207
|
+
// BASIC INFO
|
|
208
|
+
const encrypted: boolean =
|
|
209
|
+
Reflect.getMetadata(Constants.INTERCEPTORS_METADATA, proto)?.[0]
|
|
210
|
+
?.constructor?.name === "EncryptedRouteInterceptor";
|
|
211
|
+
const query: boolean =
|
|
212
|
+
Reflect.getMetadata(Constants.INTERCEPTORS_METADATA, proto)?.[0]
|
|
213
|
+
?.constructor?.name === "TypedQueryRouteInterceptor";
|
|
214
|
+
const method: string =
|
|
215
|
+
METHODS[Reflect.getMetadata(Constants.METHOD_METADATA, proto)];
|
|
216
|
+
if (method === undefined || method === "OPTIONS") return null;
|
|
217
|
+
|
|
218
|
+
const parameters: IController.IParameter[] = (() => {
|
|
219
|
+
const nestParameters: NestParameters | undefined =
|
|
220
|
+
Reflect.getMetadata(
|
|
221
|
+
Constants.ROUTE_ARGS_METADATA,
|
|
222
|
+
classProto.constructor,
|
|
223
|
+
name,
|
|
224
|
+
);
|
|
225
|
+
if (nestParameters === undefined) return [];
|
|
226
|
+
|
|
227
|
+
const output: IController.IParameter[] = [];
|
|
228
|
+
for (const tuple of Object.entries(nestParameters)) {
|
|
229
|
+
const child: IController.IParameter | null =
|
|
230
|
+
_Analyze_parameter(...tuple);
|
|
231
|
+
if (child !== null) output.push(child);
|
|
232
|
+
}
|
|
233
|
+
return output.sort((x, y) => x.index - y.index);
|
|
234
|
+
})();
|
|
235
|
+
|
|
236
|
+
// VALIDATE BODY
|
|
237
|
+
const body: IController.IParameter | undefined = parameters.find(
|
|
238
|
+
(param) => param.category === "body",
|
|
236
239
|
);
|
|
240
|
+
if (body !== undefined && (method === "GET" || method === "HEAD")) {
|
|
241
|
+
errors.push({
|
|
242
|
+
file: controller.file,
|
|
243
|
+
controller: controller.name,
|
|
244
|
+
function: name,
|
|
245
|
+
message: `"body" parameter cannot be used in the "${method}" method.`,
|
|
246
|
+
});
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
237
249
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
metaLocation,
|
|
274
|
-
);
|
|
250
|
+
// DO CONSTRUCT
|
|
251
|
+
const meta: IController.IFunction = {
|
|
252
|
+
name,
|
|
253
|
+
method: method === "ALL" ? "POST" : method,
|
|
254
|
+
paths: _Get_paths(proto),
|
|
255
|
+
versions: _Get_versions(proto),
|
|
256
|
+
parameters,
|
|
257
|
+
status: Reflect.getMetadata(
|
|
258
|
+
Constants.HTTP_CODE_METADATA,
|
|
259
|
+
proto,
|
|
260
|
+
),
|
|
261
|
+
encrypted,
|
|
262
|
+
contentType: encrypted
|
|
263
|
+
? "text/plain"
|
|
264
|
+
: query
|
|
265
|
+
? "application/x-www-form-urlencoded"
|
|
266
|
+
: Reflect.getMetadata(
|
|
267
|
+
Constants.HEADERS_METADATA,
|
|
268
|
+
proto,
|
|
269
|
+
)?.find(
|
|
270
|
+
(h: Record<string, string>) =>
|
|
271
|
+
typeof h?.name === "string" &&
|
|
272
|
+
typeof h?.value === "string" &&
|
|
273
|
+
h.name.toLowerCase() === "content-type",
|
|
274
|
+
)?.value ?? "application/json",
|
|
275
|
+
security: _Get_securities(proto),
|
|
276
|
+
exceptions: _Get_exceptions(proto),
|
|
277
|
+
swaggerTags: [
|
|
278
|
+
...new Set([
|
|
279
|
+
...controller.swaggerTgas,
|
|
280
|
+
...(Reflect.getMetadata("swagger/apiUseTags", proto) ??
|
|
281
|
+
[]),
|
|
282
|
+
]),
|
|
283
|
+
],
|
|
284
|
+
};
|
|
275
285
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
.filter((param) => param.category === "param")
|
|
284
|
-
.map((param) => param.field!)
|
|
285
|
-
.sort();
|
|
286
|
-
|
|
287
|
-
// DO VALIDATE
|
|
288
|
-
if (equal(binded, parameters) === false)
|
|
289
|
-
throw new Error(
|
|
290
|
-
`Error on ${
|
|
291
|
-
controller.name
|
|
292
|
-
}.${name}(): binded arguments in the "path" between function's decorator and parameters' decorators are different (function: [${binded.join(
|
|
293
|
-
", ",
|
|
294
|
-
)}], parameters: [${parameters.join(", ")}])`,
|
|
286
|
+
// VALIDATE PATH ARGUMENTS
|
|
287
|
+
for (const controllerLocation of controller.paths)
|
|
288
|
+
for (const metaLocation of meta.paths) {
|
|
289
|
+
// NORMALIZE LOCATION
|
|
290
|
+
const location: string = PathAnalyzer.join(
|
|
291
|
+
controllerLocation,
|
|
292
|
+
metaLocation,
|
|
295
293
|
);
|
|
296
|
-
}
|
|
297
294
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
295
|
+
// LIST UP PARAMETERS
|
|
296
|
+
const binded: string[] = PathAnalyzer.parameters(
|
|
297
|
+
location,
|
|
298
|
+
() => `${controller.name}.${name}()`,
|
|
299
|
+
).sort();
|
|
300
|
+
|
|
301
|
+
const parameters: string[] = meta.parameters
|
|
302
|
+
.filter((param) => param.category === "param")
|
|
303
|
+
.map((param) => param.field!)
|
|
304
|
+
.sort();
|
|
305
|
+
|
|
306
|
+
// DO VALIDATE
|
|
307
|
+
if (equal(binded, parameters) === false)
|
|
308
|
+
errors.push({
|
|
309
|
+
file: controller.file,
|
|
310
|
+
controller: controller.name,
|
|
311
|
+
function: name,
|
|
312
|
+
message: `binded arguments in the "path" between function's decorator and parameters' decorators are different (function: [${binded.join(
|
|
313
|
+
", ",
|
|
314
|
+
)}], parameters: [${parameters.join(", ")}]).`,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// RETURNS
|
|
319
|
+
if (errors.length) {
|
|
320
|
+
project.errors.push(...errors);
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
return meta;
|
|
324
|
+
};
|
|
301
325
|
|
|
302
326
|
/* ---------------------------------------------------------
|
|
303
327
|
PARAMETER
|
package/src/executable/sdk.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { INestiaConfig } from "../INestiaConfig";
|
|
4
|
+
import { IErrorReport } from "./IErrorReport";
|
|
5
|
+
import { INormalizedInput } from "./INormalizedInput";
|
|
6
|
+
|
|
7
|
+
export interface INestiaProject {
|
|
8
|
+
config: INestiaConfig;
|
|
9
|
+
input: INormalizedInput;
|
|
10
|
+
checker: ts.TypeChecker;
|
|
11
|
+
errors: IErrorReport[];
|
|
12
|
+
}
|