@nestia/sdk 10.0.2 → 11.0.0-dev.20260312

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 (151) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/assets/bundle/api/HttpError.ts +1 -1
  4. package/assets/bundle/api/IConnection.ts +1 -1
  5. package/assets/bundle/api/Primitive.ts +1 -1
  6. package/assets/bundle/api/Resolved.ts +1 -1
  7. package/assets/bundle/api/index.ts +4 -4
  8. package/assets/bundle/api/module.ts +6 -6
  9. package/assets/bundle/distribute/README.md +37 -37
  10. package/assets/bundle/distribute/package.json +28 -28
  11. package/assets/bundle/distribute/tsconfig.json +109 -109
  12. package/assets/bundle/e2e/index.ts +42 -42
  13. package/assets/config/nestia.config.ts +97 -97
  14. package/lib/INestiaConfig.d.ts +3 -3
  15. package/lib/NestiaSdkApplication.js.map +1 -1
  16. package/lib/NestiaSwaggerComposer.d.ts +3 -2
  17. package/lib/NestiaSwaggerComposer.js +5 -6
  18. package/lib/NestiaSwaggerComposer.js.map +1 -1
  19. package/lib/analyses/AccessorAnalyzer.js +2 -2
  20. package/lib/analyses/AccessorAnalyzer.js.map +1 -1
  21. package/lib/analyses/DtoAnalyzer.js.map +1 -1
  22. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  23. package/lib/analyses/ReflectHttpOperationAnalyzer.js +3 -3
  24. package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
  25. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js +4 -2
  26. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js.map +1 -1
  27. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js +7 -11
  28. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js.map +1 -1
  29. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js +6 -6
  30. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js.map +1 -1
  31. package/lib/analyses/TypedHttpRouteAnalyzer.d.ts +1 -1
  32. package/lib/analyses/TypedHttpRouteAnalyzer.js +6 -8
  33. package/lib/analyses/TypedHttpRouteAnalyzer.js.map +1 -1
  34. package/lib/executable/internal/NestiaConfigLoader.js +111 -52
  35. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  36. package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
  37. package/lib/executable/sdk.js +0 -0
  38. package/lib/generates/SwaggerGenerator.d.ts +1 -1
  39. package/lib/generates/SwaggerGenerator.js +11 -12
  40. package/lib/generates/SwaggerGenerator.js.map +1 -1
  41. package/lib/generates/internal/E2eFileProgrammer.js +8 -9
  42. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  43. package/lib/generates/internal/SdkAliasCollection.d.ts +2 -2
  44. package/lib/generates/internal/SdkAliasCollection.js +2 -2
  45. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  46. package/lib/generates/internal/SdkDistributionComposer.js +1 -1
  47. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
  48. package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -1
  49. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +11 -12
  50. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  51. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +13 -16
  52. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  53. package/lib/generates/internal/SdkHttpRouteProgrammer.js +4 -4
  54. package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -1
  55. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +12 -16
  56. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  57. package/lib/generates/internal/SdkImportWizard.js +2 -2
  58. package/lib/generates/internal/SdkImportWizard.js.map +1 -1
  59. package/lib/generates/internal/SdkTypeProgrammer.d.ts +2 -3
  60. package/lib/generates/internal/SdkTypeProgrammer.js +6 -7
  61. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
  62. package/lib/generates/internal/SdkTypeTagProgrammer.d.ts +1 -1
  63. package/lib/generates/internal/SdkTypeTagProgrammer.js +11 -11
  64. package/lib/generates/internal/SdkTypeTagProgrammer.js.map +1 -1
  65. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +6 -8
  66. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
  67. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +2 -2
  68. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  69. package/lib/generates/internal/SwaggerOperationComposer.d.ts +3 -3
  70. package/lib/generates/internal/SwaggerOperationComposer.js.map +1 -1
  71. package/lib/generates/internal/SwaggerOperationParameterComposer.d.ts +1 -1
  72. package/lib/generates/internal/SwaggerOperationParameterComposer.js +10 -8
  73. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  74. package/lib/generates/internal/SwaggerOperationResponseComposer.d.ts +3 -3
  75. package/lib/generates/internal/SwaggerOperationResponseComposer.js.map +1 -1
  76. package/lib/module.d.ts +1 -0
  77. package/lib/module.js +1 -0
  78. package/lib/module.js.map +1 -1
  79. package/lib/structures/IReflectHttpOperationException.d.ts +3 -4
  80. package/lib/structures/IReflectHttpOperationParameter.d.ts +3 -5
  81. package/lib/structures/IReflectHttpOperationSuccess.d.ts +3 -4
  82. package/lib/structures/ITypedApplication.d.ts +1 -1
  83. package/lib/structures/ITypedHttpRouteException.d.ts +2 -2
  84. package/lib/structures/ITypedHttpRouteParameter.d.ts +2 -2
  85. package/lib/structures/ITypedHttpRouteSuccess.d.ts +2 -2
  86. package/lib/transformers/IOperationMetadata.d.ts +2 -4
  87. package/lib/transformers/ISdkOperationTransformerContext.d.ts +1 -1
  88. package/lib/transformers/SdkOperationProgrammer.js +8 -10
  89. package/lib/transformers/SdkOperationProgrammer.js.map +1 -1
  90. package/lib/transformers/SdkOperationTransformer.js +6 -8
  91. package/lib/transformers/SdkOperationTransformer.js.map +1 -1
  92. package/lib/transformers/TextPlainValidator.d.ts +2 -2
  93. package/lib/transformers/TextPlainValidator.js.map +1 -1
  94. package/lib/utils/MetadataUtil.d.ts +2 -2
  95. package/lib/utils/MetadataUtil.js.map +1 -1
  96. package/lib/validators/HttpHeadersValidator.d.ts +2 -3
  97. package/lib/validators/HttpHeadersValidator.js +2 -2
  98. package/lib/validators/HttpHeadersValidator.js.map +1 -1
  99. package/lib/validators/HttpQueryValidator.d.ts +2 -3
  100. package/lib/validators/HttpQueryValidator.js +2 -2
  101. package/lib/validators/HttpQueryValidator.js.map +1 -1
  102. package/package.json +44 -30
  103. package/src/INestiaConfig.ts +267 -267
  104. package/src/NestiaSdkApplication.ts +307 -307
  105. package/src/NestiaSwaggerComposer.ts +143 -138
  106. package/src/analyses/AccessorAnalyzer.ts +67 -67
  107. package/src/analyses/DtoAnalyzer.ts +260 -260
  108. package/src/analyses/ImportAnalyzer.ts +126 -126
  109. package/src/analyses/ReflectHttpOperationAnalyzer.ts +183 -183
  110. package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +72 -71
  111. package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +350 -348
  112. package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +126 -127
  113. package/src/analyses/TypedHttpRouteAnalyzer.ts +208 -204
  114. package/src/executable/internal/NestiaConfigLoader.ts +85 -78
  115. package/src/executable/internal/NestiaSdkCommand.ts +107 -103
  116. package/src/generates/SwaggerGenerator.ts +291 -284
  117. package/src/generates/internal/E2eFileProgrammer.ts +196 -197
  118. package/src/generates/internal/FilePrinter.ts +64 -64
  119. package/src/generates/internal/ImportDictionary.ts +192 -192
  120. package/src/generates/internal/SdkAliasCollection.ts +260 -261
  121. package/src/generates/internal/SdkFileProgrammer.ts +110 -110
  122. package/src/generates/internal/SdkHttpCloneProgrammer.ts +126 -124
  123. package/src/generates/internal/SdkHttpCloneReferencer.ts +77 -77
  124. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +278 -279
  125. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +502 -500
  126. package/src/generates/internal/SdkHttpRouteProgrammer.ts +109 -108
  127. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +312 -310
  128. package/src/generates/internal/SdkImportWizard.ts +62 -62
  129. package/src/generates/internal/SdkTypeProgrammer.ts +388 -385
  130. package/src/generates/internal/SdkTypeTagProgrammer.ts +114 -104
  131. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +379 -381
  132. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +302 -302
  133. package/src/generates/internal/SwaggerOperationComposer.ts +119 -119
  134. package/src/generates/internal/SwaggerOperationParameterComposer.ts +161 -162
  135. package/src/generates/internal/SwaggerOperationResponseComposer.ts +110 -110
  136. package/src/module.ts +4 -3
  137. package/src/structures/IReflectHttpOperationException.ts +18 -19
  138. package/src/structures/IReflectHttpOperationParameter.ts +79 -77
  139. package/src/structures/IReflectHttpOperationSuccess.ts +21 -22
  140. package/src/structures/ITypedApplication.ts +11 -11
  141. package/src/structures/ITypedHttpRouteException.ts +15 -15
  142. package/src/structures/ITypedHttpRouteParameter.ts +41 -41
  143. package/src/structures/ITypedHttpRouteSuccess.ts +22 -22
  144. package/src/transformers/IOperationMetadata.ts +46 -44
  145. package/src/transformers/ISdkOperationTransformerContext.ts +8 -8
  146. package/src/transformers/SdkOperationProgrammer.ts +240 -238
  147. package/src/transformers/SdkOperationTransformer.ts +248 -252
  148. package/src/transformers/TextPlainValidator.ts +17 -17
  149. package/src/utils/MetadataUtil.ts +26 -26
  150. package/src/validators/HttpHeadersValidator.ts +36 -34
  151. package/src/validators/HttpQueryValidator.ts +36 -34
