@nestia/sdk 2.0.0-dev.20230831-5 → 2.0.0-dev.20230901-2

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 (60) hide show
  1. package/assets/bundle/api/utils/NestiaSimulator.ts +1 -22
  2. package/lib/NestiaSdkApplication.js +1 -1
  3. package/lib/NestiaSdkApplication.js.map +1 -1
  4. package/lib/analyses/ControllerAnalyzer.js +11 -5
  5. package/lib/analyses/ControllerAnalyzer.js.map +1 -1
  6. package/lib/analyses/ExceptionAnalyzer.js +7 -2
  7. package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
  8. package/lib/analyses/ImportAnalyzer.js +1 -1
  9. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  10. package/lib/analyses/ReflectAnalyzer.js +0 -10
  11. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  12. package/lib/executable/internal/NestiaSdkConfig.js +37 -46
  13. package/lib/executable/internal/NestiaSdkConfig.js.map +1 -1
  14. package/lib/generates/SwaggerGenerator.d.ts +10 -0
  15. package/lib/generates/SwaggerGenerator.js +37 -497
  16. package/lib/generates/SwaggerGenerator.js.map +1 -1
  17. package/lib/generates/internal/E2eFileProgrammer.js +5 -44
  18. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  19. package/lib/generates/internal/SdkFunctionProgrammer.js +13 -11
  20. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  21. package/lib/generates/internal/SdkSimulationProgrammer.js +4 -4
  22. package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
  23. package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +19 -0
  24. package/lib/generates/internal/SwaggerSchemaGenerator.js +301 -0
  25. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -0
  26. package/lib/generates/internal/SwaggerSchemaValidator.d.ts +7 -0
  27. package/lib/generates/internal/SwaggerSchemaValidator.js +196 -0
  28. package/lib/generates/internal/SwaggerSchemaValidator.js.map +1 -0
  29. package/lib/structures/IController.d.ts +0 -4
  30. package/lib/structures/IRoute.d.ts +6 -3
  31. package/lib/structures/ISwaggerError.d.ts +6 -0
  32. package/lib/structures/ISwaggerError.js +3 -0
  33. package/lib/structures/ISwaggerError.js.map +1 -0
  34. package/lib/structures/ISwaggerRoute.d.ts +2 -1
  35. package/lib/structures/ISwaggerSchemaTuple.d.ts +6 -0
  36. package/lib/structures/ISwaggerSchemaTuple.js +3 -0
  37. package/lib/structures/ISwaggerSchemaTuple.js.map +1 -0
  38. package/lib/structures/ITypeTuple.d.ts +1 -1
  39. package/lib/utils/ImportDictionary.d.ts +1 -2
  40. package/lib/utils/ImportDictionary.js +28 -24
  41. package/lib/utils/ImportDictionary.js.map +1 -1
  42. package/package.json +5 -5
  43. package/src/NestiaSdkApplication.ts +1 -1
  44. package/src/analyses/ControllerAnalyzer.ts +13 -4
  45. package/src/analyses/ExceptionAnalyzer.ts +3 -2
  46. package/src/analyses/ImportAnalyzer.ts +1 -1
  47. package/src/analyses/ReflectAnalyzer.ts +0 -10
  48. package/src/generates/SwaggerGenerator.ts +102 -478
  49. package/src/generates/internal/E2eFileProgrammer.ts +7 -49
  50. package/src/generates/internal/SdkFunctionProgrammer.ts +14 -12
  51. package/src/generates/internal/SdkSimulationProgrammer.ts +5 -5
  52. package/src/generates/internal/SwaggerSchemaGenerator.ts +433 -0
  53. package/src/generates/internal/SwaggerSchemaValidator.ts +216 -0
  54. package/src/structures/IController.ts +0 -4
  55. package/src/structures/IRoute.ts +6 -3
  56. package/src/structures/ISwaggerError.ts +8 -0
  57. package/src/structures/ISwaggerRoute.ts +2 -1
  58. package/src/structures/ISwaggerSchemaTuple.ts +7 -0
  59. package/src/structures/ITypeTuple.ts +1 -1
  60. package/src/utils/ImportDictionary.ts +29 -26
