@nestia/sdk 3.0.0-dev.20231209 → 3.0.0-dev.20240412

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 (168) hide show
  1. package/README.md +12 -9
  2. package/assets/config/nestia.config.ts +82 -79
  3. package/lib/INestiaConfig.d.ts +28 -6
  4. package/lib/NestiaSdkApplication.js +12 -10
  5. package/lib/NestiaSdkApplication.js.map +1 -1
  6. package/lib/analyses/ConfigAnalyzer.js +1 -1
  7. package/lib/analyses/ConfigAnalyzer.js.map +1 -1
  8. package/lib/analyses/ControllerAnalyzer.js +30 -15
  9. package/lib/analyses/ControllerAnalyzer.js.map +1 -1
  10. package/lib/analyses/ExceptionAnalyzer.js +35 -6
  11. package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
  12. package/lib/analyses/ImportAnalyzer.d.ts +1 -2
  13. package/lib/analyses/ImportAnalyzer.js +2 -2
  14. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  15. package/lib/analyses/PathAnalyzer.d.ts +2 -4
  16. package/lib/analyses/PathAnalyzer.js +27 -11
  17. package/lib/analyses/PathAnalyzer.js.map +1 -1
  18. package/lib/analyses/ReflectAnalyzer.js +34 -22
  19. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  20. package/lib/analyses/SecurityAnalyzer.js +13 -8
  21. package/lib/analyses/SecurityAnalyzer.js.map +1 -1
  22. package/lib/executable/internal/NestiaConfigLoader.js +300 -220
  23. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  24. package/lib/executable/sdk.js +11 -11
  25. package/lib/generates/CloneGenerator.d.ts +6 -0
  26. package/lib/generates/CloneGenerator.js +62 -0
  27. package/lib/generates/CloneGenerator.js.map +1 -0
  28. package/lib/generates/E2eGenerator.d.ts +2 -1
  29. package/lib/generates/E2eGenerator.js +2 -2
  30. package/lib/generates/E2eGenerator.js.map +1 -1
  31. package/lib/generates/SdkGenerator.js +3 -11
  32. package/lib/generates/SdkGenerator.js.map +1 -1
  33. package/lib/generates/SwaggerGenerator.d.ts +2 -0
  34. package/lib/generates/SwaggerGenerator.js +119 -62
  35. package/lib/generates/SwaggerGenerator.js.map +1 -1
  36. package/lib/generates/internal/E2eFileProgrammer.d.ts +2 -1
  37. package/lib/generates/internal/E2eFileProgrammer.js +49 -53
  38. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  39. package/lib/generates/internal/FilePrinter.d.ts +10 -0
  40. package/lib/generates/internal/FilePrinter.js +46 -0
  41. package/lib/generates/internal/FilePrinter.js.map +1 -0
  42. package/lib/{utils → generates/internal}/ImportDictionary.d.ts +2 -1
  43. package/lib/{utils → generates/internal}/ImportDictionary.js +20 -14
  44. package/lib/generates/internal/ImportDictionary.js.map +1 -0
  45. package/lib/generates/internal/SdkAliasCollection.d.ts +12 -0
  46. package/lib/generates/internal/SdkAliasCollection.js +97 -0
  47. package/lib/generates/internal/SdkAliasCollection.js.map +1 -0
  48. package/lib/generates/internal/SdkCloneProgrammer.d.ts +12 -0
  49. package/lib/generates/internal/SdkCloneProgrammer.js +99 -0
  50. package/lib/generates/internal/SdkCloneProgrammer.js.map +1 -0
  51. package/lib/generates/internal/SdkFileProgrammer.d.ts +2 -1
  52. package/lib/generates/internal/SdkFileProgrammer.js +27 -28
  53. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  54. package/lib/generates/internal/SdkFunctionProgrammer.d.ts +7 -2
  55. package/lib/generates/internal/SdkFunctionProgrammer.js +115 -322
  56. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  57. package/lib/generates/internal/SdkImportWizard.d.ts +1 -1
  58. package/lib/generates/internal/SdkNamespaceProgrammer.d.ts +11 -0
  59. package/lib/generates/internal/SdkNamespaceProgrammer.js +180 -0
  60. package/lib/generates/internal/SdkNamespaceProgrammer.js.map +1 -0
  61. package/lib/generates/internal/SdkRouteProgrammer.d.ts +7 -0
  62. package/lib/generates/internal/SdkRouteProgrammer.js +55 -0
  63. package/lib/generates/internal/SdkRouteProgrammer.js.map +1 -0
  64. package/lib/generates/internal/SdkSimulationProgrammer.d.ts +8 -2
  65. package/lib/generates/internal/SdkSimulationProgrammer.js +103 -89
  66. package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
  67. package/lib/generates/internal/SdkTypeProgrammer.d.ts +9 -0
  68. package/lib/generates/internal/SdkTypeProgrammer.js +228 -0
  69. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -0
  70. package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +4 -4
  71. package/lib/generates/internal/SwaggerSchemaGenerator.js +30 -28
  72. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  73. package/lib/structures/IController.d.ts +4 -2
  74. package/lib/structures/IRoute.d.ts +5 -4
  75. package/lib/structures/ISwaggerLazyProperty.d.ts +2 -2
  76. package/lib/structures/ISwaggerLazySchema.d.ts +2 -2
  77. package/lib/structures/ParamCategory.d.ts +1 -1
  78. package/lib/structures/TypeEntry.js +2 -2
  79. package/lib/structures/TypeEntry.js.map +1 -1
  80. package/lib/utils/StringUtil.d.ts +3 -0
  81. package/lib/utils/StringUtil.js +8 -0
  82. package/lib/utils/StringUtil.js.map +1 -0
  83. package/package.json +12 -16
  84. package/src/INestiaConfig.ts +30 -6
  85. package/src/NestiaSdkApplication.ts +255 -253
  86. package/src/analyses/AccessorAnalyzer.ts +60 -60
  87. package/src/analyses/ConfigAnalyzer.ts +147 -147
  88. package/src/analyses/ControllerAnalyzer.ts +42 -19
  89. package/src/analyses/ExceptionAnalyzer.ts +148 -115
  90. package/src/analyses/GenericAnalyzer.ts +51 -51
  91. package/src/analyses/ImportAnalyzer.ts +1 -2
  92. package/src/analyses/PathAnalyzer.ts +110 -98
  93. package/src/analyses/ReflectAnalyzer.ts +39 -35
  94. package/src/analyses/SecurityAnalyzer.ts +24 -20
  95. package/src/executable/internal/CommandParser.ts +15 -15
  96. package/src/executable/internal/NestiaConfigLoader.ts +67 -67
  97. package/src/executable/internal/NestiaSdkCommand.ts +60 -60
  98. package/src/executable/sdk.ts +73 -73
  99. package/src/generates/CloneGenerator.ts +62 -0
  100. package/src/generates/E2eGenerator.ts +66 -64
  101. package/src/generates/SdkGenerator.ts +84 -96
  102. package/src/generates/SwaggerGenerator.ts +145 -53
  103. package/src/generates/internal/E2eFileProgrammer.ts +182 -123
  104. package/src/generates/internal/FilePrinter.ts +53 -0
  105. package/src/{utils → generates/internal}/ImportDictionary.ts +35 -13
  106. package/src/generates/internal/SdkAliasCollection.ts +152 -0
  107. package/src/generates/internal/SdkCloneProgrammer.ts +155 -0
  108. package/src/generates/internal/SdkDistributionComposer.ts +91 -91
  109. package/src/generates/internal/SdkFileProgrammer.ts +115 -106
  110. package/src/generates/internal/SdkFunctionProgrammer.ts +298 -518
  111. package/src/generates/internal/SdkImportWizard.ts +55 -55
  112. package/src/generates/internal/SdkNamespaceProgrammer.ts +510 -0
  113. package/src/generates/internal/SdkRouteDirectory.ts +17 -17
  114. package/src/generates/internal/SdkRouteProgrammer.ts +83 -0
  115. package/src/generates/internal/SdkSimulationProgrammer.ts +365 -133
  116. package/src/generates/internal/SdkTypeProgrammer.ts +386 -0
  117. package/src/generates/internal/SwaggerSchemaGenerator.ts +437 -427
  118. package/src/generates/internal/SwaggerSchemaValidator.ts +198 -198
  119. package/src/index.ts +4 -4
  120. package/src/module.ts +2 -2
  121. package/src/structures/IController.ts +94 -95
  122. package/src/structures/IErrorReport.ts +6 -6
  123. package/src/structures/INestiaProject.ts +13 -13
  124. package/src/structures/INormalizedInput.ts +20 -20
  125. package/src/structures/IRoute.ts +53 -53
  126. package/src/structures/ISwaggerLazyProperty.ts +2 -2
  127. package/src/structures/ISwaggerLazySchema.ts +2 -2
  128. package/src/structures/ITypeTuple.ts +6 -6
  129. package/src/structures/MethodType.ts +5 -5
  130. package/src/structures/ParamCategory.ts +1 -1
  131. package/src/structures/TypeEntry.ts +1 -1
  132. package/src/utils/ArrayUtil.ts +26 -26
  133. package/src/utils/FileRetriever.ts +22 -22
  134. package/src/utils/MapUtil.ts +14 -14
  135. package/src/utils/PathUtil.ts +10 -10
  136. package/src/utils/SourceFinder.ts +66 -66
  137. package/src/utils/StringUtil.ts +6 -0
  138. package/src/utils/StripEnums.ts +5 -5
  139. package/assets/bundle/api/utils/NestiaSimulator.ts +0 -70
  140. package/lib/generates/internal/SdkDtoGenerator.d.ts +0 -9
  141. package/lib/generates/internal/SdkDtoGenerator.js +0 -294
  142. package/lib/generates/internal/SdkDtoGenerator.js.map +0 -1
  143. package/lib/generates/internal/SdkTypeDefiner.d.ts +0 -11
  144. package/lib/generates/internal/SdkTypeDefiner.js +0 -82
  145. package/lib/generates/internal/SdkTypeDefiner.js.map +0 -1
  146. package/lib/structures/ISwagger.d.ts +0 -72
  147. package/lib/structures/ISwagger.js +0 -3
  148. package/lib/structures/ISwagger.js.map +0 -1
  149. package/lib/structures/ISwaggerComponents.d.ts +0 -26
  150. package/lib/structures/ISwaggerComponents.js +0 -3
  151. package/lib/structures/ISwaggerComponents.js.map +0 -1
  152. package/lib/structures/ISwaggerInfo.d.ts +0 -71
  153. package/lib/structures/ISwaggerInfo.js +0 -3
  154. package/lib/structures/ISwaggerInfo.js.map +0 -1
  155. package/lib/structures/ISwaggerRoute.d.ts +0 -47
  156. package/lib/structures/ISwaggerRoute.js +0 -3
  157. package/lib/structures/ISwaggerRoute.js.map +0 -1
  158. package/lib/structures/ISwaggerSecurityScheme.d.ts +0 -56
  159. package/lib/structures/ISwaggerSecurityScheme.js +0 -3
  160. package/lib/structures/ISwaggerSecurityScheme.js.map +0 -1
  161. package/lib/utils/ImportDictionary.js.map +0 -1
  162. package/src/generates/internal/SdkDtoGenerator.ts +0 -424
  163. package/src/generates/internal/SdkTypeDefiner.ts +0 -119
  164. package/src/structures/ISwagger.ts +0 -91
  165. package/src/structures/ISwaggerComponents.ts +0 -29
  166. package/src/structures/ISwaggerInfo.ts +0 -80
  167. package/src/structures/ISwaggerRoute.ts +0 -51
  168. package/src/structures/ISwaggerSecurityScheme.ts +0 -65