@@ -1,44 +1,46 @@
1
- import { IJsDocTagInfo } from "typia";
2
- import { IMetadata } from "typia/lib/schemas/metadata/IMetadata";
3
- import { IMetadataComponents } from "typia/lib/schemas/metadata/IMetadataComponents";
4
- import { ValidationPipe } from "typia/lib/typings/ValidationPipe";
5
-
6
- import { IReflectImport } from "../structures/IReflectImport";
7
- import { IReflectType } from "../structures/IReflectType";
8
-
9
- export interface IOperationMetadata {
10
- parameters: IOperationMetadata.IParameter[];
11
- success: IOperationMetadata.IResponse;
12
- exceptions: IOperationMetadata.IResponse[];
13
- description: string | null;
14
- jsDocTags: IJsDocTagInfo[];
15
- }
16
- export namespace IOperationMetadata {
17
- export interface IParameter extends IResponse {
18
- name: string;
19
- index: number;
20
- description: string | null;
21
- jsDocTags: IJsDocTagInfo[];
22
- }
23
- export interface IResponse {
24
- type: IReflectType | null;
25
- imports: IReflectImport[];
26
- primitive: ValidationPipe<ISchema, IError>;
27
- resolved: ValidationPipe<ISchema, IError>;
28
- }
29
- export interface IException {
30
- type: IReflectType | null;
31
- imports: IReflectImport[];
32
- primitive: ValidationPipe<ISchema, IError>;
33
- }
34
-
35
- export interface ISchema {
36
- components: IMetadataComponents;
37
- metadata: IMetadata;
38
- }
39
- export interface IError {
40
- name: string;
41
- accessor: string | null;
42
- messages: string[];
43
- }
44
- }
1
+ import {
2
+ IMetadataComponents,
3
+ IMetadataSchema,
4
+ ValidationPipe,
5
+ } from "@typia/interface";
6
+ import { IJsDocTagInfo } from "typia";
7
+
8
+ import { IReflectImport } from "../structures/IReflectImport";
9
+ import { IReflectType } from "../structures/IReflectType";
10
+
11
+ export interface IOperationMetadata {
12
+ parameters: IOperationMetadata.IParameter[];
13
+ success: IOperationMetadata.IResponse;
14
+ exceptions: IOperationMetadata.IResponse[];
15
+ description: string | null;
16
+ jsDocTags: IJsDocTagInfo[];
17
+ }
18
+ export namespace IOperationMetadata {
19
+ export interface IParameter extends IResponse {
20
+ name: string;
21
+ index: number;
22
+ description: string | null;
23
+ jsDocTags: IJsDocTagInfo[];
24
+ }
25
+ export interface IResponse {
26
+ type: IReflectType | null;
27
+ imports: IReflectImport[];
28
+ primitive: ValidationPipe<ISchema, IError>;
29
+ resolved: ValidationPipe<ISchema, IError>;
30
+ }
31
+ export interface IException {
32
+ type: IReflectType | null;
33
+ imports: IReflectImport[];
34
+ primitive: ValidationPipe<ISchema, IError>;
35
+ }
36
+
37
+ export interface ISchema {
38
+ components: IMetadataComponents;
39
+ metadata: IMetadataSchema;
40
+ }
41
+ export interface IError {
42
+ name: string;
43
+ accessor: string | null;
44
+ messages: string[];
45
+ }
46
+ }
@@ -1,8 +1,8 @@
1
- import ts from "typescript";
2
- import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
3
-
4
- export interface ISdkOperationTransformerContext {
5
- checker: ts.TypeChecker;
6
- transformer: ts.TransformationContext;
7
- collection: MetadataCollection;
8
- }
1
+ import { MetadataCollection } from "@typia/core";
2
+ import ts from "typescript";
3
+
4
+ export interface ISdkOperationTransformerContext {
5
+ checker: ts.TypeChecker;
6
+ transformer: ts.TransformationContext;
7
+ collection: MetadataCollection;
8
+ }
@@ -1,238 +1,240 @@
1
- import { Singleton } from "tstl";
2
- import ts from "typescript";
3
- import { CommentFactory } from "typia/lib/factories/CommentFactory";
4
- import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
5
- import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
6
- import { TypeFactory } from "typia/lib/factories/TypeFactory";
7
- import { Metadata } from "typia/lib/schemas/metadata/Metadata";
8
- import { MetadataObjectType } from "typia/lib/schemas/metadata/MetadataObjectType";
9
- import { ValidationPipe } from "typia/lib/typings/ValidationPipe";
10
- import { Escaper } from "typia/lib/utils/Escaper";
11
-
12
- import { DtoAnalyzer } from "../analyses/DtoAnalyzer";
13
- import { IReflectImport } from "../structures/IReflectImport";
14
- import { MetadataUtil } from "../utils/MetadataUtil";
15
- import { IOperationMetadata } from "./IOperationMetadata";
16
- import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
17
-
18
- export namespace SdkOperationProgrammer {
19
- export interface IProps {
20
- context: ISdkOperationTransformerContext;
21
- imports: Singleton<IReflectImport[]>;
22
- node: ts.MethodDeclaration;
23
- symbol: ts.Symbol | undefined;
24
- exceptions: ts.TypeNode[];
25
- }
26
- export const write = (p: IProps): IOperationMetadata => {
27
- return {
28
- parameters: p.node.parameters.map((parameter, index) =>
29
- writeParameter({
30
- context: p.context,
31
- imports: p.imports,
32
- parameter,
33
- index,
34
- }),
35
- ),
36
- success: writeResponse({
37
- context: p.context,
38
- imports: p.imports,
39
- typeNode: p.node.type ? getReturnTypeNode(p.node.type) : null,
40
- type: getReturnType({
41
- checker: p.context.checker,
42
- signature: p.context.checker.getSignatureFromDeclaration(p.node),
43
- }),
44
- }),
45
- exceptions: p.exceptions.map((e) =>
46
- writeResponse({
47
- context: p.context,
48
- imports: p.imports,
49
- typeNode: e,
50
- type: p.context.checker.getTypeFromTypeNode(e),
51
- }),
52
- ),
53
- jsDocTags: p.symbol?.getJsDocTags() ?? [],
54
- description: p.symbol
55
- ? (CommentFactory.description(p.symbol) ?? null)
56
- : null,
57
- };
58
- };
59
-
60
- const writeParameter = (props: {
61
- context: ISdkOperationTransformerContext;
62
- imports: Singleton<IReflectImport[]>;
63
- parameter: ts.ParameterDeclaration;
64
- index: number;
65
- }): IOperationMetadata.IParameter => {
66
- const symbol: ts.Symbol | undefined =
67
- props.context.checker.getSymbolAtLocation(props.parameter);
68
- const common: IOperationMetadata.IResponse = writeResponse({
69
- context: props.context,
70
- imports: props.imports,
71
- typeNode: props.parameter.type ?? null,
72
- type:
73
- props.context.checker.getTypeFromTypeNode(
74
- props.parameter.type ?? TypeFactory.keyword("any"),
75
- ) ?? null,
76
- });
77
- const optional: boolean = props.parameter.questionToken !== undefined;
78
- if (common.primitive.success)
79
- common.primitive.data.metadata.optional = optional;
80
- if (common.resolved.success)
81
- common.resolved.data.metadata.optional = optional;
82
-
83
- return {
84
- ...common,
85
- name: props.parameter.name.getText(),
86
- index: props.index,
87
- description: (symbol && CommentFactory.description(symbol)) ?? null,
88
- jsDocTags: symbol?.getJsDocTags() ?? [],
89
- };
90
- };
91
-
92
- const writeResponse = (p: {
93
- context: ISdkOperationTransformerContext;
94
- imports: Singleton<IReflectImport[]>;
95
- typeNode: ts.TypeNode | null;
96
- type: ts.Type | null;
97
- }): IOperationMetadata.IResponse => {
98
- const analyzed: DtoAnalyzer.IOutput | null = p.typeNode
99
- ? DtoAnalyzer.analyzeNode({
100
- checker: p.context.checker,
101
- imports: p.imports.get(),
102
- typeNode: p.typeNode,
103
- })
104
- : p.type
105
- ? DtoAnalyzer.analyzeType({
106
- checker: p.context.checker,
107
- imports: p.imports.get(),
108
- type: p.type,
109
- })
110
- : {
111
- type: { name: "any" },
112
- imports: [],
113
- };
114
- const [primitive, resolved] = [true, false].map((escape) =>
115
- MetadataFactory.analyze({
116
- checker: p.context.checker,
117
- transformer: p.context.transformer,
118
- options: {
119
- escape,
120
- constant: true,
121
- absorb: true,
122
- },
123
- collection: p.context.collection,
124
- type: p.type,
125
- }),
126
- );
127
- return {
128
- ...(analyzed
129
- ? analyzed
130
- : {
131
- imports: [],
132
- type: null,
133
- }),
134
- primitive: writeSchema({
135
- collection: p.context.collection,
136
- result: primitive,
137
- }),
138
- resolved: writeSchema({
139
- collection: p.context.collection,
140
- result: resolved,
141
- }),
142
- };
143
- };
144
-
145
- const writeSchema = (p: {
146
- collection: MetadataCollection;
147
- result: ValidationPipe<Metadata, MetadataFactory.IError>;
148
- }): ValidationPipe<IOperationMetadata.ISchema, IOperationMetadata.IError> => {
149
- if (p.result.success === false)
150
- return {
151
- success: false,
152
- errors: p.result.errors.map((e) => ({
153
- name: e.name,
154
- accessor:
155
- e.explore.object !== null
156
- ? join({
157
- object: e.explore.object,
158
- key: e.explore.property,
159
- })
160
- : null,
161
- messages: e.messages,
162
- })),
163
- };
164
- const visited: Set<string> = iterateVisited(p.result.data);
165
- return {
166
- success: true,
167
- data: {
168
- components: {
169
- objects: p.collection
170
- .objects()
171
- .filter((o) => visited.has(o.name))
172
- .map((o) => o.toJSON()),
173
- aliases: p.collection
174
- .aliases()
175
- .filter((a) => visited.has(a.name))
176
- .map((a) => a.toJSON()),
177
- arrays: p.collection
178
- .arrays()
179
- .filter((a) => visited.has(a.name))
180
- .map((a) => a.toJSON()),
181
- tuples: p.collection
182
- .tuples()
183
- .filter((t) => visited.has(t.name))
184
- .map((t) => t.toJSON()),
185
- },
186
- metadata: p.result.data.toJSON(),
187
- },
188
- };
189
- };
190
- }
191
-
192
- const iterateVisited = (metadata: Metadata): Set<string> => {
193
- const names: Set<string> = new Set();
194
- MetadataUtil.visit((m) => {
195
- for (const alias of m.aliases) names.add(alias.type.name);
196
- for (const array of m.arrays) names.add(array.type.name);
197
- for (const tuple of m.tuples) names.add(tuple.type.name);
198
- for (const object of m.objects) names.add(object.type.name);
199
- })(metadata);
200
- return names;
201
- };
202
-
203
- const join = ({
204
- object,
205
- key,
206
- }: {
207
- object: MetadataObjectType;
208
- key: string | object | null;
209
- }) => {
210
- if (key === null) return object.name;
211
- else if (typeof key === "object") return `${object.name}[key]`;
212
- else if (Escaper.variable(key)) return `${object.name}.${key}`;
213
- return `${object.name}[${JSON.stringify(key)}]`;
214
- };
215
-
216
- const getReturnTypeNode = (node: ts.TypeNode): ts.TypeNode | null => {
217
- if (ts.isTypeReferenceNode(node)) {
218
- const typeName: string = node.typeName.getText();
219
- if (typeName === "Promise") return node.typeArguments?.[0] ?? null;
220
- }
221
- return node;
222
- };
223
-
224
- const getReturnType = (p: {
225
- checker: ts.TypeChecker;
226
- signature: ts.Signature | undefined;
227
- }): ts.Type | null => {
228
- const type: ts.Type | null =
229
- (p.signature && p.checker.getReturnTypeOfSignature(p.signature)) ?? null;
230
- if (type === null) return null;
231
- else if (type.symbol?.name === "Promise") {
232
- const generic: readonly ts.Type[] = p.checker.getTypeArguments(
233
- type as ts.TypeReference,
234
- );
235
- return generic[0] ?? null;
236
- }
237
- return type;
238
- };
1
+ import {
2
+ CommentFactory,
3
+ MetadataCollection,
4
+ MetadataFactory,
5
+ MetadataObjectType,
6
+ MetadataSchema,
7
+ TypeFactory,
8
+ } from "@typia/core";
9
+ import { ValidationPipe } from "@typia/interface";
10
+ import { NamingConvention } from "@typia/utils";
11
+ import { Singleton } from "tstl";
12
+ import ts from "typescript";
13
+
14
+ import { DtoAnalyzer } from "../analyses/DtoAnalyzer";
15
+ import { IReflectImport } from "../structures/IReflectImport";
16
+ import { MetadataUtil } from "../utils/MetadataUtil";
17
+ import { IOperationMetadata } from "./IOperationMetadata";
18
+ import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
19
+
20
+ export namespace SdkOperationProgrammer {
21
+ export interface IProps {
22
+ context: ISdkOperationTransformerContext;
23
+ imports: Singleton<IReflectImport[]>;
24
+ node: ts.MethodDeclaration;
25
+ symbol: ts.Symbol | undefined;
26
+ exceptions: ts.TypeNode[];
27
+ }
28
+ export const write = (p: IProps): IOperationMetadata => {
29
+ return {
30
+ parameters: p.node.parameters.map((parameter, index) =>
31
+ writeParameter({
32
+ context: p.context,
33
+ imports: p.imports,
34
+ parameter,
35
+ index,
36
+ }),
37
+ ),
38
+ success: writeResponse({
39
+ context: p.context,
40
+ imports: p.imports,
41
+ typeNode: p.node.type ? getReturnTypeNode(p.node.type) : null,
42
+ type: getReturnType({
43
+ checker: p.context.checker,
44
+ signature: p.context.checker.getSignatureFromDeclaration(p.node),
45
+ }),
46
+ }),
47
+ exceptions: p.exceptions.map((e) =>
48
+ writeResponse({
49
+ context: p.context,
50
+ imports: p.imports,
51
+ typeNode: e,
52
+ type: p.context.checker.getTypeFromTypeNode(e),
53
+ }),
54
+ ),
55
+ jsDocTags: p.symbol?.getJsDocTags() ?? [],
56
+ description: p.symbol
57
+ ? (CommentFactory.description(p.symbol) ?? null)
58
+ : null,
59
+ };
60
+ };
61
+
62
+ const writeParameter = (props: {
63
+ context: ISdkOperationTransformerContext;
64
+ imports: Singleton<IReflectImport[]>;
65
+ parameter: ts.ParameterDeclaration;
66
+ index: number;
67
+ }): IOperationMetadata.IParameter => {
68
+ const symbol: ts.Symbol | undefined =
69
+ props.context.checker.getSymbolAtLocation(props.parameter);
70
+ const common: IOperationMetadata.IResponse = writeResponse({
71
+ context: props.context,
72
+ imports: props.imports,
73
+ typeNode: props.parameter.type ?? null,
74
+ type:
75
+ props.context.checker.getTypeFromTypeNode(
76
+ props.parameter.type ?? TypeFactory.keyword("any"),
77
+ ) ?? null,
78
+ });
79
+ const optional: boolean = props.parameter.questionToken !== undefined;
80
+ if (common.primitive.success)
81
+ common.primitive.data.metadata.optional = optional;
82
+ if (common.resolved.success)
83
+ common.resolved.data.metadata.optional = optional;
84
+
85
+ return {
86
+ ...common,
87
+ name: props.parameter.name.getText(),
88
+ index: props.index,
89
+ description: (symbol && CommentFactory.description(symbol)) ?? null,
90
+ jsDocTags: symbol?.getJsDocTags() ?? [],
91
+ };
92
+ };
93
+
94
+ const writeResponse = (p: {
95
+ context: ISdkOperationTransformerContext;
96
+ imports: Singleton<IReflectImport[]>;
97
+ typeNode: ts.TypeNode | null;
98
+ type: ts.Type | null;
99
+ }): IOperationMetadata.IResponse => {
100
+ const analyzed: DtoAnalyzer.IOutput | null = p.typeNode
101
+ ? DtoAnalyzer.analyzeNode({
102
+ checker: p.context.checker,
103
+ imports: p.imports.get(),
104
+ typeNode: p.typeNode,
105
+ })
106
+ : p.type
107
+ ? DtoAnalyzer.analyzeType({
108
+ checker: p.context.checker,
109
+ imports: p.imports.get(),
110
+ type: p.type,
111
+ })
112
+ : {
113
+ type: { name: "any" },
114
+ imports: [],
115
+ };
116
+ const [primitive, resolved] = [true, false].map((escape) =>
117
+ MetadataFactory.analyze({
118
+ checker: p.context.checker,
119
+ transformer: p.context.transformer,
120
+ options: {
121
+ escape,
122
+ constant: true,
123
+ absorb: true,
124
+ },
125
+ components: p.context.collection,
126
+ type: p.type,
127
+ }),
128
+ );
129
+ return {
130
+ ...(analyzed
131
+ ? analyzed
132
+ : {
133
+ imports: [],
134
+ type: null,
135
+ }),
136
+ primitive: writeSchema({
137
+ collection: p.context.collection,
138
+ result: primitive!,
139
+ }),
140
+ resolved: writeSchema({
141
+ collection: p.context.collection,
142
+ result: resolved!,
143
+ }),
144
+ };
145
+ };
146
+
147
+ const writeSchema = (p: {
148
+ collection: MetadataCollection;
149
+ result: ValidationPipe<MetadataSchema, MetadataFactory.IError>;
150
+ }): ValidationPipe<IOperationMetadata.ISchema, IOperationMetadata.IError> => {
151
+ if (p.result.success === false)
152
+ return {
153
+ success: false,
154
+ errors: p.result.errors.map((e) => ({
155
+ name: e.name,
156
+ accessor:
157
+ e.explore.object !== null
158
+ ? join({
159
+ object: e.explore.object,
160
+ key: e.explore.property,
161
+ })
162
+ : null,
163
+ messages: e.messages,
164
+ })),
165
+ };
166
+ const visited: Set<string> = iterateVisited(p.result.data);
167
+ return {
168
+ success: true,
169
+ data: {
170
+ components: {
171
+ objects: p.collection
172
+ .objects()
173
+ .filter((o) => visited.has(o.name))
174
+ .map((o) => o.toJSON()),
175
+ aliases: p.collection
176
+ .aliases()
177
+ .filter((a) => visited.has(a.name))
178
+ .map((a) => a.toJSON()),
179
+ arrays: p.collection
180
+ .arrays()
181
+ .filter((a) => visited.has(a.name))
182
+ .map((a) => a.toJSON()),
183
+ tuples: p.collection
184
+ .tuples()
185
+ .filter((t) => visited.has(t.name))
186
+ .map((t) => t.toJSON()),
187
+ },
188
+ metadata: p.result.data.toJSON(),
189
+ },
190
+ };
191
+ };
192
+ }
193
+
194
+ const iterateVisited = (metadata: MetadataSchema): Set<string> => {
195
+ const names: Set<string> = new Set();
196
+ MetadataUtil.visit((m) => {
197
+ for (const alias of m.aliases) names.add(alias.type.name);
198
+ for (const array of m.arrays) names.add(array.type.name);
199
+ for (const tuple of m.tuples) names.add(tuple.type.name);
200
+ for (const object of m.objects) names.add(object.type.name);
201
+ })(metadata);
202
+ return names;
203
+ };
204
+
205
+ const join = ({
206
+ object,
207
+ key,
208
+ }: {
209
+ object: MetadataObjectType;
210
+ key: string | object | null;
211
+ }) => {
212
+ if (key === null) return object.name;
213
+ else if (typeof key === "object") return `${object.name}[key]`;
214
+ else if (NamingConvention.variable(key)) return `${object.name}.${key}`;
215
+ return `${object.name}[${JSON.stringify(key)}]`;
216
+ };
217
+
218
+ const getReturnTypeNode = (node: ts.TypeNode): ts.TypeNode | null => {
219
+ if (ts.isTypeReferenceNode(node)) {
220
+ const typeName: string = node.typeName.getText();
221
+ if (typeName === "Promise") return node.typeArguments?.[0] ?? null;
222
+ }
223
+ return node;
224
+ };
225
+
226
+ const getReturnType = (p: {
227
+ checker: ts.TypeChecker;
228
+ signature: ts.Signature | undefined;
229
+ }): ts.Type | null => {
230
+ const type: ts.Type | null =
231
+ (p.signature && p.checker.getReturnTypeOfSignature(p.signature)) ?? null;
232
+ if (type === null) return null;
233
+ else if (type.symbol?.name === "Promise") {
234
+ const generic: readonly ts.Type[] = p.checker.getTypeArguments(
235
+ type as ts.TypeReference,
236
+ );
237
+ return generic[0] ?? null;
238
+ }
239
+ return type;
240
+ };