@@ -1,24 +1,34 @@
1
1
  import fs from "fs";
2
2
  import NodePath from "path";
3
+ import path from "path";
3
4
  import { Singleton } from "tstl/thread/Singleton";
4
5
  import ts from "typescript";
5
6
 
6
- import typia, { IJsonApplication, IJsonComponents, IJsonSchema } from "typia";
7
+ import typia, { IJsonApplication } from "typia";
7
8
  import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
8
- import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
9
- import { Metadata } from "typia/lib/metadata/Metadata";
10
- import { ApplicationProgrammer } from "typia/lib/programmers/ApplicationProgrammer";
9
+ import { JsonApplicationProgrammer } from "typia/lib/programmers/json/JsonApplicationProgrammer";
11
10
 
12
11
  import { INestiaConfig } from "../INestiaConfig";
13
12
  import { IRoute } from "../structures/IRoute";
14
13
  import { ISwagger } from "../structures/ISwagger";
14
+ import { ISwaggerError } from "../structures/ISwaggerError";
15
15
  import { ISwaggerInfo } from "../structures/ISwaggerInfo";
16
16
  import { ISwaggerRoute } from "../structures/ISwaggerRoute";
17
+ import { ISwaggerSchemaTuple } from "../structures/ISwaggerSchemaTuple";
17
18
  import { ISwaggerSecurityScheme } from "../structures/ISwaggerSecurityScheme";
18
19
  import { FileRetriever } from "../utils/FileRetriever";
19
20
  import { MapUtil } from "../utils/MapUtil";
21
+ import { SwaggerSchemaGenerator } from "./internal/SwaggerSchemaGenerator";
20
22
 
21
23
  export namespace SwaggerGenerator {
24
+ export interface IProps {
25
+ config: INestiaConfig.ISwaggerConfig;
26
+ checker: ts.TypeChecker;
27
+ collection: MetadataCollection;
28
+ tuples: Array<ISwaggerSchemaTuple>;
29
+ errors: ISwaggerError[];
30
+ }
31
+
22
32
  export const generate =
23
33
  (checker: ts.TypeChecker) =>
24
34
  (config: INestiaConfig.ISwaggerConfig) =>
@@ -52,7 +62,8 @@ export namespace SwaggerGenerator {
52
62
  });
53
63
 
54
64
  // CONSTRUCT SWAGGER DOCUMENTS
55
- const tupleList: Array<ISchemaTuple> = [];
65
+ const errors: ISwaggerError[] = [];
66
+ const tuples: Array<ISwaggerSchemaTuple> = [];
56
67
  const swagger: ISwagger = await initialize(config);
57
68
  const pathDict: Map<
58
69
  string,
@@ -67,13 +78,13 @@ export namespace SwaggerGenerator {
67
78
  get_path(route.path, route.parameters),
68
79
  () => ({}),
69
80
  );
70
- path[route.method.toLowerCase()] = generate_route(
81
+ path[route.method.toLowerCase()] = generate_route({
71
82
  config,
72
83
  checker,
73
84
  collection,
74
- tupleList,
75
- route,
76
- );
85
+ tuples,
86
+ errors,
87
+ })(route);
77
88
  }
78
89
  swagger.paths = {};