@@ -0,0 +1,53 @@
1
+ import fs from "fs";
2
+ import { format } from "prettier";
3
+ import ts from "typescript";
4
+
5
+ export namespace FilePrinter {
6
+ export const description = <Node extends ts.Node>(
7
+ node: Node,
8
+ comment: string,
9
+ ): Node => {
10
+ if (comment.length === 0) return node;
11
+ ts.addSyntheticLeadingComment(
12
+ node,
13
+ ts.SyntaxKind.MultiLineCommentTrivia,
14
+ ["*", ...comment.split("\n").map((str) => ` * ${str}`), ""].join("\n"),
15
+ true,
16
+ );
17
+ return node;
18
+ };
19
+
20
+ export const enter = () =>
21
+ ts.factory.createExpressionStatement(ts.factory.createIdentifier("\n"));
22
+
23
+ export const write = async (props: {
24
+ location: string;
25
+ statements: ts.Statement[];
26
+ top?: string;
27
+ }): Promise<void> => {
28
+ const script: string = ts
29
+ .createPrinter()
30
+ .printFile(
31
+ ts.factory.createSourceFile(
32
+ props.statements,
33
+ ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
34
+ ts.NodeFlags.None,
35
+ ),
36
+ );
37
+ await fs.promises.writeFile(
38
+ props.location,
39
+ await beautify((props.top ?? "") + script),
40
+ "utf8",
41
+ );
42
+ };
43
+
44
+ const beautify = async (script: string): Promise<string> => {
45
+ try {
46
+ return await format(script, {
47
+ parser: "typescript",
48
+ });
49
+ } catch {
50
+ return script;
51
+ }
52
+ };
53
+ }
@@ -1,7 +1,8 @@
1
1
  import path from "path";
