@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.
Files changed (49) hide show
  1. package/lib/INestiaConfig.d.ts +40 -32
  2. package/lib/NestiaSdkApplication.d.ts +1 -1
  3. package/lib/NestiaSdkApplication.js +5 -5
  4. package/lib/NestiaSdkApplication.js.map +1 -1
  5. package/lib/analyses/ControllerAnalyzer.js +4 -4
  6. package/lib/analyses/ControllerAnalyzer.js.map +1 -1
  7. package/lib/analyses/ReflectAnalyzer.js +9 -1
  8. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  9. package/lib/executable/internal/NestiaConfigLoader.js +17 -13
  10. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  11. package/lib/generates/SdkGenerator.d.ts +2 -1
  12. package/lib/generates/SdkGenerator.js +5 -1
  13. package/lib/generates/SdkGenerator.js.map +1 -1
  14. package/lib/generates/SwaggerGenerator.js +12 -8
  15. package/lib/generates/SwaggerGenerator.js.map +1 -1
  16. package/lib/generates/internal/E2eFileProgrammer.js +15 -10
  17. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  18. package/lib/generates/internal/SdkDtoGenerator.d.ts +9 -0
  19. package/lib/generates/internal/SdkDtoGenerator.js +264 -0
  20. package/lib/generates/internal/SdkDtoGenerator.js.map +1 -0
  21. package/lib/generates/internal/SdkFileProgrammer.js +8 -7
  22. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  23. package/lib/generates/internal/SdkFunctionProgrammer.js +11 -7
  24. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  25. package/lib/generates/internal/SdkSimulationProgrammer.js +5 -1
  26. package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
  27. package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +1 -1
  28. package/lib/generates/internal/SwaggerSchemaGenerator.js +59 -71
  29. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  30. package/lib/generates/internal/SwaggerSchemaValidator.js +0 -4
  31. package/lib/generates/internal/SwaggerSchemaValidator.js.map +1 -1
  32. package/lib/structures/IController.d.ts +2 -0
  33. package/lib/structures/IRoute.d.ts +5 -1
  34. package/package.json +5 -5
  35. package/src/INestiaConfig.ts +43 -34
  36. package/src/NestiaSdkApplication.ts +5 -9
  37. package/src/analyses/ControllerAnalyzer.ts +5 -5
  38. package/src/analyses/ReflectAnalyzer.ts +8 -0
  39. package/src/generates/SdkGenerator.ts +7 -0
  40. package/src/generates/SwaggerGenerator.ts +16 -11
  41. package/src/generates/internal/E2eFileProgrammer.ts +24 -11
  42. package/src/generates/internal/SdkDtoGenerator.ts +384 -0
  43. package/src/generates/internal/SdkFileProgrammer.ts +8 -7
  44. package/src/generates/internal/SdkFunctionProgrammer.ts +35 -7
  45. package/src/generates/internal/SdkSimulationProgrammer.ts +10 -1
  46. package/src/generates/internal/SwaggerSchemaGenerator.ts +85 -88
  47. package/src/generates/internal/SwaggerSchemaValidator.ts +0 -6
  48. package/src/structures/IController.ts +2 -0
  49. 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: coalesceSchema(props)(result),
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.tags) {
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: coalesceSchema(props)(result),
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 = coalesceSchema(props)(result);
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 lazyParameterReturns(props)(route)("path")(param, result);
249
+ return lazy(props)(route)(param, result);
286
250
  };
287
251
 
288
- const query =
252
+ const headers =
289
253
  (props: IProps) =>
290
254
  (route: IRoute) =>
291
- (param: IRoute.IParameter): ISwaggerRoute.IParameter => {
292
- // ANALYZE TYPE WITH VALIDATIONS
293
- const result = (() => {
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
- })(props.collection)(param.type);
299
- if (result.success === false) {
300
- props.errors.push(
301
- ...result.errors.map((e) => ({
302
- ...e,
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
- // RETURNS WITH LAZY CONSTRUCTION
321
- return lazyParameterReturns(props)(route)("query")(param, result);
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 coalesceSchema =
282
+ const decomposible =
325
283
  (props: IProps) =>
284
+ (route: IRoute) =>
285
+ (param: IRoute.IParameter) =>
326
286
  (
327
287
  result: ValidationPipe<Metadata, MetadataFactory.IError>,
328
- ): IJsonSchema => {
329
- const schema: IJsonSchema = {} as any;
330
- props.tuples.push({
331
- metadata: result.success ? result.data : any.get(),
332
- schema,
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 lazyParameterReturns =
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 = coalesceSchema(props)(result);
328
+ ): ISwaggerRoute.IParameter => {
329
+ const schema: IJsonSchema = coalesce(props)(result);
346
330
  return {
347
331
  name: param.field ?? param.name,
348
- in: inKeyword,
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
- function describe(
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.tags.find(
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 =
@@ -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
- tags: ts.JSDocTagInfo[];
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
  }