@nestia/sdk 2.0.0-dev.20230904 → 2.0.0-dev.20230906
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/lib/INestiaConfig.d.ts +40 -32
- package/lib/NestiaSdkApplication.d.ts +1 -1
- package/lib/NestiaSdkApplication.js +5 -5
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.js +4 -4
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectAnalyzer.js +9 -1
- package/lib/analyses/ReflectAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaConfigLoader.js +17 -13
- package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
- package/lib/generates/SdkGenerator.d.ts +2 -1
- package/lib/generates/SdkGenerator.js +5 -1
- package/lib/generates/SdkGenerator.js.map +1 -1
- package/lib/generates/SwaggerGenerator.js +12 -8
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.js +15 -10
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkDtoGenerator.d.ts +9 -0
- package/lib/generates/internal/SdkDtoGenerator.js +264 -0
- package/lib/generates/internal/SdkDtoGenerator.js.map +1 -0
- package/lib/generates/internal/SdkFileProgrammer.js +8 -7
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkFunctionProgrammer.js +11 -7
- package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkSimulationProgrammer.js +5 -1
- package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.js +59 -71
- package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaValidator.js +0 -4
- package/lib/generates/internal/SwaggerSchemaValidator.js.map +1 -1
- package/lib/structures/IController.d.ts +2 -0
- package/lib/structures/IRoute.d.ts +5 -1
- package/package.json +5 -5
- package/src/INestiaConfig.ts +43 -34
- package/src/NestiaSdkApplication.ts +5 -9
- package/src/analyses/ControllerAnalyzer.ts +5 -5
- package/src/analyses/ReflectAnalyzer.ts +8 -0
- package/src/generates/SdkGenerator.ts +7 -0
- package/src/generates/SwaggerGenerator.ts +16 -11
- package/src/generates/internal/E2eFileProgrammer.ts +24 -11
- package/src/generates/internal/SdkDtoGenerator.ts +384 -0
- package/src/generates/internal/SdkFileProgrammer.ts +8 -7
- package/src/generates/internal/SdkFunctionProgrammer.ts +35 -7
- package/src/generates/internal/SdkSimulationProgrammer.ts +10 -1
- package/src/generates/internal/SwaggerSchemaGenerator.ts +85 -88
- package/src/generates/internal/SwaggerSchemaValidator.ts +0 -6
- package/src/structures/IController.ts +2 -0
- package/src/structures/IRoute.ts +7 -2
|
@@ -57,14 +57,14 @@ export namespace SwaggerSchemaGenerator {
|
|
|
57
57
|
description: exp.description ?? "",
|
|
58
58
|
content: {
|
|
59
59
|
"application/json": {
|
|
60
|
-
schema:
|
|
60
|
+
schema: coalesce(props)(result),
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// FROM COMMENT TAGS -> ANY
|
|
67
|
-
for (const tag of route.
|
|
67
|
+
for (const tag of route.jsDocTags) {
|
|
68
68
|
if (tag.name !== "throw" && tag.name !== "throws") continue;
|
|
69
69
|
|
|
70
70
|
const text: string | undefined = tag.text?.find(
|
|
@@ -151,7 +151,7 @@ export namespace SwaggerSchemaGenerator {
|
|
|
151
151
|
? undefined
|
|
152
152
|
: {
|
|
153
153
|
[route.output.contentType]: {
|
|
154
|
-
schema:
|
|
154
|
+
schema: coalesce(props)(result),
|
|
155
155
|
},
|
|
156
156
|
},
|
|
157
157
|
"x-nestia-encrypted": route.encrypted,
|
|
@@ -198,7 +198,7 @@ export namespace SwaggerSchemaGenerator {
|
|
|
198
198
|
);
|
|
199
199
|
|
|
200
200
|
// RETURNS WITH LAZY CONSTRUCTION
|
|
201
|
-
const schema: IJsonSchema =
|
|
201
|
+
const schema: IJsonSchema = coalesce(props)(result);
|
|
202
202
|
return {
|
|
203
203
|
description: encrypted
|
|
204
204
|
? `${warning.get(!!description).get("request")}${
|
|
@@ -218,49 +218,13 @@ export namespace SwaggerSchemaGenerator {
|
|
|
218
218
|
export const parameter =
|
|
219
219
|
(props: IProps) =>
|
|
220
220
|
(route: IRoute) =>
|
|
221
|
-
(param: IRoute.IParameter): ISwaggerRoute.IParameter =>
|
|
221
|
+
(param: IRoute.IParameter): ISwaggerRoute.IParameter[] =>
|
|
222
222
|
param.category === "headers"
|
|
223
223
|
? headers(props)(route)(param)
|
|
224
224
|
: param.category === "param"
|
|
225
|
-
? path(props)(route)(param)
|
|
225
|
+
? [path(props)(route)(param)]
|
|
226
226
|
: query(props)(route)(param);
|
|
227
227
|
|
|
228
|
-
const headers =
|
|
229
|
-
(props: IProps) =>
|
|
230
|
-
(route: IRoute) =>
|
|
231
|
-
(param: IRoute.IParameter): ISwaggerRoute.IParameter => {
|
|
232
|
-
// ANALYZE TYPE WITH VALIDATIONS
|
|
233
|
-
const result = (() => {
|
|
234
|
-
const result = MetadataFactory.analyze(props.checker)({
|
|
235
|
-
escape: false,
|
|
236
|
-
constant: true,
|
|
237
|
-
absorb: true,
|
|
238
|
-
})(props.collection)(param.type);
|
|
239
|
-
if (result.success === false)
|
|
240
|
-
props.errors.push(
|
|
241
|
-
...result.errors.map((e) => ({
|
|
242
|
-
...e,
|
|
243
|
-
route,
|
|
244
|
-
from: param.name,
|
|
245
|
-
})),
|
|
246
|
-
);
|
|
247
|
-
else if (result.data.objects.length === 1) {
|
|
248
|
-
// WHEN OBJECT CASE, VALIDATE IT MORE DETAILY
|
|
249
|
-
const again = MetadataFactory.analyze(props.checker)({
|
|
250
|
-
escape: false,
|
|
251
|
-
constant: true,
|
|
252
|
-
absorb: true,
|
|
253
|
-
validate: SwaggerSchemaValidator.headers,
|
|
254
|
-
})(new MetadataCollection())(param.type);
|
|
255
|
-
if (again.success === false) return again;
|
|
256
|
-
}
|
|
257
|
-
return result;
|
|
258
|
-
})();
|
|
259
|
-
|
|
260
|
-
// RETURNS WITH LAZY CONSTRUCTION
|
|
261
|
-
return lazyParameterReturns(props)(route)("header")(param, result);
|
|
262
|
-
};
|
|
263
|
-
|
|
264
228
|
const path =
|
|
265
229
|
(props: IProps) =>
|
|
266
230
|
(route: IRoute) =>
|
|
@@ -282,81 +246,114 @@ export namespace SwaggerSchemaGenerator {
|
|
|
282
246
|
);
|
|
283
247
|
|
|
284
248
|
// RETURNS WITH LAZY CONSTRUCTION
|
|
285
|
-
return
|
|
249
|
+
return lazy(props)(route)(param, result);
|
|
286
250
|
};
|
|
287
251
|
|
|
288
|
-
const
|
|
252
|
+
const headers =
|
|
289
253
|
(props: IProps) =>
|
|
290
254
|
(route: IRoute) =>
|
|
291
|
-
(param: IRoute.IParameter): ISwaggerRoute.IParameter =>
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const result = MetadataFactory.analyze(props.checker)({
|
|
255
|
+
(param: IRoute.IParameter): ISwaggerRoute.IParameter[] =>
|
|
256
|
+
decomposible(props)(route)(param)(
|
|
257
|
+
MetadataFactory.analyze(props.checker)({
|
|
295
258
|
escape: false,
|
|
296
259
|
constant: true,
|
|
297
260
|
absorb: true,
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
route,
|
|
304
|
-
from: param.name,
|
|
305
|
-
})),
|
|
306
|
-
);
|
|
307
|
-
} else if (result.data.objects.length === 1) {
|
|
308
|
-
// WHEN OBJECT CASE, VALIDATE IT MORE DETAILY
|
|
309
|
-
const again = MetadataFactory.analyze(props.checker)({
|
|
310
|
-
escape: false,
|
|
311
|
-
constant: true,
|
|
312
|
-
absorb: true,
|
|
313
|
-
validate: SwaggerSchemaValidator.query,
|
|
314
|
-
})(new MetadataCollection())(param.type);
|
|
315
|
-
if (again.success === false) return again;
|
|
316
|
-
}
|
|
317
|
-
return result;
|
|
318
|
-
})();
|
|
261
|
+
validate: param.custom
|
|
262
|
+
? SwaggerSchemaValidator.headers
|
|
263
|
+
: undefined,
|
|
264
|
+
})(new MetadataCollection())(param.type),
|
|
265
|
+
);
|
|
319
266
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
267
|
+
const query =
|
|
268
|
+
(props: IProps) =>
|
|
269
|
+
(route: IRoute) =>
|
|
270
|
+
(param: IRoute.IParameter): ISwaggerRoute.IParameter[] =>
|
|
271
|
+
decomposible(props)(route)(param)(
|
|
272
|
+
MetadataFactory.analyze(props.checker)({
|
|
273
|
+
escape: false,
|
|
274
|
+
constant: true,
|
|
275
|
+
absorb: true,
|
|
276
|
+
validate: param.custom
|
|
277
|
+
? SwaggerSchemaValidator.query
|
|
278
|
+
: undefined,
|
|
279
|
+
})(new MetadataCollection())(param.type),
|
|
280
|
+
);
|
|
323
281
|
|
|
324
|
-
const
|
|
282
|
+
const decomposible =
|
|
325
283
|
(props: IProps) =>
|
|
284
|
+
(route: IRoute) =>
|
|
285
|
+
(param: IRoute.IParameter) =>
|
|
326
286
|
(
|
|
327
287
|
result: ValidationPipe<Metadata, MetadataFactory.IError>,
|
|
328
|
-
):
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
288
|
+
): ISwaggerRoute.IParameter[] => {
|
|
289
|
+
if (result.success === false) {
|
|
290
|
+
props.errors.push(
|
|
291
|
+
...result.errors.map((e) => ({
|
|
292
|
+
...e,
|
|
293
|
+
route,
|
|
294
|
+
from: param.name,
|
|
295
|
+
})),
|
|
296
|
+
);
|
|
297
|
+
return [lazy(props)(route)(param, result)];
|
|
298
|
+
} else if (
|
|
299
|
+
props.config.decompose !== true ||
|
|
300
|
+
result.data.objects.length === 0
|
|
301
|
+
)
|
|
302
|
+
return [lazy(props)(route)(param, result)];
|
|
303
|
+
|
|
304
|
+
return result.data.objects[0].properties.map((p) => {
|
|
305
|
+
const schema = coalesce(props)({
|
|
306
|
+
success: true,
|
|
307
|
+
data: p.value,
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
name: p.key.constants[0].values[0] as string,
|
|
311
|
+
in:
|
|
312
|
+
param.category === "headers"
|
|
313
|
+
? "header"
|
|
314
|
+
: param.category,
|
|
315
|
+
schema,
|
|
316
|
+
description: p.description ?? undefined,
|
|
317
|
+
required: p.value.isRequired(),
|
|
318
|
+
};
|
|
333
319
|
});
|
|
334
|
-
return schema;
|
|
335
320
|
};
|
|
336
321
|
|
|
337
|
-
const
|
|
322
|
+
const lazy =
|
|
338
323
|
(props: IProps) =>
|
|
339
324
|
(route: IRoute) =>
|
|
340
|
-
(inKeyword: string) =>
|
|
341
325
|
(
|
|
342
326
|
param: IRoute.IParameter,
|
|
343
327
|
result: ValidationPipe<Metadata, MetadataFactory.IError>,
|
|
344
|
-
) => {
|
|
345
|
-
const schema: IJsonSchema =
|
|
328
|
+
): ISwaggerRoute.IParameter => {
|
|
329
|
+
const schema: IJsonSchema = coalesce(props)(result);
|
|
346
330
|
return {
|
|
347
331
|
name: param.field ?? param.name,
|
|
348
|
-
in:
|
|
332
|
+
in: param.category === "headers" ? "header" : param.category,
|
|
349
333
|
schema,
|
|
350
334
|
description: describe(route, "param", param.name) ?? "",
|
|
351
335
|
required: result.success ? result.data.isRequired() : true,
|
|
352
336
|
};
|
|
353
337
|
};
|
|
354
338
|
|
|
355
|
-
|
|
339
|
+
const coalesce =
|
|
340
|
+
(props: IProps) =>
|
|
341
|
+
(
|
|
342
|
+
result: ValidationPipe<Metadata, MetadataFactory.IError>,
|
|
343
|
+
): IJsonSchema => {
|
|
344
|
+
const schema: IJsonSchema = {} as any;
|
|
345
|
+
props.tuples.push({
|
|
346
|
+
metadata: result.success ? result.data : any.get(),
|
|
347
|
+
schema,
|
|
348
|
+
});
|
|
349
|
+
return schema;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const describe = (
|
|
356
353
|
route: IRoute,
|
|
357
354
|
tagName: string,
|
|
358
355
|
parameterName?: string,
|
|
359
|
-
): string | undefined {
|
|
356
|
+
): string | undefined => {
|
|
360
357
|
const parametric: (elem: ts.JSDocTagInfo) => boolean = parameterName
|
|
361
358
|
? (tag) =>
|
|
362
359
|
tag.text!.find(
|
|
@@ -366,13 +363,13 @@ export namespace SwaggerSchemaGenerator {
|
|
|
366
363
|
) !== undefined
|
|
367
364
|
: () => true;
|
|
368
365
|
|
|
369
|
-
const tag: ts.JSDocTagInfo | undefined = route.
|
|
366
|
+
const tag: ts.JSDocTagInfo | undefined = route.jsDocTags.find(
|
|
370
367
|
(tag) => tag.name === tagName && tag.text && parametric(tag),
|
|
371
368
|
);
|
|
372
369
|
return tag && tag.text
|
|
373
370
|
? tag.text.find((elem) => elem.kind === "text")?.text
|
|
374
371
|
: undefined;
|
|
375
|
-
}
|
|
372
|
+
};
|
|
376
373
|
}
|
|
377
374
|
|
|
378
375
|
const warning = new Singleton((described: boolean) => {
|
|
@@ -130,12 +130,6 @@ export namespace SwaggerSchemaValidator {
|
|
|
130
130
|
// PROPERTY MUST BE SOLE
|
|
131
131
|
if (typeof explore.property === "object")
|
|
132
132
|
insert("dynamic property is not allowed.");
|
|
133
|
-
// MUST BE LOWER-CASE
|
|
134
|
-
if (
|
|
135
|
-
typeof explore.property === "string" &&
|
|
136
|
-
explore.property !== explore.property.toLowerCase()
|
|
137
|
-
)
|
|
138
|
-
insert("property name must be lower-case.");
|
|
139
133
|
// DO NOT ALLOW TUPLE TYPE
|
|
140
134
|
if (meta.tuples.length) insert("tuple type is not allowed.");
|
|
141
135
|
// DO NOT ALLOW UNION TYPE
|
|
@@ -6,6 +6,7 @@ export interface IController {
|
|
|
6
6
|
paths: string[];
|
|
7
7
|
functions: IController.IFunction[];
|
|
8
8
|
security: Record<string, string[]>[];
|
|
9
|
+
swaggerTgas: string[];
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export namespace IController {
|
|
@@ -23,6 +24,7 @@ export namespace IController {
|
|
|
23
24
|
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
24
25
|
IController.IException
|
|
25
26
|
>;
|
|
27
|
+
swaggerTags: string[];
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
export type IParameter =
|
package/src/structures/IRoute.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
4
|
+
|
|
3
5
|
import { IController } from "./IController";
|
|
4
6
|
|
|
5
7
|
export interface IRoute {
|
|
@@ -18,16 +20,17 @@ export interface IRoute {
|
|
|
18
20
|
symbol: {
|
|
19
21
|
class: string;
|
|
20
22
|
function: string;
|
|
21
|
-
}
|
|
23
|
+
};
|
|
22
24
|
description?: string;
|
|
23
25
|
operationId?: string;
|
|
24
|
-
|
|
26
|
+
jsDocTags: ts.JSDocTagInfo[];
|
|
25
27
|
setHeaders: Array<
|
|
26
28
|
| { type: "setter"; source: string; target?: string }
|
|
27
29
|
| { type: "assigner"; source: string }
|
|
28
30
|
>;
|
|
29
31
|
security: Record<string, string[]>[];
|
|
30
32
|
exceptions: Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput>;
|
|
33
|
+
swaggerTags: string[];
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
export namespace IRoute {
|
|
@@ -35,10 +38,12 @@ export namespace IRoute {
|
|
|
35
38
|
optional: boolean;
|
|
36
39
|
type: ts.Type;
|
|
37
40
|
typeName: string;
|
|
41
|
+
metadata?: Metadata;
|
|
38
42
|
};
|
|
39
43
|
export interface IOutput {
|
|
40
44
|
type: ts.Type;
|
|
41
45
|
typeName: string;
|
|
46
|
+
metadata?: Metadata;
|
|
42
47
|
description?: string;
|
|
43
48
|
contentType: "application/json" | "text/plain";
|
|
44
49
|
}
|