2
- import { HashMap } from "tstl/container/HashMap";
3
- import { HashSet } from "tstl/container/HashSet";
4
- import { Pair } from "tstl/utility/Pair";
2
+ import { HashMap, HashSet, Pair } from "tstl";
3
+ import ts from "typescript";
4
+
5
+ import { FilePrinter } from "./FilePrinter";
5
6
 
6
7
  export class ImportDictionary {
7
8
  private readonly components_: HashMap<Pair<string, boolean>, IComposition> =
@@ -52,9 +53,9 @@ export class ImportDictionary {
52
53
  return props.instance ?? file;
53
54
  }
54
55
 
55
- public toScript(outDir: string): string {
56
- const external: string[] = [];
57
- const internal: string[] = [];
56
+ public toStatements(outDir: string): ts.Statement[] {
57
+ const external: ts.ImportDeclaration[] = [];
58
+ const internal: ts.ImportDeclaration[] = [];
58
59
 
59
60
  const locator = (str: string) => {
60
61
  const location: string = path.relative(outDir, str).split("\\").join("/");
@@ -66,7 +67,8 @@ export class ImportDictionary {
66
67
  : location.substring(index + NODE_MODULES.length);
67
68
  };
68
69
  const enroll =
69
- (filter: (str: string) => boolean) => (container: string[]) => {
70
+ (filter: (str: string) => boolean) =>
71
+ (container: ts.ImportDeclaration[]) => {
70
72
  const compositions: IComposition[] = this.components_
71
73
  .toJSON()
72
74
  .filter((c) => filter(c.second.location))
@@ -86,18 +88,38 @@ export class ImportDictionary {
86
88
  .join(", ")} }`,
87
89
  );
88
90
  container.push(
89
- `import ${c.type ? "type " : ""}${brackets.join(", ")} from "${
90
- c.location
91
- }";`,
91
+ ts.factory.createImportDeclaration(
92
+ undefined,
93
+ ts.factory.createImportClause(
94
+ c.type,
95
+ c.default
96
+ ? ts.factory.createIdentifier(c.name ?? c.location)
97
+ : undefined,
98
+ c.elements.empty() === false
99
+ ? ts.factory.createNamedImports(
100
+ [...c.elements].map((elem) =>
101
+ ts.factory.createImportSpecifier(
102
+ false,
103
+ undefined,
104
+ ts.factory.createIdentifier(elem),
105
+ ),
106
+ ),
107
+ )
108
+ : undefined,
109
+ ),
110
+ ts.factory.createStringLiteral(c.location),
111
+ ),
92
112
  );
93
113
  }
94
114
  };
95
115
 
96
116
  enroll((str) => str.indexOf(NODE_MODULES) !== -1)(external);
97
117
  enroll((str) => str.indexOf(NODE_MODULES) === -1)(internal);
98
-
99
- if (external.length && internal.length) external.push("");
100
- return [...external, ...internal].join("\n");
118
+ return [
119
+ ...external,
120
+ ...(external.length && internal.length ? [FilePrinter.enter()] : []),
121
+ ...internal,
122
+ ];
101
123
  }
