@nestia/sdk 12.0.0-dev.20260612.2 → 12.0.0-dev.20260619.1

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 (93) hide show
  1. package/assets/bundle/distribute/package.json +1 -1
  2. package/lib/factories/ExpressionFactory.d.ts +9 -0
  3. package/lib/factories/ExpressionFactory.js +16 -0
  4. package/lib/factories/ExpressionFactory.js.map +1 -0
  5. package/lib/factories/IdentifierFactory.d.ts +22 -0
  6. package/lib/factories/IdentifierFactory.js +50 -0
  7. package/lib/factories/IdentifierFactory.js.map +1 -0
  8. package/lib/factories/LiteralFactory.d.ts +9 -0
  9. package/lib/factories/LiteralFactory.js +48 -0
  10. package/lib/factories/LiteralFactory.js.map +1 -0
  11. package/lib/factories/StatementFactory.d.ts +14 -0
  12. package/lib/factories/StatementFactory.js +20 -0
  13. package/lib/factories/StatementFactory.js.map +1 -0
  14. package/lib/factories/TypeFactory.d.ts +24 -0
  15. package/lib/factories/TypeFactory.js +27 -0
  16. package/lib/factories/TypeFactory.js.map +1 -0
  17. package/lib/generates/CloneGenerator.js +2 -2
  18. package/lib/generates/CloneGenerator.js.map +1 -1
  19. package/lib/generates/internal/E2eFileProgrammer.js +30 -29
  20. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  21. package/lib/generates/internal/FilePrinter.d.ts +2 -2
  22. package/lib/generates/internal/FilePrinter.js +14 -25
  23. package/lib/generates/internal/FilePrinter.js.map +1 -1
  24. package/lib/generates/internal/ImportDictionary.d.ts +1 -1
  25. package/lib/generates/internal/ImportDictionary.js +10 -9
  26. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  27. package/lib/generates/internal/SdkAliasCollection.d.ts +12 -12
  28. package/lib/generates/internal/SdkAliasCollection.js +23 -25
  29. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  30. package/lib/generates/internal/SdkFileProgrammer.js +2 -2
  31. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  32. package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +1 -1
  33. package/lib/generates/internal/SdkHttpCloneProgrammer.js +3 -3
  34. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
  35. package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +1 -1
  36. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +45 -48
  37. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  38. package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +1 -1
  39. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +61 -60
  40. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  41. package/lib/generates/internal/SdkHttpParameterProgrammer.d.ts +2 -2
  42. package/lib/generates/internal/SdkHttpParameterProgrammer.js +11 -13
  43. package/lib/generates/internal/SdkHttpParameterProgrammer.js.map +1 -1
  44. package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +1 -1
  45. package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +1 -1
  46. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +50 -48
  47. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  48. package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +1 -1
  49. package/lib/generates/internal/SdkMcpRouteProgrammer.js +54 -53
  50. package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -1
  51. package/lib/generates/internal/SdkTypeProgrammer.d.ts +3 -3
  52. package/lib/generates/internal/SdkTypeProgrammer.js +42 -43
  53. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
  54. package/lib/generates/internal/SdkTypeTagProgrammer.d.ts +2 -1
  55. package/lib/generates/internal/SdkTypeTagProgrammer.js +7 -9
  56. package/lib/generates/internal/SdkTypeTagProgrammer.js.map +1 -1
  57. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +2 -2
  58. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +45 -47
  59. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
  60. package/lib/generates/internal/SdkWebSocketParameterProgrammer.d.ts +3 -3
  61. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js +9 -9
  62. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js.map +1 -1
  63. package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +2 -2
  64. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +34 -40
  65. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  66. package/lib/transform.d.ts +5 -9
  67. package/lib/transform.js +8 -31
  68. package/lib/transform.js.map +1 -1
  69. package/package.json +11 -11
  70. package/src/factories/ExpressionFactory.ts +23 -0
  71. package/src/factories/IdentifierFactory.ts +84 -0
  72. package/src/factories/LiteralFactory.ts +54 -0
  73. package/src/factories/StatementFactory.ts +56 -0
  74. package/src/factories/TypeFactory.ts +27 -0
  75. package/src/generates/CloneGenerator.ts +8 -7
  76. package/src/generates/internal/E2eFileProgrammer.ts +59 -53
  77. package/src/generates/internal/FilePrinter.ts +28 -36
  78. package/src/generates/internal/ImportDictionary.ts +19 -21
  79. package/src/generates/internal/SdkAliasCollection.ts +55 -49
  80. package/src/generates/internal/SdkFileProgrammer.ts +4 -7
  81. package/src/generates/internal/SdkHttpCloneProgrammer.ts +11 -13
  82. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +90 -101
  83. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +153 -166
  84. package/src/generates/internal/SdkHttpParameterProgrammer.ts +15 -17
  85. package/src/generates/internal/SdkHttpRouteProgrammer.ts +1 -1
  86. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +121 -130
  87. package/src/generates/internal/SdkMcpRouteProgrammer.ts +135 -140
  88. package/src/generates/internal/SdkTypeProgrammer.ts +389 -382
  89. package/src/generates/internal/SdkTypeTagProgrammer.ts +13 -17
  90. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +124 -130
  91. package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +17 -15
  92. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +112 -139
  93. package/src/transform.ts +14 -45