79
90
  for (const [path, routes] of pathDict) {
@@ -81,20 +92,36 @@ export namespace SwaggerGenerator {
81
92
  }
82
93
 
83
94
  // FILL JSON-SCHEMAS
84
- const application: IJsonApplication = ApplicationProgrammer.write({
85
- purpose: "swagger",
86
- })(tupleList.map(({ metadata }) => metadata));
95
+ const application: IJsonApplication =
96
+ JsonApplicationProgrammer.write({
97
+ purpose: "swagger",
98
+ })(tuples.map(({ metadata }) => metadata));
87
99
  swagger.components = {
88
100
  ...(swagger.components ?? {}),
89
101
  ...(application.components ?? {}),
90
102
  };
91
- tupleList.forEach(({ schema }, index) => {
103
+ tuples.forEach(({ schema }, index) => {
92
104
  Object.assign(schema, application.schemas[index]!);
93
105
  });
94
106
 
95
107
  // CONFIGURE SECURITY
96
108
  if (config.security) fill_security(config.security, swagger);
97
109
 
110
+ // REPORT ERRORS
111
+ if (errors.length) {
112
+ for (const e of errors)
113
+ console.error(
114
+ `${path.relative(location, process.cwd())}:${
115
+ e.route.symbol
116
+ }:${
117
+ e.from
118
+ } - error TS(@nestia/sdk): invalid type detected.\n\n` +
119
+ e.messages.map((m) => ` - ${m}`).join("\n"),
120
+ "\n\n",
121
+ );
122
+ throw new TypeError("Invalid type detected");
123
+ }
124
+
98
125
  // DO GENERATE
99
126
  await fs.promises.writeFile(
100
127
  location,
@@ -191,7 +218,7 @@ export namespace SwaggerGenerator {
191
218
  location,
192
219
  "utf8",
193
220
  );
194
- const data = typia.assertParse<{
221
+ const data = typia.json.assertParse<{
195
222
  name?: string;
196
223
  version?: string;
197
224
  description?: string;
@@ -264,93 +291,74 @@ export namespace SwaggerGenerator {
264
291
  return path;
265
292
  }
266
293
 
267
- function generate_route(
268
- config: INestiaConfig.ISwaggerConfig,
269
- checker: ts.TypeChecker,
270
- collection: MetadataCollection,
271
- tupleList: Array<ISchemaTuple>,
272
- route: IRoute,
273
- ): ISwaggerRoute {
274
- const bodyParam = route.parameters.find(
275
- (param) => param.category === "body",
276
- );
277
-
278
- const getTagTexts = (name: string) =>
279
- route.tags
280
- .filter(
281
- (tag) =>
282
- tag.name === name &&
283
- tag.text &&
284
- tag.text.find(
285
- (elem) => elem.kind === "text" && elem.text.length,
286
- ) !== undefined,
287
- )
288
- .map(
289
- (tag) =>
290
- tag.text!.find((elem) => elem.kind === "text")!.text,
291
- );
294
+ const generate_route =
295
+ (props: IProps) =>
296
+ (route: IRoute): ISwaggerRoute => {
297
+ const body = route.parameters.find(
298
+ (param) => param.category === "body",
299
+ );
300
+ const getTagTexts = (name: string) =>
301
+ route.tags
302
+ .filter(
303
+ (tag) =>
304
+ tag.name === name &&
305
+ tag.text &&
306
+ tag.text.find(
307
+ (elem) =>
308
+ elem.kind === "text" && elem.text.length,
309
+ ) !== undefined,
310
+ )
311
+ .map(
312
+ (tag) =>
313
+ tag.text!.find((elem) => elem.kind === "text")!
314
+ .text,
315
+ );
292
316
 
293
- const description: string | undefined = route.description?.length
294
- ? route.description
295
- : undefined;
296
- const summary: string | undefined = (() => {
297
- if (description === undefined) return undefined;
317
+ const description: string | undefined = route.description?.length
318
+ ? route.description
319
+ : undefined;
320
+ const summary: string | undefined = (() => {
321
+ if (description === undefined) return undefined;
298
322
 
299
- const [explicit] = getTagTexts("summary");
300
- if (explicit?.length) return explicit;
323
+ const [explicit] = getTagTexts("summary");
324
+ if (explicit?.length) return explicit;
301
325
 
302
- const index: number = description.indexOf(".");
303
- if (index <= 0) return undefined;
326
+ const index: number = description.indexOf(".");
327
+ if (index <= 0) return undefined;
304
328
 
305
- const content: string = description.substring(0, index).trim();
306
- return content.length ? content : undefined;
307
- })();
308
- const deprecated = route.tags.find((tag) => tag.name === "deprecated");
329
+ const content: string = description.substring(0, index).trim();
330
+ return content.length ? content : undefined;
331
+ })();
332
+ const deprecated = route.tags.find(
333
+ (tag) => tag.name === "deprecated",
334
+ );
309
335
 
310
- return {
311
- deprecated: deprecated ? true : undefined,
312
- tags: getTagTexts("tag"),
313
- parameters: route.parameters
314
- .filter((param) => param.category !== "body")
315
- .map((param) =>
316
- generate_parameter(
317
- config,
318
- checker,
319
- collection,
320
- tupleList,
321
- route,
322
- param,
336
+ return {
337
+ deprecated: deprecated ? true : undefined,
338
+ tags: getTagTexts("tag"),
339
+ operationId: route.operationId,
340
+ parameters: route.parameters
341
+ .filter((param) => param.category !== "body")
342
+ .map((param) =>
343
+ SwaggerSchemaGenerator.parameter(props)(route)(param),
323
344
  ),
324
- )
325
- .flat(),
326
- requestBody: bodyParam
327
- ? generate_request_body(
328
- checker,
329
- collection,
330
- tupleList,
331
- route,
332
- bodyParam,
333
- )
334
- : undefined,
335
- responses: generate_response_body(
336
- checker,
337
- collection,
338
- tupleList,
339
- route,
340
- ),
341
- summary,
342
- description,
343
- security: route.security.length ? route.security : undefined,
344
- "x-nestia-namespace": [
345
- ...route.path
346
- .split("/")
347
- .filter((str) => str.length && str[0] !== ":"),
348
- route.name,
349
- ].join("."),
350
- "x-nestia-jsDocTags": route.tags,
351
- "x-nestia-method": route.method,
345
+ requestBody: body
346
+ ? SwaggerSchemaGenerator.body(props)(route)(body)
347
+ : undefined,
348
+ responses: SwaggerSchemaGenerator.response(props)(route),
349
+ summary,
350
+ description,
351
+ security: route.security.length ? route.security : undefined,
352
+ "x-nestia-namespace": [
353
+ ...route.path
354
+ .split("/")
355
+ .filter((str) => str.length && str[0] !== ":"),
356
+ route.name,
357
+ ].join("."),
358
+ "x-nestia-jsDocTags": route.tags,
359
+ "x-nestia-method": route.method,
360
+ };
352
361
  };
353
- }
354
362
 
355
363
  function fill_security(
356
364
  security: Required<INestiaConfig.ISwaggerConfig>["security"],
@@ -372,388 +380,4 @@ export namespace SwaggerGenerator {
372
380
  };
373
381
  return input;
374
382
  }
375
-
376
- /* ---------------------------------------------------------
377
- REQUEST & RESPONSE
378
- --------------------------------------------------------- */
379
- function generate_parameter(
380
- config: INestiaConfig.ISwaggerConfig,
381
- checker: ts.TypeChecker,
382
- collection: MetadataCollection,
383
- tupleList: Array<ISchemaTuple>,
384
- route: IRoute,
385
- parameter: IRoute.IParameter,
386
- ): ISwaggerRoute.IParameter[] {
387
- const schema: IJsonSchema | null = generate_schema(
388
- checker,
389
- collection,
390
- tupleList,
391
- parameter.type.type,
392
- );
393
- if (schema === null)
394
- throw new Error(
395
- `Error on NestiaApplication.swagger(): invalid parameter type on ${route.symbol}#${parameter.name}`,
396
- );
397
- else if (
398
- parameter.custom &&
399
- parameter.category === "param" &&
400
- !!parameter.meta &&
401
- (parameter.meta.type === "date" ||
402
- parameter.meta.type === "uuid") &&
403
- schema !== null
404
- ) {
405
- const string: IJsonSchema.IString = schema as IJsonSchema.IString;
406
- string.format = parameter.meta.type;
407
- } else if (
408
- config.decompose === true &&
409
- parameter.category === "query"
410
- ) {
411
- const metadata: Metadata = MetadataFactory.analyze(checker)({
412
- resolve: true,
413
- constant: true,
414
- absorb: true,
415
- validate: (meta) => {
416
- if (meta.atomics.find((str) => str === "bigint"))
417
- throw new Error(NO_BIGIT);
418
- },
419
- })(collection)(parameter.type.type);
420
- if (
421
- metadata.size() === 1 &&
422
- metadata.objects.length === 1 &&
423
- metadata.objects[0].properties.every(
424
- (prop) =>
425
- prop.key.size() &&
426
- prop.key.constants.length === 1 &&
427
- prop.key.constants[0].type === "string" &&
428
- route.parameters.every(
429
- (param) =>
430
- param.name !== prop.key.constants[0].values[0],
431
- ),
432
- )
433
- ) {
434
- const app: IJsonApplication = ApplicationProgrammer.write({
435
- purpose: "swagger",
436
- })([metadata]);
437
- const top = Object.values(app.components.schemas ?? {})[0];
438
-
439
- if (typia.is<IJsonComponents.IObject>(top))
440
- return Object.entries(top.properties).map(
441
- ([key, value]) => ({
442
- name: key,
443
- in: "query",
444
- schema: value,
445
- required: top.required?.includes(key) ?? false,
446
- description: value.description,
447
- }),
448
- );
449
- }
450
- } else if (
451
- config.decompose === true &&
452
- parameter.category === "headers"
453
- ) {
454
- const metadata: Metadata = MetadataFactory.analyze(checker)({
455
- resolve: true,
456
- constant: true,
457
- absorb: true,
458
- validate: (meta) => {
459
- if (meta.atomics.find((str) => str === "bigint"))
460
- throw new Error(NO_BIGIT);
461
- },
462
- })(collection)(parameter.type.type);
463
- if (
464
- metadata.size() === 1 &&
465
- metadata.objects.length === 1 &&
466
- metadata.objects[0].properties.every(
467
- (prop) =>
468
- prop.key.size() &&
469
- prop.key.constants.length === 1 &&
470
- prop.key.constants[0].type === "string" &&
471
- route.parameters.every(
472
- (param) =>
473
- param.name !== prop.key.constants[0].values[0],
474
- ),
475
- )
476
- ) {
477
- const app: IJsonApplication = ApplicationProgrammer.write({
478
- purpose: "swagger",
479
- })([metadata]);
480
- const top = Object.values(app.components.schemas ?? {})[0];
481
-
482
- if (typia.is<IJsonComponents.IObject>(top))
483
- return Object.entries(top.properties).map(
484
- ([key, value]) => ({
485
- name: key,
486
- in: "header",
487
- schema: value,
488
- required: top.required?.includes(key) ?? false,
489
- description: value.description,
490
- }),
491
- );
492
- }
493
- }
494
-
495
- return [
496
- {
497
- name: parameter.field ?? parameter.name,
498
- in:
499
- parameter.category === "param"
500
- ? "path"
501
- : parameter.category === "headers"
502
- ? "header"
503
- : parameter.category,
504
- description:
505
- get_parametric_description(
506
- route,
507
- "param",
508
- parameter.name,
509
- ) || "",
510
- schema,
511
- required: required(parameter.type.type),
512
- },
513
- ];
514
- }
515
-
516
- function generate_request_body(
517
- checker: ts.TypeChecker,
518
- collection: MetadataCollection,
519
- tupleList: Array<ISchemaTuple>,
520
- route: IRoute,
521
- parameter: IRoute.IParameter,
522
- ): ISwaggerRoute.IRequestBody {
523
- const schema: IJsonSchema | null = generate_schema(
524
- checker,
525
- collection,
526
- tupleList,
527
- parameter.type.type,
528
- );
529
- if (schema === null)
530
- throw new Error(
531
- `Error on NestiaApplication.sdk(): invalid request body type on ${route.symbol}.`,
532
- );
533
- else if (parameter.category !== "body")
534
- throw new Error("Unreachable code.");
535
-
536
- const contentType = parameter.custom
537
- ? parameter.contentType
538
- : "application/json";
539
- const description = get_parametric_description(
540
- route,
541
- "param",
542
- parameter.name,
543
- );
544
-
545
- return {
546
- description:
547
- parameter.custom && parameter.encrypted
548
- ? `${warning.get(!!description).get("request")}${
549
- description ?? ""
550
- }`
551
- : description,
552
- content: {
553
- [contentType]: {
554
- schema,
555
- },
556
- },
557
- required: true,
558
- "x-nestia-encrypted": parameter.custom && parameter.encrypted,
559
- };
560
- }
561
-
562
- function generate_response_body(
563
- checker: ts.TypeChecker,
564
- collection: MetadataCollection,
565
- tupleList: Array<ISchemaTuple>,
566
- route: IRoute,
567
- ): ISwaggerRoute.IResponseBody {
568
- const output: ISwaggerRoute.IResponseBody = {};
569
-
570
- //----
571
- // EXCEPTION STATUSES
572
- //----
573
- // FROM DECORATOR
574
- for (const [status, exp] of Object.entries(route.exceptions)) {
575
- const schema = generate_schema(
576
- checker,
577
- collection,
578
- tupleList,
579
- exp.type,
580
- );
581
- if (schema !== null)
582
- output[status] = {
583
- description: exp.description ?? "",
584
- content: {
585
- "application/json": { schema },
586
- },
587
- };
588
- }
589
-
590
- // FROM COMMENT TAGS
591
- for (const tag of route.tags) {
592
- if (tag.name !== "throw" && tag.name !== "throws") continue;
593
-
594
- const text: string | undefined = tag.text?.find(
595
- (elem) => elem.kind === "text",
596
- )?.text;
597
- if (text === undefined) continue;
598
-
599
- const elements: string[] = text.split(" ").map((str) => str.trim());
600
- const status: string = elements[0];
601
- if (
602
- isNaN(Number(status)) &&
603
- status !== "2XX" &&
604
- status !== "3XX" &&
605
- status !== "4XX" &&
606
- status !== "5XX"
607
- )
608
- continue;
609
-
610
- const description: string | undefined =
611
- elements.length === 1 ? undefined : elements.slice(1).join(" ");
612
- const oldbie = output[status];
613
- if (description && oldbie !== undefined)
614
- oldbie.description = description;
615
- else if (oldbie === undefined)
616
- output[status] = {
617
- description: description ?? "",
618
- content: {
619
- "application/json": {
620
- schema: {},
621
- },
622
- },
623
- };
624
- }
625
-
626
- //----
627
- // SUCCESS
628
- //----
629
- // STATUS & SCHEMA
630
- const status: string =
631
- route.status !== undefined
632
- ? String(route.status)
633
- : route.method === "GET" ||
634
- route.method === "HEAD" ||
635
- route.method === "DELETE"
636
- ? "200"
637
- : "201";
638
- const schema: IJsonSchema | null = generate_schema(
639
- checker,
640
- collection,
641
- tupleList,
642
- route.output.type,
643
- );
644
-
645
- // DO ASSIGN
646
- const description =
647
- get_parametric_description(route, "return") ??
648
- get_parametric_description(route, "returns");
649
- output[status] = {
650
- description: route.encrypted
651
- ? `${warning.get(!!description).get("response", route.method)}${
652
- description ?? ""
653
- }`
654
- : description ?? "",
655
- content:
656
- schema === null || route.output.name === "void"
657
- ? undefined
658
- : {
659
- [route.output.contentType]: {
660
- schema,
661
- },
662
- },
663
- "x-nestia-encrypted": route.encrypted,
664
- };
665
- return output;
666
- }
667
-
668
- /* ---------------------------------------------------------
669
- UTILS
670
- --------------------------------------------------------- */
671
- function generate_schema(
672
- checker: ts.TypeChecker,
673
- collection: MetadataCollection,
674
- tupleList: Array<ISchemaTuple>,
675
- type: ts.Type,
676
- ): IJsonSchema | null {
677
- const metadata: Metadata = MetadataFactory.analyze(checker)({
678
- resolve: true,
679
- constant: true,
680
- absorb: false,
681
- validate: (meta) => {
682
- if (meta.atomics.find((str) => str === "bigint"))
683
- throw new Error(NO_BIGIT);
684
- },
685
- })(collection)(type);
686
- if (metadata.empty() && metadata.nullable === false) return null;
687
-
688
- const schema: IJsonSchema = {} as IJsonSchema;
689
- tupleList.push({ metadata, schema });
690
- return schema;
691
- }
692
-
693
- function get_parametric_description(
694
- route: IRoute,
695
- tagName: string,
696
- parameterName?: string,
697
- ): string | undefined {
698
- const parametric: (elem: ts.JSDocTagInfo) => boolean = parameterName
699
- ? (tag) =>
700
- tag.text!.find(
701
- (elem) =>
702
- elem.kind === "parameterName" &&
703
- elem.text === parameterName,
704
- ) !== undefined
705
- : () => true;
706
-
707
- const tag: ts.JSDocTagInfo | undefined = route.tags.find(
708
- (tag) => tag.name === tagName && tag.text && parametric(tag),
709
- );
710
- return tag && tag.text
711
- ? tag.text.find((elem) => elem.kind === "text")?.text
712
- : undefined;
713
- }
714
383
  }
715
-
716
- const required = (type: ts.Type): boolean => {
717
- if (type.isUnion()) return type.types.every((type) => required(type));
718
- const obstacle = (other: ts.TypeFlags) => (type.getFlags() & other) === 0;
719
- return (
720
- obstacle(ts.TypeFlags.Undefined) &&
721
- obstacle(ts.TypeFlags.Never) &&
722
- obstacle(ts.TypeFlags.Void) &&
723
- obstacle(ts.TypeFlags.VoidLike)
724
- );
725
- };
726
-
727
- const warning = new Singleton((described: boolean) => {
728
- return new Singleton((type: "request" | "response", method?: string) => {
729
- const summary =
730
- type === "request"
731
- ? "Request body must be encrypted."
732
- : "Response data have been encrypted.";
733
- const component =
734
- type === "request"
735
- ? "[EncryptedBody](https://github.com/samchon/@nestia/core#encryptedbody)"
736
- : `[EncryptedRoute.${method![0].toUpperCase()}.${method!
737
- .substring(1)
738
- .toLowerCase()}](https://github.com/samchon/@nestia/core#encryptedroute)`;
739
-
740
- const content: string[] = [
741
- "## Warning",
742
- "",
743
- summary,
744
- "",
745
- `The ${type} body data would be encrypted as "AES-128(256) / CBC mode / PKCS#5 Padding / Base64 Encoding", through the ${component} component.`,
746
- "",
747
- `Therefore, just utilize this swagger editor only for referencing. If you need to call the real API, using [SDK](https://github.com/samchon/nestia#software-development-kit) would be much better.`,
748
- ];
749
- if (described === true) content.push("----------------", "");
750
- return content.join("\n");
751
- });
752
- });
753
-
754
- interface ISchemaTuple {
755
- metadata: Metadata;
756
- schema: IJsonSchema;
757
- }
758
-
759
- const NO_BIGIT = "Error on typia.application(): does not allow bigint type.";