102
124
  }
103
125
  export namespace ImportDictionary {
@@ -0,0 +1,152 @@
1
+ import ts from "typescript";
2
+ import typia from "typia";
3
+
4
+ import { INestiaConfig } from "../../INestiaConfig";
5
+ import { IController } from "../../structures/IController";
6
+ import { IRoute } from "../../structures/IRoute";
7
+ import { ImportDictionary } from "./ImportDictionary";
8
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
9
+
10
+ export namespace SdkAliasCollection {
11
+ export const name =
12
+ (config: INestiaConfig) =>
13
+ (importer: ImportDictionary) =>
14
+ (p: IRoute.IParameter | IRoute.IOutput): ts.TypeNode =>
15
+ p.metadata
16
+ ? SdkTypeProgrammer.write(config)(importer)(p.metadata)
17
+ : ts.factory.createTypeReferenceNode(p.typeName);
18
+
19
+ export const headers =
20
+ (config: INestiaConfig) =>
21
+ (importer: ImportDictionary) =>
22
+ (param: IRoute.IParameter): ts.TypeNode => {
23
+ const type: ts.TypeNode = name(config)(importer)(param);
24
+ if (config.primitive === false) return type;
25
+ return ts.factory.createTypeReferenceNode(
26
+ importer.external({
27
+ type: true,
28
+ library: "@nestia/fetcher",
29
+ instance: "Resolved",
30
+ }),
31
+ [type],
32
+ );
33
+ };
34
+
35
+ export const query =
36
+ (config: INestiaConfig) =>
37
+ (importer: ImportDictionary) =>
38
+ (param: IRoute.IParameter): ts.TypeNode => {
39
+ const type: ts.TypeNode = name(config)(importer)(param);
40
+ if (config.primitive === false) return type;
41
+ return ts.factory.createTypeReferenceNode(
42
+ importer.external({
43
+ type: true,
44
+ library: "@nestia/fetcher",
45
+ instance: "Resolved",
46
+ }),
47
+ [type],
48
+ );
49
+ };
50
+
51
+ export const input =
52
+ (config: INestiaConfig) =>
53
+ (importer: ImportDictionary) =>
54
+ (param: IRoute.IParameter): ts.TypeNode => {
55
+ const type: ts.TypeNode = name(config)(importer)(param);
56
+ if (config.clone === true || config.primitive === false) return type;
57
+ return ts.factory.createTypeReferenceNode(
58
+ importer.external({
59
+ type: true,
60
+ library: "@nestia/fetcher",
61
+ instance:
62
+ typia.is<IController.IBodyParameter>(param) &&
63
+ param.contentType === "multipart/form-data"
64
+ ? "Resolved"
65
+ : "Primitive",
66
+ }),
67
+ [type],
68
+ );
69
+ };
70
+
71
+ export const output =
72
+ (checker: ts.TypeChecker) =>
73
+ (config: INestiaConfig) =>
74
+ (importer: ImportDictionary) =>
75
+ (route: IRoute): ts.TypeNode => {
76
+ if (config.propagate !== true) {
77
+ const node: ts.TypeNode = name(config)(importer)(route.output);
78
+ const type = checker.getTypeAtLocation(node);
79
+ const filter = (flag: ts.TypeFlags) => (type.getFlags() & flag) !== 0;
80
+
81
+ if (
82
+ config.clone === true ||
83
+ config.primitive === false ||
84
+ filter(ts.TypeFlags.Undefined) ||
85
+ filter(ts.TypeFlags.Never) ||
86
+ filter(ts.TypeFlags.Void) ||
87
+ filter(ts.TypeFlags.VoidLike)
88
+ )
89
+ return node;
90
+ return ts.factory.createTypeReferenceNode(
91
+ importer.external({
92
+ type: true,
93
+ library: "@nestia/fetcher",
94
+ instance:
95
+ route.output.contentType === "application/x-www-form-urlencoded"
96
+ ? "Resolved"
97
+ : "Primitive",
98
+ }),
99
+ [node],
100
+ );
101
+ }
102
+
103
+ const branches: IBranch[] = [
104
+ {
105
+ status: String(route.status ?? (route.method === "POST" ? 201 : 200)),
106
+ type: name(config)(importer)(route.output),
107
+ },
108
+ ...Object.entries(route.exceptions).map(([status, value]) => ({
109
+ status,
110
+ type: name(config)(importer)(value),
111
+ })),
112
+ ];
113
+ return ts.factory.createTypeReferenceNode(
114
+ importer.external({
115
+ type: true,
116
+ library: "@nestia/fetcher",
117
+ instance: "IPropagation",
118
+ }),
119
+ [
120
+ ts.factory.createTypeLiteralNode(
121
+ branches.map((b) =>
122
+ ts.factory.createPropertySignature(
123
+ undefined,
124
+ ts.factory.createNumericLiteral(b.status),
125
+ undefined,
126
+ b.type,
127
+ ),
128
+ ),
129
+ ),
130
+ ...(route.status
131
+ ? [
132
+ ts.factory.createLiteralTypeNode(
133
+ ts.factory.createNumericLiteral(route.status),
134
+ ),
135
+ ]
136
+ : []),
137
+ ],
138
+ );
139
+ };
140
+
141
+ export const responseBody =
142
+ (checker: ts.TypeChecker) =>
143
+ (config: INestiaConfig) =>
144
+ (importer: ImportDictionary) =>
145
+ (route: IRoute): ts.TypeNode =>
146
+ output(checker)({ ...config, propagate: false })(importer)(route);
147
+ }
148
+
149
+ interface IBranch {
150
+ status: string;
151
+ type: ts.TypeNode;
152
+ }
@@ -0,0 +1,155 @@
1
+ import { IPointer } from "tstl";
2
+ import ts from "typescript";
3
+ import { IJsDocTagInfo } from "typia";
4
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
5
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
6
+ import { MetadataAlias } from "typia/lib/schemas/metadata/MetadataAlias";
7
+ import { MetadataAtomic } from "typia/lib/schemas/metadata/MetadataAtomic";
8
+ import { MetadataObject } from "typia/lib/schemas/metadata/MetadataObject";
9
+
10
+ import { INestiaConfig } from "../../INestiaConfig";
11
+ import { IRoute } from "../../structures/IRoute";
12
+ import { MapUtil } from "../../utils/MapUtil";
13
+ import { FilePrinter } from "./FilePrinter";
14
+ import { ImportDictionary } from "./ImportDictionary";
15
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
16
+
17
+ export namespace SdkCloneProgrammer {
18
+ export interface IModule {
19
+ name: string;
20
+ children: Map<string, IModule>;
21
+ programmer:
22
+ | null
23
+ | ((importer: ImportDictionary) => ts.TypeAliasDeclaration);
24
+ }
25
+
26
+ export const write =
27
+ (checker: ts.TypeChecker) =>
28
+ (config: INestiaConfig) =>
29
+ (routes: IRoute[]): Map<string, IModule> => {
30
+ const collection = new MetadataCollection({
31
+ replace: MetadataCollection.replace,
32
+ });
33
+ for (const r of routes) {
34
+ for (const p of r.parameters) {
35
+ const res = MetadataFactory.analyze(checker)({
36
+ escape: false,
37
+ constant: true,
38
+ absorb: false,
39
+ })(collection)(p.type);
40
+ if (res.success) p.metadata = res.data;
41
+ }
42
+ for (const e of Object.values(r.exceptions)) {
43
+ const res = MetadataFactory.analyze(checker)({
44
+ escape: true,
45
+ constant: true,
46
+ absorb: false,
47
+ })(collection)(e.type);
48
+ if (res.success) e.metadata = res.data;
49
+ }
50
+ const res = MetadataFactory.analyze(checker)({
51
+ escape: true,
52
+ constant: true,
53
+ absorb: false,
54
+ })(collection)(r.output.type);
55
+ if (res.success) r.output.metadata = res.data;
56
+ }
57
+
58
+ const dict: Map<string, IModule> = new Map();
59
+ for (const alias of collection.aliases())
60
+ if (isNamedDeclaration(alias.name))
61
+ prepare(dict)(alias.name)((importer) =>
62
+ write_alias(config)(importer)(alias),
63
+ );
64
+ for (const object of collection.objects())
65
+ if (isNamedDeclaration(object.name))
66
+ prepare(dict)(object.name)((importer) =>
67
+ write_object(config)(importer)(object),
68
+ );
69
+ return dict;
70
+ };
71
+
72
+ const prepare =
73
+ (dict: Map<string, IModule>) =>
74
+ (name: string) =>
75
+ (programmer: (importer: ImportDictionary) => ts.TypeAliasDeclaration) => {
76
+ const accessors: string[] = name.split(".");
77
+ const modulo: IPointer<IModule> = { value: null! };
78
+
79
+ accessors.forEach((acc, i) => {
80
+ modulo.value = MapUtil.take(dict, acc, () => ({
81
+ name: acc,
82
+ children: new Map(),
83
+ programmer: null,
84
+ }));
85
+ if (i === accessors.length - 1) modulo.value.programmer = programmer;
86
+ dict = modulo.value.children;
87
+ });
88
+ return modulo!;
89
+ };
90
+
91
+ const write_alias =
92
+ (config: INestiaConfig) =>
93
+ (importer: ImportDictionary) =>
94
+ (alias: MetadataAlias): ts.TypeAliasDeclaration =>
95
+ FilePrinter.description(
96
+ ts.factory.createTypeAliasDeclaration(
97
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
98
+ alias.name.split(".").at(-1)!,
99
+ [],
100
+ SdkTypeProgrammer.write(config)(importer)(alias.value),
101
+ ),
102
+ writeComment([])(alias.description, alias.jsDocTags),
103
+ );
104
+
105
+ const write_object =
106
+ (config: INestiaConfig) =>
107
+ (importer: ImportDictionary) =>
108
+ (object: MetadataObject): ts.TypeAliasDeclaration => {
109
+ return FilePrinter.description(
110
+ ts.factory.createTypeAliasDeclaration(
111
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
112
+ object.name.split(".").at(-1)!,
113
+ [],
114
+ SdkTypeProgrammer.write_object(config)(importer)(object),
115
+ ),
116
+ writeComment([])(object.description ?? null, object.jsDocTags),
117
+ );
118
+ };
119
+ }
120
+
121
+ const isNamedDeclaration = (name: string) =>
122
+ name !== "object" &&
123
+ name !== "__type" &&
124
+ !name.startsWith("__type.") &&
125
+ name !== "__object" &&
126
+ !name.startsWith("__object.");
127
+
128
+ const writeComment =
129
+ (atomics: MetadataAtomic[]) =>
130
+ (description: string | null, jsDocTags: IJsDocTagInfo[]): string => {
131
+ const lines: string[] = [];
132
+ if (description?.length)
133
+ lines.push(...description.split("\n").map((s) => `${s}`));
134
+
135
+ const filtered: IJsDocTagInfo[] =
136
+ !!atomics.length && !!jsDocTags?.length
137
+ ? jsDocTags.filter(
138
+ (tag) =>
139
+ !atomics.some((a) =>
140
+ a.tags.some((r) => r.some((t) => t.kind === tag.name)),
141
+ ),
142
+ )
143
+ : jsDocTags ?? [];
144
+
145
+ if (description?.length && filtered.length) lines.push("");
146
+ if (filtered.length)
147
+ lines.push(
148
+ ...filtered.map((t) =>
149
+ t.text?.length
150
+ ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
151
+ : `@${t.name}`,
152
+ ),
153
+ );
154
+ return lines.join("\n");
155
+ };
@@ -1,91 +1,91 @@
1
- import cp from "child_process";
2
- import fs from "fs";
3
- import path from "path";
4
-
5
- import { INestiaConfig } from "../../INestiaConfig";
6
-
7
- export namespace SdkDistributionComposer {
8
- export const compose = async (config: INestiaConfig) => {
9
- if (!fs.existsSync(config.distribute!))
10
- await fs.promises.mkdir(config.distribute!);
11
-
12
- const root: string = process.cwd();
13
- const output: string = path.resolve(config.output!);
14
- process.chdir(config.distribute!);
15
-
16
- const exit = () => process.chdir(root);
17
- if (await configured()) return exit();
18
-
19
- // COPY FILES
20
- console.log("Composing SDK distribution environments...");
21
- for (const file of await fs.promises.readdir(BUNDLE))
22
- await fs.promises.copyFile(`${BUNDLE}/${file}`, file);
23
-
24
- // CONFIGURE PATHS
25
- for (const file of ["package.json", "tsconfig.json"])
26
- await replace({ root, output })(file);
27
-
28
- // INSTALL PACKAGES
29
- const versions: IDependencies = await dependencies();
30
- execute("npm install --save-dev rimraf");
31
- execute(
32
- `npm install --save @nestia/fetcher@${versions["@nestia/fetcher"]}`,
33
- );
34
- execute(`npm install --save typia@${versions["typia"]}`);
35
- execute("npx typia setup --manager npm");
36
-
37
- exit();
38
- };
39
-
40
- const configured = async (): Promise<boolean> =>
41
- ["package.json", "tsconfig.json"].every(fs.existsSync) &&
42
- (await (async () => {
43
- const content = JSON.parse(
44
- await fs.promises.readFile("package.json", "utf8"),
45
- );
46
- return !!content.dependencies?.["@nestia/fetcher"];
47
- })());
48
-
49
- const execute = (command: string) => {
50
- console.log(` - ${command}`);
51
- cp.execSync(command, { stdio: "ignore" });
52
- };
53
-
54
- const replace =
55
- (props: { root: string; output: string }) =>
56
- async (file: string): Promise<void> => {
57
- const relative = (from: string) => (to: string) =>
58
- path.relative(from, to).split("\\").join("/");
59
- const root: string = relative(process.cwd())(props.root);
60
- const output: string = relative(process.cwd())(props.output);
61
- const current: string = relative(props.root)(process.cwd());
62
-
63
- const content: string = await fs.promises.readFile(file, "utf8");
64
- await fs.promises.writeFile(
65
- file,
66
- content
67
- .split("${root}")
68
- .join(root)
69
- .split("${output}")
70
- .join(output)
71
- .split("${current}")
72
- .join(current),
73
- "utf8",
74
- );
75
- };
76
-
77
- const dependencies = async () => {
78
- const content: string = await fs.promises.readFile(
79
- __dirname + "/../../../package.json",
80
- "utf8",
81
- );
82
- const json: { dependencies: IDependencies } = JSON.parse(content);
83
- return json.dependencies;
84
- };
85
- }
86
-
87
- interface IDependencies {
88
- "@nestia/fetcher": string;
89
- typia: string;
90
- }
91
- const BUNDLE = __dirname + "/../../../assets/bundle/distribute";
1
+ import cp from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ import { INestiaConfig } from "../../INestiaConfig";
6
+
7
+ export namespace SdkDistributionComposer {
8
+ export const compose = async (config: INestiaConfig) => {
9
+ if (!fs.existsSync(config.distribute!))
10
+ await fs.promises.mkdir(config.distribute!);
11
+
12
+ const root: string = process.cwd();
13
+ const output: string = path.resolve(config.output!);
14
+ process.chdir(config.distribute!);
15
+
16
+ const exit = () => process.chdir(root);
17
+ if (await configured()) return exit();
18
+
19
+ // COPY FILES
20
+ console.log("Composing SDK distribution environments...");
21
+ for (const file of await fs.promises.readdir(BUNDLE))
22
+ await fs.promises.copyFile(`${BUNDLE}/${file}`, file);
23
+
24
+ // CONFIGURE PATHS
25
+ for (const file of ["package.json", "tsconfig.json"])
26
+ await replace({ root, output })(file);
27
+
28
+ // INSTALL PACKAGES
29
+ const versions: IDependencies = await dependencies();
30
+ execute("npm install --save-dev rimraf");
31
+ execute(
32
+ `npm install --save @nestia/fetcher@${versions["@nestia/fetcher"]}`,
33
+ );
34
+ execute(`npm install --save typia@${versions["typia"]}`);
35
+ execute("npx typia setup --manager npm");
36
+
37
+ exit();
38
+ };
39
+
40
+ const configured = async (): Promise<boolean> =>
41
+ ["package.json", "tsconfig.json"].every(fs.existsSync) &&
42
+ (await (async () => {
43
+ const content = JSON.parse(
44
+ await fs.promises.readFile("package.json", "utf8"),
45
+ );
46
+ return !!content.dependencies?.["@nestia/fetcher"];
47
+ })());
48
+
49
+ const execute = (command: string) => {
50
+ console.log(` - ${command}`);
51
+ cp.execSync(command, { stdio: "ignore" });
52
+ };
53
+
54
+ const replace =
55
+ (props: { root: string; output: string }) =>
56
+ async (file: string): Promise<void> => {
57
+ const relative = (from: string) => (to: string) =>
58
+ path.relative(from, to).split("\\").join("/");
59
+ const root: string = relative(process.cwd())(props.root);
60
+ const output: string = relative(process.cwd())(props.output);
61
+ const current: string = relative(props.root)(process.cwd());
62
+
63
+ const content: string = await fs.promises.readFile(file, "utf8");
64
+ await fs.promises.writeFile(
65
+ file,
66
+ content
67
+ .split("${root}")
68
+ .join(root)
69
+ .split("${output}")
70
+ .join(output)
71
+ .split("${current}")
72
+ .join(current),
73
+ "utf8",
74
+ );
75
+ };
76
+
77
+ const dependencies = async () => {
78
+ const content: string = await fs.promises.readFile(
79
+ __dirname + "/../../../package.json",
80
+ "utf8",
81
+ );
82
+ const json: { dependencies: IDependencies } = JSON.parse(content);
83
+ return json.dependencies;
84
+ };
85
+ }
86
+
87
+ interface IDependencies {
88
+ "@nestia/fetcher": string;
89
+ typia: string;
90
+ }
91
+ const BUNDLE = __dirname + "/../../../assets/bundle/distribute";