@@ -1,382 +1,389 @@
1
- import { Node, SyntaxKind, TypeScriptFactory } from "@nestia/factory";
2
- import { ExpressionFactory, TypeFactory } from "@nestia/factory";
3
- import { MetadataAliasType, MetadataArray, MetadataAtomic, MetadataConstantValue, MetadataEscaped, MetadataObjectType, MetadataProperty, MetadataSchema, MetadataTuple, isSoleLiteralOf, sizeOf } from "../../internal/legacy";
4
- import { NamingConvention } from "@typia/utils";
5
- import { IJsDocTagInfo, IMetadataTypeTag } from "typia";
6
-
7
- import { INestiaProject } from "../../structures/INestiaProject";
8
- import { FilePrinter } from "./FilePrinter";
9
- import { ImportDictionary } from "./ImportDictionary";
10
- import { SdkTypeTagProgrammer } from "./SdkTypeTagProgrammer";
11
-
12
- export namespace SdkTypeProgrammer {
13
- /* -----------------------------------------------------------
14
- FACADE
15
- ----------------------------------------------------------- */
16
- export const write =
17
- (project: INestiaProject) =>
18
- (importer: ImportDictionary) =>
19
- (meta: MetadataSchema, parentEscaped: boolean = false): Node => {
20
- const union: Node[] = [];
21
-
22
- // COALESCES
23
- if (meta.any) union.push(TypeFactory.keyword("any"));
24
- if (meta.nullable) union.push(writeNode("null"));
25
- if (meta.required === false) union.push(writeNode("undefined"));
26
- if (parentEscaped === false && meta.escaped)
27
- union.push(write_escaped(project)(importer)(meta.escaped));
28
-
29
- // ATOMIC TYPES
30
- for (const c of meta.constants)
31
- for (const value of c.values) union.push(write_constant(value));
32
- for (const tpl of meta.templates)
33
- union.push(write_template(project)(importer)(tpl.row ?? tpl));
34
- for (const atom of meta.atomics) union.push(write_atomic(importer)(atom));
35
-
36
- // OBJECT TYPES
37
- for (const tuple of meta.tuples)
38
- union.push(write_tuple(project)(importer)(tuple as MetadataTuple));
39
- for (const array of meta.arrays)
40
- union.push(write_array(project)(importer)(array as MetadataArray));
41
- for (const object of meta.objects) {
42
- const target = object.type as MetadataObjectType;
43
- if (
44
- target.name === "object" ||
45
- target.name === "__type" ||
46
- target.name.startsWith("__type.") ||
47
- target.name === "__object" ||
48
- target.name.startsWith("__object.")
49
- )
50
- union.push(write_object(project)(importer)(target));
51
- else union.push(writeAlias(project)(importer)(target));
52
- }
53
- for (const alias of meta.aliases)
54
- union.push(writeAlias(project)(importer)(alias.type as MetadataAliasType));
55
- for (const native of meta.natives)
56
- if (native.name === "Blob" || native.name === "File")
57
- union.push(write_native(native.name));
58
-
59
- return union.length === 1
60
- ? union[0]!
61
- : TypeScriptFactory.createUnionTypeNode(union);
62
- };
63
-
64
- export const write_object =
65
- (project: INestiaProject) =>
66
- (importer: ImportDictionary) =>
67
- (object: MetadataObjectType): Node => {
68
- const regular = object.properties.filter((p) => isSoleLiteralOf(p.key));
69
- const dynamic = object.properties.filter((p) => !isSoleLiteralOf(p.key));
70
- return regular.length && dynamic.length
71
- ? TypeScriptFactory.createIntersectionTypeNode([
72
- write_regular_property(project)(importer)(regular),
73
- ...dynamic.map(write_dynamic_property(project)(importer)),
74
- ])
75
- : dynamic.length
76
- ? TypeScriptFactory.createIntersectionTypeNode(
77
- dynamic.map(write_dynamic_property(project)(importer)),
78
- )
79
- : write_regular_property(project)(importer)(regular);
80
- };
81
-
82
- const write_escaped =
83
- (project: INestiaProject) =>
84
- (importer: ImportDictionary) =>
85
- (meta: MetadataEscaped): Node => {
86
- if (
87
- sizeOf(meta.original) === 1 &&
88
- meta.original.natives.length === 1 &&
89
- meta.original.natives[0]!.name === "Date"
90
- )
91
- return TypeScriptFactory.createIntersectionTypeNode([
92
- TypeFactory.keyword("string"),
93
- SdkTypeTagProgrammer.write(importer, "string", {
94
- name: "Format",
95
- value: "date-time",
96
- } as IMetadataTypeTag),
97
- ]);
98
- return write(project)(importer)(meta.returns, true);
99
- };
100
-
101
- /* -----------------------------------------------------------
102
- ATOMICS
103
- ----------------------------------------------------------- */
104
- const write_constant = (value: MetadataConstantValue) => {
105
- if (typeof value.value === "boolean")
106
- return TypeScriptFactory.createLiteralTypeNode(
107
- value.value
108
- ? TypeScriptFactory.createTrue()
109
- : TypeScriptFactory.createFalse(),
110
- );
111
- else if (typeof value.value === "bigint")
112
- return TypeScriptFactory.createLiteralTypeNode(
113
- value.value < BigInt(0)
114
- ? TypeScriptFactory.createPrefixUnaryExpression(
115
- SyntaxKind.MinusToken,
116
- TypeScriptFactory.createBigIntLiteral((-value.value).toString()),
117
- )
118
- : TypeScriptFactory.createBigIntLiteral(value.value.toString()),
119
- );
120
- else if (typeof value.value === "number")
121
- return TypeScriptFactory.createLiteralTypeNode(
122
- ExpressionFactory.number(value.value),
123
- );
124
- return TypeScriptFactory.createLiteralTypeNode(
125
- TypeScriptFactory.createStringLiteral(value.value as string),
126
- );
127
- };
128
-
129
- const write_template =
130
- (project: INestiaProject) =>
131
- (importer: ImportDictionary) =>
132
- (meta: MetadataSchema[]): Node => {
133
- const head: boolean = isSoleLiteralOf(meta[0]!);
134
- const spans: [Node | null, string | null][] = [];
135
- for (const elem of meta.slice(head ? 1 : 0)) {
136
- const last =
137
- spans.at(-1) ??
138
- (() => {
139
- const tuple = [null!, null!] as [Node | null, string | null];
140
- spans.push(tuple);
141
- return tuple;
142
- })();
143
- if (isSoleLiteralOf(elem))
144
- if (last[1] === null)
145
- last[1] = String(elem.constants[0]!.values[0]!.value);
146
- else
147
- spans.push([
148
- TypeScriptFactory.createLiteralTypeNode(
149
- TypeScriptFactory.createStringLiteral(
150
- String(elem.constants[0]!.values[0]!.value),
151
- ),
152
- ),
153
- null,
154
- ]);
155
- else if (last[0] === null) last[0] = write(project)(importer)(elem);
156
- else spans.push([write(project)(importer)(elem), null]);
157
- }
158
- return TypeScriptFactory.createTemplateLiteralType(
159
- TypeScriptFactory.createTemplateHead(
160
- head ? (meta[0]!.constants[0]!.values[0]!.value as string) : "",
161
- ),
162
- spans
163
- .filter(([node]) => node !== null)
164
- .map(([node, str], i, array) =>
165
- TypeScriptFactory.createTemplateLiteralTypeSpan(
166
- node!,
167
- (i !== array.length - 1
168
- ? TypeScriptFactory.createTemplateMiddle
169
- : TypeScriptFactory.createTemplateTail)(str ?? ""),
170
- ),
171
- ),
172
- );
173
- };
174
-
175
- const write_atomic =
176
- (importer: ImportDictionary) =>
177
- (meta: MetadataAtomic): Node =>
178
- write_type_tag_matrix(importer)(
179
- meta.type as "boolean" | "bigint" | "number" | "string",
180
- TypeScriptFactory.createKeywordTypeNode(
181
- meta.type === "boolean"
182
- ? SyntaxKind.BooleanKeyword
183
- : meta.type === "bigint"
184
- ? SyntaxKind.BigIntKeyword
185
- : meta.type === "number"
186
- ? SyntaxKind.NumberKeyword
187
- : SyntaxKind.StringKeyword,
188
- ),
189
- meta.tags,
190
- );
191
-
192
- /* -----------------------------------------------------------
193
- INSTANCES
194
- ----------------------------------------------------------- */
195
- const write_array =
196
- (project: INestiaProject) =>
197
- (importer: ImportDictionary) =>
198
- (meta: MetadataArray): Node =>
199
- write_type_tag_matrix(importer)(
200
- "array",
201
- TypeScriptFactory.createArrayTypeNode(
202
- write(project)(importer)(meta.type!.value),
203
- ),
204
- meta.tags,
205
- );
206
-
207
- const write_tuple =
208
- (project: INestiaProject) =>
209
- (importer: ImportDictionary) =>
210
- (meta: MetadataTuple): Node =>
211
- TypeScriptFactory.createTupleTypeNode(
212
- meta.type!.elements.map((elem) =>
213
- elem.rest
214
- ? TypeScriptFactory.createRestTypeNode(
215
- TypeScriptFactory.createArrayTypeNode(
216
- write(project)(importer)(elem.rest),
217
- ),
218
- )
219
- : elem.optional
220
- ? TypeScriptFactory.createOptionalTypeNode(
221
- write(project)(importer)(elem),
222
- )
223
- : write(project)(importer)(elem),
224
- ),
225
- );
226
-
227
- const write_regular_property =
228
- (project: INestiaProject) =>
229
- (importer: ImportDictionary) =>
230
- (properties: MetadataProperty[]): Node =>
231
- TypeScriptFactory.createTypeLiteralNode(
232
- properties
233
- .map((p) => {
234
- const description: string = writeComment(p.value.atomics)(
235
- p.description,
236
- p.jsDocTags,
237
- );
238
- const signature: Node =
239
- TypeScriptFactory.createPropertySignature(
240
- undefined,
241
- NamingConvention.variable(
242
- String(p.key.constants[0]!.values[0]!.value),
243
- )
244
- ? TypeScriptFactory.createIdentifier(
245
- String(p.key.constants[0]!.values[0]!.value),
246
- )
247
- : TypeScriptFactory.createStringLiteral(
248
- String(p.key.constants[0]!.values[0]!.value),
249
- ),
250
- p.value.required === false
251
- ? TypeScriptFactory.createToken(SyntaxKind.QuestionToken)
252
- : undefined,
253
- SdkTypeProgrammer.write(project)(importer)(p.value),
254
- );
255
- return !!description.length
256
- ? [
257
- TypeScriptFactory.createIdentifier("\n") as any,
258
- FilePrinter.description(signature, description),
259
- ]
260
- : signature;
261
- })
262
- .flat(),
263
- );
264
-
265
- const write_dynamic_property =
266
- (project: INestiaProject) =>
267
- (importer: ImportDictionary) =>
268
- (property: MetadataProperty): Node =>
269
- TypeScriptFactory.createTypeLiteralNode([
270
- FilePrinter.description(
271
- TypeScriptFactory.createIndexSignature(
272
- undefined,
273
- [
274
- TypeScriptFactory.createParameterDeclaration(
275
- undefined,
276
- undefined,
277
- TypeScriptFactory.createIdentifier("key"),
278
- undefined,
279
- SdkTypeProgrammer.write(project)(importer)(property.key),
280
- ),
281
- ],
282
- SdkTypeProgrammer.write(project)(importer)(property.value),
283
- ),
284
- writeComment(property.value.atomics)(
285
- property.description,
286
- property.jsDocTags,
287
- ),
288
- ),
289
- ]);
290
-
291
- const writeAlias =
292
- (project: INestiaProject) =>
293
- (importer: ImportDictionary) =>
294
- (meta: MetadataAliasType | MetadataObjectType): Node => {
295
- importInternalFile(project)(importer)(meta.name);
296
- return TypeScriptFactory.createTypeReferenceNode(meta.name);
297
- };
298
-
299
- const write_native = (name: string): Node =>
300
- TypeScriptFactory.createTypeReferenceNode(name);
301
-
302
- /* -----------------------------------------------------------
303
- MISCELLANEOUS
304
- ----------------------------------------------------------- */
305
- const write_type_tag_matrix =
306
- (importer: ImportDictionary) =>
307
- (
308
- from: "array" | "boolean" | "number" | "bigint" | "string" | "object",
309
- base: Node,
310
- matrix: IMetadataTypeTag[][],
311
- ): Node => {
312
- matrix = matrix.filter((row) => row.length !== 0);
313
- if (matrix.length === 0) return base;
314
- else if (matrix.length === 1)
315
- return TypeScriptFactory.createIntersectionTypeNode([
316
- base,
317
- ...matrix[0]!.map((tag) =>
318
- SdkTypeTagProgrammer.write(importer, from, tag),
319
- ),
320
- ]);
321
- return TypeScriptFactory.createIntersectionTypeNode([
322
- base,
323
- TypeScriptFactory.createUnionTypeNode(
324
- matrix.map((row) =>
325
- row.length === 1
326
- ? SdkTypeTagProgrammer.write(importer, from, row[0]!)
327
- : TypeScriptFactory.createIntersectionTypeNode(
328
- row.map((tag) =>
329
- SdkTypeTagProgrammer.write(importer, from, tag),
330
- ),
331
- ),
332
- ),
333
- ),
334
- ]);
335
- };
336
- }
337
-
338
- const writeNode = (text: string) =>
339
- TypeScriptFactory.createTypeReferenceNode(text);
340
- const writeComment =
341
- (atomics: MetadataAtomic[]) =>
342
- (description: string | null, jsDocTags: IJsDocTagInfo[]): string => {
343
- const lines: string[] = [];
344
- if (description?.length)
345
- lines.push(...description.split("\n").map((s) => `${s}`));
346
-
347
- const filtered: IJsDocTagInfo[] =
348
- !!atomics.length && !!jsDocTags?.length
349
- ? jsDocTags.filter(
350
- (tag) =>
351
- !atomics.some((a) =>
352
- a.tags.some((r) => r.some((t) => t.kind === tag.name)),
353
- ),
354
- )
355
- : (jsDocTags ?? []);
356
-
357
- if (description?.length && filtered.length) lines.push("");
358
- if (filtered.length)
359
- lines.push(
360
- ...filtered.map((t) =>
361
- t.text?.length
362
- ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
363
- : `@${t.name}`,
364
- ),
365
- );
366
- return lines.join("\n");
367
- };
368
-
369
- const importInternalFile =
370
- (project: INestiaProject) =>
371
- (importer: ImportDictionary) =>
372
- (name: string) => {
373
- const top: string = name.split(".")[0]!;
374
- if (importer.file === `${project.config.output}/structures/${top}.ts`)
375
- return;
376
- importer.internal({
377
- declaration: true,
378
- file: `${project.config.output}/structures/${name.split(".")[0]}`,
379
- type: "element",
380
- name: top,
381
- });
382
- };
1
+ import { SyntaxKind, type TypeNode, factory } from "@ttsc/factory";
2
+ import { NamingConvention } from "@typia/utils";
3
+ import { IJsDocTagInfo, IMetadataTypeTag } from "typia";
4
+
5
+ import { ExpressionFactory } from "../../factories/ExpressionFactory";
6
+ import { TypeFactory } from "../../factories/TypeFactory";
7
+ import {
8
+ MetadataAliasType,
9
+ MetadataArray,
10
+ MetadataAtomic,
11
+ MetadataConstantValue,
12
+ MetadataEscaped,
13
+ MetadataObjectType,
14
+ MetadataProperty,
15
+ MetadataSchema,
16
+ MetadataTuple,
17
+ isSoleLiteralOf,
18
+ sizeOf,
19
+ } from "../../internal/legacy";
20
+ import { INestiaProject } from "../../structures/INestiaProject";
21
+ import { FilePrinter } from "./FilePrinter";
22
+ import { ImportDictionary } from "./ImportDictionary";
23
+ import { SdkTypeTagProgrammer } from "./SdkTypeTagProgrammer";
24
+
25
+ export namespace SdkTypeProgrammer {
26
+ /* -----------------------------------------------------------
27
+ FACADE
28
+ ----------------------------------------------------------- */
29
+ export const write =
30
+ (project: INestiaProject) =>
31
+ (importer: ImportDictionary) =>
32
+ (meta: MetadataSchema, parentEscaped: boolean = false): TypeNode => {
33
+ const union: TypeNode[] = [];
34
+
35
+ // COALESCES
36
+ if (meta.any) union.push(TypeFactory.keyword("any"));
37
+ if (meta.nullable) union.push(writeNode("null"));
38
+ if (meta.required === false) union.push(writeNode("undefined"));
39
+ if (parentEscaped === false && meta.escaped)
40
+ union.push(write_escaped(project)(importer)(meta.escaped));
41
+
42
+ // ATOMIC TYPES
43
+ for (const c of meta.constants)
44
+ for (const value of c.values) union.push(write_constant(value));
45
+ for (const tpl of meta.templates)
46
+ union.push(write_template(project)(importer)(tpl.row ?? tpl));
47
+ for (const atom of meta.atomics) union.push(write_atomic(importer)(atom));
48
+
49
+ // OBJECT TYPES
50
+ for (const tuple of meta.tuples)
51
+ union.push(write_tuple(project)(importer)(tuple as MetadataTuple));
52
+ for (const array of meta.arrays)
53
+ union.push(write_array(project)(importer)(array as MetadataArray));
54
+ for (const object of meta.objects) {
55
+ const target = object.type as MetadataObjectType;
56
+ if (
57
+ target.name === "object" ||
58
+ target.name === "__type" ||
59
+ target.name.startsWith("__type.") ||
60
+ target.name === "__object" ||
61
+ target.name.startsWith("__object.")
62
+ )
63
+ union.push(write_object(project)(importer)(target));
64
+ else union.push(writeAlias(project)(importer)(target));
65
+ }
66
+ for (const alias of meta.aliases)
67
+ union.push(
68
+ writeAlias(project)(importer)(alias.type as MetadataAliasType),
69
+ );
70
+ for (const native of meta.natives)
71
+ if (native.name === "Blob" || native.name === "File")
72
+ union.push(write_native(native.name));
73
+
74
+ return union.length === 1
75
+ ? union[0]!
76
+ : factory.createUnionTypeNode(union);
77
+ };
78
+
79
+ export const write_object =
80
+ (project: INestiaProject) =>
81
+ (importer: ImportDictionary) =>
82
+ (object: MetadataObjectType): TypeNode => {
83
+ const regular = object.properties.filter((p) => isSoleLiteralOf(p.key));
84
+ const dynamic = object.properties.filter((p) => !isSoleLiteralOf(p.key));
85
+ return regular.length && dynamic.length
86
+ ? factory.createIntersectionTypeNode([
87
+ write_regular_property(project)(importer)(regular),
88
+ ...dynamic.map(write_dynamic_property(project)(importer)),
89
+ ])
90
+ : dynamic.length
91
+ ? factory.createIntersectionTypeNode(
92
+ dynamic.map(write_dynamic_property(project)(importer)),
93
+ )
94
+ : write_regular_property(project)(importer)(regular);
95
+ };
96
+
97
+ const write_escaped =
98
+ (project: INestiaProject) =>
99
+ (importer: ImportDictionary) =>
100
+ (meta: MetadataEscaped): TypeNode => {
101
+ if (
102
+ sizeOf(meta.original) === 1 &&
103
+ meta.original.natives.length === 1 &&
104
+ meta.original.natives[0]!.name === "Date"
105
+ )
106
+ return factory.createIntersectionTypeNode([
107
+ TypeFactory.keyword("string"),
108
+ SdkTypeTagProgrammer.write(importer, "string", {
109
+ name: "Format",
110
+ value: "date-time",
111
+ } as IMetadataTypeTag),
112
+ ]);
113
+ return write(project)(importer)(meta.returns, true);
114
+ };
115
+
116
+ /* -----------------------------------------------------------
117
+ ATOMICS
118
+ ----------------------------------------------------------- */
119
+ const write_constant = (value: MetadataConstantValue) => {
120
+ if (typeof value.value === "boolean")
121
+ return factory.createLiteralTypeNode(
122
+ value.value ? factory.createTrue() : factory.createFalse(),
123
+ );
124
+ else if (typeof value.value === "bigint")
125
+ return factory.createLiteralTypeNode(
126
+ value.value < BigInt(0)
127
+ ? factory.createPrefixUnaryExpression(
128
+ SyntaxKind.MinusToken,
129
+ factory.createBigIntLiteral((-value.value).toString()),
130
+ )
131
+ : factory.createBigIntLiteral(value.value.toString()),
132
+ );
133
+ else if (typeof value.value === "number")
134
+ return factory.createLiteralTypeNode(
135
+ ExpressionFactory.number(value.value),
136
+ );
137
+ return factory.createLiteralTypeNode(
138
+ factory.createStringLiteral(value.value as string),
139
+ );
140
+ };
141
+
142
+ const write_template =
143
+ (project: INestiaProject) =>
144
+ (importer: ImportDictionary) =>
145
+ (meta: MetadataSchema[]): TypeNode => {
146
+ const head: boolean = isSoleLiteralOf(meta[0]!);
147
+ const spans: [TypeNode | null, string | null][] = [];
148
+ for (const elem of meta.slice(head ? 1 : 0)) {
149
+ const last =
150
+ spans.at(-1) ??
151
+ (() => {
152
+ const tuple = [null!, null!] as [TypeNode | null, string | null];
153
+ spans.push(tuple);
154
+ return tuple;
155
+ })();
156
+ if (isSoleLiteralOf(elem))
157
+ if (last[1] === null)
158
+ last[1] = String(elem.constants[0]!.values[0]!.value);
159
+ else
160
+ spans.push([
161
+ factory.createLiteralTypeNode(
162
+ factory.createStringLiteral(
163
+ String(elem.constants[0]!.values[0]!.value),
164
+ ),
165
+ ),
166
+ null,
167
+ ]);
168
+ else if (last[0] === null) last[0] = write(project)(importer)(elem);
169
+ else spans.push([write(project)(importer)(elem), null]);
170
+ }
171
+ return factory.createTemplateLiteralType(
172
+ factory.createTemplateHead(
173
+ head ? (meta[0]!.constants[0]!.values[0]!.value as string) : "",
174
+ ),
175
+ spans
176
+ .filter(([node]) => node !== null)
177
+ .map(([node, str], i, array) =>
178
+ factory.createTemplateLiteralTypeSpan(
179
+ node!,
180
+ (i !== array.length - 1
181
+ ? factory.createTemplateMiddle
182
+ : factory.createTemplateTail)(str ?? ""),
183
+ ),
184
+ ),
185
+ );
186
+ };
187
+
188
+ const write_atomic =
189
+ (importer: ImportDictionary) =>
190
+ (meta: MetadataAtomic): TypeNode =>
191
+ write_type_tag_matrix(importer)(
192
+ meta.type as "boolean" | "bigint" | "number" | "string",
193
+ factory.createKeywordTypeNode(
194
+ meta.type === "boolean"
195
+ ? SyntaxKind.BooleanKeyword
196
+ : meta.type === "bigint"
197
+ ? SyntaxKind.BigIntKeyword
198
+ : meta.type === "number"
199
+ ? SyntaxKind.NumberKeyword
200
+ : SyntaxKind.StringKeyword,
201
+ ),
202
+ meta.tags,
203
+ );
204
+
205
+ /* -----------------------------------------------------------
206
+ INSTANCES
207
+ ----------------------------------------------------------- */
208
+ const write_array =
209
+ (project: INestiaProject) =>
210
+ (importer: ImportDictionary) =>
211
+ (meta: MetadataArray): TypeNode =>
212
+ write_type_tag_matrix(importer)(
213
+ "array",
214
+ factory.createArrayTypeNode(write(project)(importer)(meta.type!.value)),
215
+ meta.tags,
216
+ );
217
+
218
+ const write_tuple =
219
+ (project: INestiaProject) =>
220
+ (importer: ImportDictionary) =>
221
+ (meta: MetadataTuple): TypeNode =>
222
+ factory.createTupleTypeNode(
223
+ meta.type!.elements.map((elem) =>
224
+ elem.rest
225
+ ? factory.createRestTypeNode(
226
+ factory.createArrayTypeNode(
227
+ write(project)(importer)(elem.rest),
228
+ ),
229
+ )
230
+ : elem.optional
231
+ ? factory.createOptionalTypeNode(write(project)(importer)(elem))
232
+ : write(project)(importer)(elem),
233
+ ),
234
+ );
235
+
236
+ const write_regular_property =
237
+ (project: INestiaProject) =>
238
+ (importer: ImportDictionary) =>
239
+ (properties: MetadataProperty[]): TypeNode =>
240
+ factory.createTypeLiteralNode(
241
+ properties
242
+ .map((p) => {
243
+ const description: string = writeComment(p.value.atomics)(
244
+ p.description,
245
+ p.jsDocTags,
246
+ );
247
+ const signature = factory.createPropertySignature(
248
+ undefined,
249
+ NamingConvention.variable(
250
+ String(p.key.constants[0]!.values[0]!.value),
251
+ )
252
+ ? factory.createIdentifier(
253
+ String(p.key.constants[0]!.values[0]!.value),
254
+ )
255
+ : factory.createStringLiteral(
256
+ String(p.key.constants[0]!.values[0]!.value),
257
+ ),
258
+ p.value.required === false
259
+ ? factory.createToken(SyntaxKind.QuestionToken)
260
+ : undefined,
261
+ SdkTypeProgrammer.write(project)(importer)(p.value),
262
+ );
263
+ return !!description.length
264
+ ? [
265
+ factory.createIdentifier("\n") as any,
266
+ FilePrinter.description(signature, description),
267
+ ]
268
+ : signature;
269
+ })
270
+ .flat(),
271
+ );
272
+
273
+ const write_dynamic_property =
274
+ (project: INestiaProject) =>
275
+ (importer: ImportDictionary) =>
276
+ (property: MetadataProperty): TypeNode =>
277
+ factory.createTypeLiteralNode([
278
+ FilePrinter.description(
279
+ factory.createIndexSignature(
280
+ undefined,
281
+ [
282
+ factory.createParameterDeclaration(
283
+ undefined,
284
+ undefined,
285
+ factory.createIdentifier("key"),
286
+ undefined,
287
+ SdkTypeProgrammer.write(project)(importer)(property.key),
288
+ ),
289
+ ],
290
+ SdkTypeProgrammer.write(project)(importer)(property.value),
291
+ ),
292
+ writeComment(property.value.atomics)(
293
+ property.description,
294
+ property.jsDocTags,
295
+ ),
296
+ ),
297
+ ]);
298
+
299
+ const writeAlias =
300
+ (project: INestiaProject) =>
301
+ (importer: ImportDictionary) =>
302
+ (meta: MetadataAliasType | MetadataObjectType): TypeNode => {
303
+ importInternalFile(project)(importer)(meta.name);
304
+ return factory.createTypeReferenceNode(meta.name);
305
+ };
306
+
307
+ const write_native = (name: string): TypeNode =>
308
+ factory.createTypeReferenceNode(name);
309
+
310
+ /* -----------------------------------------------------------
311
+ MISCELLANEOUS
312
+ ----------------------------------------------------------- */
313
+ const write_type_tag_matrix =
314
+ (importer: ImportDictionary) =>
315
+ (
316
+ from: "array" | "boolean" | "number" | "bigint" | "string" | "object",
317
+ base: TypeNode,
318
+ matrix: IMetadataTypeTag[][],
319
+ ): TypeNode => {
320
+ matrix = matrix.filter((row) => row.length !== 0);
321
+ if (matrix.length === 0) return base;
322
+ else if (matrix.length === 1)
323
+ return factory.createIntersectionTypeNode([
324
+ base,
325
+ ...matrix[0]!.map((tag) =>
326
+ SdkTypeTagProgrammer.write(importer, from, tag),
327
+ ),
328
+ ]);
329
+ return factory.createIntersectionTypeNode([
330
+ base,
331
+ factory.createUnionTypeNode(
332
+ matrix.map((row) =>
333
+ row.length === 1
334
+ ? SdkTypeTagProgrammer.write(importer, from, row[0]!)
335
+ : factory.createIntersectionTypeNode(
336
+ row.map((tag) =>
337
+ SdkTypeTagProgrammer.write(importer, from, tag),
338
+ ),
339
+ ),
340
+ ),
341
+ ),
342
+ ]);
343
+ };
344
+ }
345
+
346
+ const writeNode = (text: string) => factory.createTypeReferenceNode(text);
347
+ const writeComment =
348
+ (atomics: MetadataAtomic[]) =>
349
+ (description: string | null, jsDocTags: IJsDocTagInfo[]): string => {
350
+ const lines: string[] = [];
351
+ if (description?.length)
352
+ lines.push(...description.split("\n").map((s) => `${s}`));
353
+
354
+ const filtered: IJsDocTagInfo[] =
355
+ !!atomics.length && !!jsDocTags?.length
356
+ ? jsDocTags.filter(
357
+ (tag) =>
358
+ !atomics.some((a) =>
359
+ a.tags.some((r) => r.some((t) => t.kind === tag.name)),
360
+ ),
361
+ )
362
+ : (jsDocTags ?? []);
363
+
364
+ if (description?.length && filtered.length) lines.push("");
365
+ if (filtered.length)
366
+ lines.push(
367
+ ...filtered.map((t) =>
368
+ t.text?.length
369
+ ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
370
+ : `@${t.name}`,
371
+ ),
372
+ );
373
+ return lines.join("\n");
374
+ };
375
+
376
+ const importInternalFile =
377
+ (project: INestiaProject) =>
378
+ (importer: ImportDictionary) =>
379
+ (name: string) => {
380
+ const top: string = name.split(".")[0]!;
381
+ if (importer.file === `${project.config.output}/structures/${top}.ts`)
382
+ return;
383
+ importer.internal({
384
+ declaration: true,
385
+ file: `${project.config.output}/structures/${name.split(".")[0]}`,
386
+ type: "element",
387
+ name: top,
388
+ });
389
+ };