@kubb/ast 5.0.0-beta.60 → 5.0.0-beta.62
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.
- package/README.md +2 -1
- package/dist/defineMacro-BryDiuQl.cjs +115 -0
- package/dist/defineMacro-BryDiuQl.cjs.map +1 -0
- package/dist/defineMacro-CNkUpxia.js +99 -0
- package/dist/defineMacro-CNkUpxia.js.map +1 -0
- package/dist/defineMacro-Vw-xQvq7.d.ts +467 -0
- package/dist/factory.cjs +64 -4
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.ts +2 -37
- package/dist/factory.js +58 -3
- package/dist/factory.js.map +1 -0
- package/dist/{index-BzjwdK2M.d.ts → index-CTaN_ee_.d.ts} +235 -198
- package/dist/index.cjs +33 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +36 -36
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/dist/macros.cjs +130 -0
- package/dist/macros.cjs.map +1 -0
- package/dist/macros.d.ts +61 -0
- package/dist/macros.js +128 -0
- package/dist/macros.js.map +1 -0
- package/dist/{operationParams-BZ07xDm0.d.ts → operationParams-B44p6EQy.d.ts} +2 -2
- package/dist/{response-DS5S3IG4.cjs → response-BeG6hq2D.cjs} +389 -173
- package/dist/response-BeG6hq2D.cjs.map +1 -0
- package/dist/{response-DKxTr522.js → response-Rd1uisM1.js} +377 -162
- package/dist/response-Rd1uisM1.js.map +1 -0
- package/dist/types-DQTgVSwE.d.ts +314 -0
- package/dist/types.d.ts +5 -5
- package/dist/{utils-D83JA6Xx.cjs → utils-BDI3kXlb.cjs} +20 -753
- package/dist/utils-BDI3kXlb.cjs.map +1 -0
- package/dist/{utils-Dj_KoXMv.js → utils-DW9rnfsD.js} +11 -630
- package/dist/utils-DW9rnfsD.js.map +1 -0
- package/dist/utils.cjs +11 -9
- package/dist/utils.d.ts +38 -4
- package/dist/utils.js +4 -3
- package/dist/visitor-B7Zlnp4c.cjs +604 -0
- package/dist/visitor-B7Zlnp4c.cjs.map +1 -0
- package/dist/visitor-DepQEKyp.js +510 -0
- package/dist/visitor-DepQEKyp.js.map +1 -0
- package/package.json +5 -1
- package/src/constants.ts +0 -30
- package/src/dedupe.ts +1 -9
- package/src/defineMacro.ts +139 -0
- package/src/{node.ts → defineNode.ts} +19 -42
- package/src/dialect.ts +42 -19
- package/src/factory.ts +3 -90
- package/src/index.ts +9 -15
- package/src/macros/index.ts +3 -0
- package/src/macros/macroDiscriminatorEnum.ts +50 -0
- package/src/macros/macroEnumName.ts +33 -0
- package/src/macros/macroSimplifyUnion.ts +60 -0
- package/src/nodes/code.ts +32 -75
- package/src/nodes/content.ts +2 -7
- package/src/nodes/file.ts +102 -14
- package/src/nodes/function.ts +46 -46
- package/src/nodes/index.ts +2 -3
- package/src/nodes/input.ts +13 -9
- package/src/nodes/operation.ts +5 -5
- package/src/nodes/output.ts +1 -1
- package/src/nodes/parameter.ts +6 -6
- package/src/nodes/property.ts +6 -6
- package/src/nodes/requestBody.ts +6 -13
- package/src/nodes/response.ts +93 -8
- package/src/nodes/schema.ts +1 -1
- package/src/registry.ts +1 -1
- package/src/types.ts +4 -4
- package/src/utils/extractStringsFromNodes.ts +1 -0
- package/src/utils/index.ts +2 -2
- package/src/utils/operationParams.ts +1 -1
- package/src/utils/refs.ts +27 -1
- package/src/utils/schemaMerge.ts +34 -0
- package/src/visitor.ts +2 -13
- package/dist/extractStringsFromNodes-WMYJ8nQL.d.ts +0 -82
- package/dist/factory-Cl8Z7mcc.cjs +0 -299
- package/dist/factory-Cl8Z7mcc.cjs.map +0 -1
- package/dist/factory-Du7nEP4B.js +0 -282
- package/dist/factory-Du7nEP4B.js.map +0 -1
- package/dist/response-DKxTr522.js.map +0 -1
- package/dist/response-DS5S3IG4.cjs.map +0 -1
- package/dist/types-olVl9v5p.d.ts +0 -764
- package/dist/utils-D83JA6Xx.cjs.map +0 -1
- package/dist/utils-Dj_KoXMv.js.map +0 -1
- package/src/mocks.ts +0 -56
- package/src/nodes/http.ts +0 -85
- package/src/transformers.ts +0 -191
- /package/src/{printer.ts → definePrinter.ts} +0 -0
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import "./chunk-CNktS9qV.js";
|
|
2
|
-
|
|
2
|
+
import { hash } from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
//#region src/defineNode.ts
|
|
5
|
+
/**
|
|
6
|
+
* Visitor callback names, one per traversable node kind, in traversal order.
|
|
7
|
+
* Kept in sync with the keys of `Visitor` in `visitor.ts`.
|
|
8
|
+
*/
|
|
9
|
+
const visitorKeys = [
|
|
10
|
+
"input",
|
|
11
|
+
"output",
|
|
12
|
+
"operation",
|
|
13
|
+
"schema",
|
|
14
|
+
"property",
|
|
15
|
+
"parameter",
|
|
16
|
+
"response"
|
|
17
|
+
];
|
|
3
18
|
/**
|
|
4
19
|
* Builds a type guard that matches nodes of the given `kind`.
|
|
5
20
|
*/
|
|
@@ -7,52 +22,30 @@ function isKind(kind) {
|
|
|
7
22
|
return (node) => node.kind === kind;
|
|
8
23
|
}
|
|
9
24
|
/**
|
|
10
|
-
* Updates a schema's `optional` and `nullish` flags from a parent's `required`
|
|
11
|
-
* value and the schema's own `nullable`. Mirrors how OpenAPI parameters and
|
|
12
|
-
* object properties combine "required" and "nullable" into a single AST.
|
|
13
|
-
*
|
|
14
|
-
* - Non-required + non-nullable → `optional: true`.
|
|
15
|
-
* - Non-required + nullable → `nullish: true`.
|
|
16
|
-
* - Required → both flags cleared.
|
|
17
|
-
*/
|
|
18
|
-
function syncOptionality(schema, required) {
|
|
19
|
-
const nullable = schema.nullable ?? false;
|
|
20
|
-
return {
|
|
21
|
-
...schema,
|
|
22
|
-
optional: !required && !nullable ? true : void 0,
|
|
23
|
-
nullish: !required && nullable ? true : void 0
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
25
|
* Defines a node once and derives its `create` builder, `is` guard, and traversal
|
|
28
26
|
* metadata. `create` merges `defaults`, the `build` hook (or the raw input), and the
|
|
29
27
|
* `kind`, so node construction lives in one place without scattered `as` casts.
|
|
30
28
|
*
|
|
31
|
-
* Set `rebuild: true` when the `build` hook derives fields from children. After a
|
|
32
|
-
* transform rewrites those children, the registry reruns `create` so the derived
|
|
33
|
-
* fields stay correct.
|
|
34
|
-
*
|
|
35
29
|
* @example Simple node
|
|
36
30
|
* ```ts
|
|
37
31
|
* const importDef = defineNode<ImportNode>({ kind: 'Import' })
|
|
38
32
|
* const createImport = importDef.create
|
|
39
33
|
* ```
|
|
40
34
|
*
|
|
41
|
-
* @example Node with a build hook
|
|
35
|
+
* @example Node with a build hook
|
|
42
36
|
* ```ts
|
|
43
37
|
* const propertyDef = defineNode<PropertyNode, UserPropertyNode>({
|
|
44
38
|
* kind: 'Property',
|
|
45
39
|
* build: (props) => ({ ...props, required: props.required ?? false }),
|
|
46
40
|
* children: ['schema'],
|
|
47
41
|
* visitorKey: 'property',
|
|
48
|
-
* rebuild: true,
|
|
49
42
|
* })
|
|
50
43
|
* ```
|
|
51
44
|
*/
|
|
52
45
|
function defineNode(config) {
|
|
53
|
-
const { kind, defaults, build, children, visitorKey
|
|
54
|
-
function create(input) {
|
|
55
|
-
const base = build ? build(input) : input;
|
|
46
|
+
const { kind, defaults, build, children, visitorKey } = config;
|
|
47
|
+
function create(input, dialect) {
|
|
48
|
+
const base = build ? build(input, dialect) : input;
|
|
56
49
|
return {
|
|
57
50
|
...defaults,
|
|
58
51
|
...base,
|
|
@@ -64,8 +57,7 @@ function defineNode(config) {
|
|
|
64
57
|
create,
|
|
65
58
|
is: isKind(kind),
|
|
66
59
|
children,
|
|
67
|
-
visitorKey
|
|
68
|
-
rebuild
|
|
60
|
+
visitorKey
|
|
69
61
|
};
|
|
70
62
|
}
|
|
71
63
|
//#endregion
|
|
@@ -163,6 +155,23 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
|
163
155
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
164
156
|
}
|
|
165
157
|
//#endregion
|
|
158
|
+
//#region ../../internals/utils/src/fs.ts
|
|
159
|
+
/**
|
|
160
|
+
* Strips the file extension from a path or file name.
|
|
161
|
+
* Only removes the last `.ext` segment when the dot is not part of a directory name.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* trimExtName('petStore.ts') // 'petStore'
|
|
165
|
+
* trimExtName('/src/models/pet.ts') // '/src/models/pet'
|
|
166
|
+
* trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
|
|
167
|
+
* trimExtName('noExtension') // 'noExtension'
|
|
168
|
+
*/
|
|
169
|
+
function trimExtName(text) {
|
|
170
|
+
const dotIndex = text.lastIndexOf(".");
|
|
171
|
+
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
172
|
+
return text;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
166
175
|
//#region src/utils/extractStringsFromNodes.ts
|
|
167
176
|
/**
|
|
168
177
|
* Extracts all string content from a `CodeNode` tree recursively.
|
|
@@ -188,45 +197,44 @@ function extractStringsFromNodes(nodes) {
|
|
|
188
197
|
}).filter(Boolean).join("\n");
|
|
189
198
|
}
|
|
190
199
|
//#endregion
|
|
191
|
-
//#region src/nodes/
|
|
200
|
+
//#region src/nodes/code.ts
|
|
192
201
|
/**
|
|
193
|
-
* Definition for the {@link
|
|
194
|
-
* schema's `optional`/`nullish` flags are kept in sync with it.
|
|
202
|
+
* Definition for the {@link ConstNode}.
|
|
195
203
|
*/
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
const constDef = defineNode({ kind: "Const" });
|
|
205
|
+
/**
|
|
206
|
+
* Definition for the {@link TypeNode}.
|
|
207
|
+
*/
|
|
208
|
+
const typeDef = defineNode({ kind: "Type" });
|
|
209
|
+
/**
|
|
210
|
+
* Definition for the {@link FunctionNode}.
|
|
211
|
+
*/
|
|
212
|
+
const functionDef = defineNode({ kind: "Function" });
|
|
213
|
+
/**
|
|
214
|
+
* Definition for the {@link ArrowFunctionNode}.
|
|
215
|
+
*/
|
|
216
|
+
const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
|
|
217
|
+
/**
|
|
218
|
+
* Definition for the {@link TextNode}.
|
|
219
|
+
*/
|
|
220
|
+
const textDef = defineNode({
|
|
221
|
+
kind: "Text",
|
|
222
|
+
build: (value) => ({ value })
|
|
209
223
|
});
|
|
210
224
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* @example
|
|
214
|
-
* ```ts
|
|
215
|
-
* const property = createProperty({
|
|
216
|
-
* name: 'status',
|
|
217
|
-
* required: true,
|
|
218
|
-
* schema: createSchema({ type: 'string', nullable: true }),
|
|
219
|
-
* })
|
|
220
|
-
* // required=true, no optional/nullish
|
|
221
|
-
* ```
|
|
225
|
+
* Definition for the {@link BreakNode}.
|
|
222
226
|
*/
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
227
|
+
const breakDef = defineNode({
|
|
228
|
+
kind: "Break",
|
|
229
|
+
build: () => ({})
|
|
230
|
+
});
|
|
226
231
|
/**
|
|
227
|
-
* Definition for the {@link
|
|
232
|
+
* Definition for the {@link JsxNode}.
|
|
228
233
|
*/
|
|
229
|
-
const
|
|
234
|
+
const jsxDef = defineNode({
|
|
235
|
+
kind: "Jsx",
|
|
236
|
+
build: (value) => ({ value })
|
|
237
|
+
});
|
|
230
238
|
/**
|
|
231
239
|
* Creates a `ConstNode` representing a TypeScript `const` declaration.
|
|
232
240
|
*
|
|
@@ -238,10 +246,6 @@ const constDef = defineNode({ kind: "Const" });
|
|
|
238
246
|
*/
|
|
239
247
|
const createConst = constDef.create;
|
|
240
248
|
/**
|
|
241
|
-
* Definition for the {@link TypeNode}.
|
|
242
|
-
*/
|
|
243
|
-
const typeDef = defineNode({ kind: "Type" });
|
|
244
|
-
/**
|
|
245
249
|
* Creates a `TypeNode` representing a TypeScript `type` alias declaration.
|
|
246
250
|
*
|
|
247
251
|
* @example
|
|
@@ -252,10 +256,6 @@ const typeDef = defineNode({ kind: "Type" });
|
|
|
252
256
|
*/
|
|
253
257
|
const createType = typeDef.create;
|
|
254
258
|
/**
|
|
255
|
-
* Definition for the {@link FunctionNode}.
|
|
256
|
-
*/
|
|
257
|
-
const functionDef = defineNode({ kind: "Function" });
|
|
258
|
-
/**
|
|
259
259
|
* Creates a `FunctionNode` representing a TypeScript `function` declaration.
|
|
260
260
|
*
|
|
261
261
|
* @example
|
|
@@ -266,10 +266,6 @@ const functionDef = defineNode({ kind: "Function" });
|
|
|
266
266
|
*/
|
|
267
267
|
const createFunction = functionDef.create;
|
|
268
268
|
/**
|
|
269
|
-
* Definition for the {@link ArrowFunctionNode}.
|
|
270
|
-
*/
|
|
271
|
-
const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
|
|
272
|
-
/**
|
|
273
269
|
* Creates an `ArrowFunctionNode` representing a TypeScript arrow function.
|
|
274
270
|
*
|
|
275
271
|
* @example
|
|
@@ -280,13 +276,6 @@ const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
|
|
|
280
276
|
*/
|
|
281
277
|
const createArrowFunction = arrowFunctionDef.create;
|
|
282
278
|
/**
|
|
283
|
-
* Definition for the {@link TextNode}.
|
|
284
|
-
*/
|
|
285
|
-
const textDef = defineNode({
|
|
286
|
-
kind: "Text",
|
|
287
|
-
build: (value) => ({ value })
|
|
288
|
-
});
|
|
289
|
-
/**
|
|
290
279
|
* Creates a {@link TextNode} representing a raw string fragment in the source output.
|
|
291
280
|
*
|
|
292
281
|
* @example
|
|
@@ -297,13 +286,6 @@ const textDef = defineNode({
|
|
|
297
286
|
*/
|
|
298
287
|
const createText = textDef.create;
|
|
299
288
|
/**
|
|
300
|
-
* Definition for the {@link BreakNode}.
|
|
301
|
-
*/
|
|
302
|
-
const breakDef = defineNode({
|
|
303
|
-
kind: "Break",
|
|
304
|
-
build: () => ({})
|
|
305
|
-
});
|
|
306
|
-
/**
|
|
307
289
|
* Creates a {@link BreakNode} representing a line break in the source output.
|
|
308
290
|
*
|
|
309
291
|
* @example
|
|
@@ -316,13 +298,6 @@ function createBreak() {
|
|
|
316
298
|
return breakDef.create();
|
|
317
299
|
}
|
|
318
300
|
/**
|
|
319
|
-
* Definition for the {@link JsxNode}.
|
|
320
|
-
*/
|
|
321
|
-
const jsxDef = defineNode({
|
|
322
|
-
kind: "Jsx",
|
|
323
|
-
build: (value) => ({ value })
|
|
324
|
-
});
|
|
325
|
-
/**
|
|
326
301
|
* Creates a {@link JsxNode} representing a raw JSX fragment in the source output.
|
|
327
302
|
*
|
|
328
303
|
* @example
|
|
@@ -346,12 +321,171 @@ const contentDef = defineNode({
|
|
|
346
321
|
*/
|
|
347
322
|
const createContent = contentDef.create;
|
|
348
323
|
//#endregion
|
|
324
|
+
//#region src/utils/fileMerge.ts
|
|
325
|
+
function sourceKey(source) {
|
|
326
|
+
return `${source.name ?? extractStringsFromNodes(source.nodes)}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`;
|
|
327
|
+
}
|
|
328
|
+
function pathTypeKey(path, isTypeOnly) {
|
|
329
|
+
return `${path}:${isTypeOnly ?? false}`;
|
|
330
|
+
}
|
|
331
|
+
function exportKey(path, name, isTypeOnly, asAlias) {
|
|
332
|
+
return `${path}:${name ?? ""}:${isTypeOnly ?? false}:${asAlias ?? ""}`;
|
|
333
|
+
}
|
|
334
|
+
function importKey(path, name, isTypeOnly) {
|
|
335
|
+
return `${path}:${name ?? ""}:${isTypeOnly ?? false}`;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Computes a multi-level sort key for exports and imports:
|
|
339
|
+
* non-array names first (wildcards/namespace aliases). Type-only before value. Alphabetical path. Unnamed before named.
|
|
340
|
+
*/
|
|
341
|
+
function sortKey(node) {
|
|
342
|
+
const isArray = Array.isArray(node.name) ? "1" : "0";
|
|
343
|
+
const typeOnly = node.isTypeOnly ? "0" : "1";
|
|
344
|
+
const hasName = node.name != null ? "1" : "0";
|
|
345
|
+
const name = Array.isArray(node.name) ? node.name.toSorted().join("\0") : node.name ?? "";
|
|
346
|
+
return `${isArray}:${typeOnly}:${node.path}:${hasName}:${name}`;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Deduplicates and merges `SourceNode` objects by `name + isExportable + isTypeOnly`.
|
|
350
|
+
*
|
|
351
|
+
* Unnamed sources are deduplicated by object reference. Returns a deduplicated array in original order.
|
|
352
|
+
*/
|
|
353
|
+
function combineSources(sources) {
|
|
354
|
+
const seen = /* @__PURE__ */ new Map();
|
|
355
|
+
for (const source of sources) {
|
|
356
|
+
const key = sourceKey(source);
|
|
357
|
+
if (!seen.has(key)) seen.set(key, source);
|
|
358
|
+
}
|
|
359
|
+
return [...seen.values()];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Merges `incoming` names into `existing`, preserving order and dropping duplicates.
|
|
363
|
+
*
|
|
364
|
+
* Shared by `combineExports` and `combineImports` for the same-path name-merge case.
|
|
365
|
+
*/
|
|
366
|
+
function mergeNameArrays(existing, incoming) {
|
|
367
|
+
const merged = new Set(existing);
|
|
368
|
+
for (const name of incoming) merged.add(name);
|
|
369
|
+
return [...merged];
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Deduplicates and merges `ExportNode` objects by path and type.
|
|
373
|
+
*
|
|
374
|
+
* Named exports with the same path and `isTypeOnly` flag have their names merged into a single export.
|
|
375
|
+
* Non-array exports are deduplicated by exact identity. Returns a sorted, deduplicated array.
|
|
376
|
+
*/
|
|
377
|
+
function combineExports(exports) {
|
|
378
|
+
const result = [];
|
|
379
|
+
const namedByPath = /* @__PURE__ */ new Map();
|
|
380
|
+
const seen = /* @__PURE__ */ new Set();
|
|
381
|
+
const keyed = exports.map((node) => ({
|
|
382
|
+
node,
|
|
383
|
+
key: sortKey(node)
|
|
384
|
+
}));
|
|
385
|
+
keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
386
|
+
for (const { node: curr } of keyed) {
|
|
387
|
+
const { name, path, isTypeOnly, asAlias } = curr;
|
|
388
|
+
if (Array.isArray(name)) {
|
|
389
|
+
if (!name.length) continue;
|
|
390
|
+
const key = pathTypeKey(path, isTypeOnly);
|
|
391
|
+
const existing = namedByPath.get(key);
|
|
392
|
+
if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
|
|
393
|
+
else {
|
|
394
|
+
const newItem = {
|
|
395
|
+
...curr,
|
|
396
|
+
name: [...new Set(name)]
|
|
397
|
+
};
|
|
398
|
+
result.push(newItem);
|
|
399
|
+
namedByPath.set(key, newItem);
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
const key = exportKey(path, name, isTypeOnly, asAlias);
|
|
403
|
+
if (!seen.has(key)) {
|
|
404
|
+
result.push(curr);
|
|
405
|
+
seen.add(key);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Deduplicates and merges `ImportNode` objects, filtering out unused imports.
|
|
413
|
+
*
|
|
414
|
+
* Retains imports that are referenced in `source` or re-exported. Imports with the same path and
|
|
415
|
+
* `isTypeOnly` flag have their names merged. Returns a sorted, deduplicated, filtered array.
|
|
416
|
+
*/
|
|
417
|
+
function combineImports(imports, exports, source) {
|
|
418
|
+
const exportedNames = new Set(exports.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
|
|
419
|
+
const isUsed = (importName) => !source || source.includes(importName) || exportedNames.has(importName);
|
|
420
|
+
const importNameMemo = /* @__PURE__ */ new Map();
|
|
421
|
+
const canonicalizeName = (n) => {
|
|
422
|
+
if (typeof n === "string") return n;
|
|
423
|
+
const key = `${n.propertyName}:${n.name ?? ""}`;
|
|
424
|
+
if (!importNameMemo.has(key)) importNameMemo.set(key, n);
|
|
425
|
+
return importNameMemo.get(key);
|
|
426
|
+
};
|
|
427
|
+
const pathsWithUsedNamedImport = /* @__PURE__ */ new Set();
|
|
428
|
+
for (const node of imports) {
|
|
429
|
+
if (!Array.isArray(node.name)) continue;
|
|
430
|
+
if (node.name.some((item) => typeof item === "string" ? isUsed(item) : isUsed(item.name ?? item.propertyName))) pathsWithUsedNamedImport.add(node.path);
|
|
431
|
+
}
|
|
432
|
+
const result = [];
|
|
433
|
+
const namedByPath = /* @__PURE__ */ new Map();
|
|
434
|
+
const seen = /* @__PURE__ */ new Set();
|
|
435
|
+
const keyed = imports.map((node) => ({
|
|
436
|
+
node,
|
|
437
|
+
key: sortKey(node)
|
|
438
|
+
}));
|
|
439
|
+
keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
440
|
+
for (const { node: curr } of keyed) {
|
|
441
|
+
if (curr.path === curr.root) continue;
|
|
442
|
+
const { path, isTypeOnly } = curr;
|
|
443
|
+
let { name } = curr;
|
|
444
|
+
if (Array.isArray(name)) {
|
|
445
|
+
name = [...new Set(name.map(canonicalizeName))].filter((item) => typeof item === "string" ? isUsed(item) : isUsed(item.name ?? item.propertyName));
|
|
446
|
+
if (!name.length) continue;
|
|
447
|
+
const key = pathTypeKey(path, isTypeOnly);
|
|
448
|
+
const existing = namedByPath.get(key);
|
|
449
|
+
if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
|
|
450
|
+
else {
|
|
451
|
+
const newItem = {
|
|
452
|
+
...curr,
|
|
453
|
+
name
|
|
454
|
+
};
|
|
455
|
+
result.push(newItem);
|
|
456
|
+
namedByPath.set(key, newItem);
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
if (name && !isUsed(name) && !pathsWithUsedNamedImport.has(path)) continue;
|
|
460
|
+
const key = importKey(path, name, isTypeOnly);
|
|
461
|
+
if (!seen.has(key)) {
|
|
462
|
+
result.push(curr);
|
|
463
|
+
seen.add(key);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
//#endregion
|
|
349
470
|
//#region src/nodes/file.ts
|
|
350
471
|
/**
|
|
351
472
|
* Definition for the {@link ImportNode}.
|
|
352
473
|
*/
|
|
353
474
|
const importDef = defineNode({ kind: "Import" });
|
|
354
475
|
/**
|
|
476
|
+
* Definition for the {@link ExportNode}.
|
|
477
|
+
*/
|
|
478
|
+
const exportDef = defineNode({ kind: "Export" });
|
|
479
|
+
/**
|
|
480
|
+
* Definition for the {@link SourceNode}.
|
|
481
|
+
*/
|
|
482
|
+
const sourceDef = defineNode({ kind: "Source" });
|
|
483
|
+
/**
|
|
484
|
+
* Definition for the {@link FileNode}. The fully resolved builder lives in
|
|
485
|
+
* `createFile`, so this definition only supplies the guard.
|
|
486
|
+
*/
|
|
487
|
+
const fileDef = defineNode({ kind: "File" });
|
|
488
|
+
/**
|
|
355
489
|
* Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
|
|
356
490
|
*
|
|
357
491
|
* @example Named import
|
|
@@ -362,10 +496,6 @@ const importDef = defineNode({ kind: "Import" });
|
|
|
362
496
|
*/
|
|
363
497
|
const createImport = importDef.create;
|
|
364
498
|
/**
|
|
365
|
-
* Definition for the {@link ExportNode}.
|
|
366
|
-
*/
|
|
367
|
-
const exportDef = defineNode({ kind: "Export" });
|
|
368
|
-
/**
|
|
369
499
|
* Creates an `ExportNode` representing a language-agnostic export/public API declaration.
|
|
370
500
|
*
|
|
371
501
|
* @example Named export
|
|
@@ -376,10 +506,6 @@ const exportDef = defineNode({ kind: "Export" });
|
|
|
376
506
|
*/
|
|
377
507
|
const createExport = exportDef.create;
|
|
378
508
|
/**
|
|
379
|
-
* Definition for the {@link SourceNode}.
|
|
380
|
-
*/
|
|
381
|
-
const sourceDef = defineNode({ kind: "Source" });
|
|
382
|
-
/**
|
|
383
509
|
* Creates a `SourceNode` representing a fragment of source code within a file.
|
|
384
510
|
*
|
|
385
511
|
* @example
|
|
@@ -389,10 +515,64 @@ const sourceDef = defineNode({ kind: "Source" });
|
|
|
389
515
|
*/
|
|
390
516
|
const createSource = sourceDef.create;
|
|
391
517
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
518
|
+
* Creates a fully resolved `FileNode` from a file input descriptor.
|
|
519
|
+
*
|
|
520
|
+
* Computes:
|
|
521
|
+
* - `id` SHA256 hash of the file path
|
|
522
|
+
* - `name` `baseName` without extension
|
|
523
|
+
* - `extname` extension extracted from `baseName`
|
|
524
|
+
*
|
|
525
|
+
* Deduplicates:
|
|
526
|
+
* - `sources` via `combineSources`
|
|
527
|
+
* - `exports` via `combineExports`
|
|
528
|
+
* - `imports` via `combineImports` (also filters unused imports)
|
|
529
|
+
*
|
|
530
|
+
* @throws {Error} when `baseName` has no extension.
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* const file = createFile({
|
|
535
|
+
* baseName: 'petStore.ts',
|
|
536
|
+
* path: 'src/models/petStore.ts',
|
|
537
|
+
* sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],
|
|
538
|
+
* imports: [createImport({ name: ['z'], path: 'zod' })],
|
|
539
|
+
* exports: [createExport({ name: ['Pet'], path: './petStore' })],
|
|
540
|
+
* })
|
|
541
|
+
* // file.id = SHA256 hash of 'src/models/petStore.ts'
|
|
542
|
+
* // file.name = 'petStore'
|
|
543
|
+
* // file.extname = '.ts'
|
|
544
|
+
* ```
|
|
394
545
|
*/
|
|
395
|
-
|
|
546
|
+
function createFile(input) {
|
|
547
|
+
const extname = path.extname(input.baseName) || (input.baseName.startsWith(".") ? input.baseName : "");
|
|
548
|
+
if (!extname) throw new Error(`No extname found for ${input.baseName}`);
|
|
549
|
+
const source = (input.sources ?? []).flatMap((item) => item.nodes ?? []).map((node) => extractStringsFromNodes([node])).filter(Boolean).join("\n\n");
|
|
550
|
+
const resolvedExports = input.exports?.length ? combineExports(input.exports) : [];
|
|
551
|
+
const combinedImports = input.imports?.length ? combineImports(input.imports, resolvedExports, source || void 0) : [];
|
|
552
|
+
const localNames = new Set((input.sources ?? []).map((item) => item.name).filter((name) => Boolean(name)));
|
|
553
|
+
const nameOf = (item) => typeof item === "string" ? item : item.name ?? item.propertyName;
|
|
554
|
+
const resolvedImports = combinedImports.filter((imp) => imp.path !== input.path).flatMap((imp) => {
|
|
555
|
+
if (!Array.isArray(imp.name)) return typeof imp.name === "string" && localNames.has(imp.name) ? [] : [imp];
|
|
556
|
+
const kept = imp.name.filter((item) => !localNames.has(nameOf(item)));
|
|
557
|
+
if (!kept.length) return [];
|
|
558
|
+
return [kept.length === imp.name.length ? imp : {
|
|
559
|
+
...imp,
|
|
560
|
+
name: kept
|
|
561
|
+
}];
|
|
562
|
+
});
|
|
563
|
+
const resolvedSources = input.sources?.length ? combineSources(input.sources) : [];
|
|
564
|
+
return {
|
|
565
|
+
kind: "File",
|
|
566
|
+
...input,
|
|
567
|
+
id: hash("sha256", input.path, "hex"),
|
|
568
|
+
name: trimExtName(input.baseName),
|
|
569
|
+
extname,
|
|
570
|
+
imports: resolvedImports,
|
|
571
|
+
exports: resolvedExports,
|
|
572
|
+
sources: resolvedSources,
|
|
573
|
+
meta: input.meta ?? {}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
396
576
|
//#endregion
|
|
397
577
|
//#region src/nodes/function.ts
|
|
398
578
|
/**
|
|
@@ -400,44 +580,14 @@ const fileDef = defineNode({ kind: "File" });
|
|
|
400
580
|
*/
|
|
401
581
|
const typeLiteralDef = defineNode({ kind: "TypeLiteral" });
|
|
402
582
|
/**
|
|
403
|
-
* Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
|
|
404
|
-
*
|
|
405
|
-
* @example
|
|
406
|
-
* ```ts
|
|
407
|
-
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
408
|
-
* // { petId: string }
|
|
409
|
-
* ```
|
|
410
|
-
*/
|
|
411
|
-
const createTypeLiteral = typeLiteralDef.create;
|
|
412
|
-
/**
|
|
413
583
|
* Definition for the {@link IndexedAccessTypeNode}.
|
|
414
584
|
*/
|
|
415
585
|
const indexedAccessTypeDef = defineNode({ kind: "IndexedAccessType" });
|
|
416
586
|
/**
|
|
417
|
-
* Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
|
|
418
|
-
*
|
|
419
|
-
* @example
|
|
420
|
-
* ```ts
|
|
421
|
-
* createIndexedAccessType({ objectType: 'DeletePetPathParams', indexType: 'petId' })
|
|
422
|
-
* // DeletePetPathParams['petId']
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
const createIndexedAccessType = indexedAccessTypeDef.create;
|
|
426
|
-
/**
|
|
427
587
|
* Definition for the {@link ObjectBindingPatternNode}.
|
|
428
588
|
*/
|
|
429
589
|
const objectBindingPatternDef = defineNode({ kind: "ObjectBindingPattern" });
|
|
430
590
|
/**
|
|
431
|
-
* Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
|
|
432
|
-
*
|
|
433
|
-
* @example
|
|
434
|
-
* ```ts
|
|
435
|
-
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
436
|
-
* // { id, name }
|
|
437
|
-
* ```
|
|
438
|
-
*/
|
|
439
|
-
const createObjectBindingPattern = objectBindingPatternDef.create;
|
|
440
|
-
/**
|
|
441
591
|
* Definition for the {@link FunctionParameterNode}. `optional` defaults to `false`.
|
|
442
592
|
* Passing `properties` builds a destructured group: an {@link ObjectBindingPatternNode} name
|
|
443
593
|
* paired with a {@link TypeLiteralNode} type.
|
|
@@ -462,6 +612,43 @@ const functionParameterDef = defineNode({
|
|
|
462
612
|
}
|
|
463
613
|
});
|
|
464
614
|
/**
|
|
615
|
+
* Definition for the {@link FunctionParametersNode}.
|
|
616
|
+
*/
|
|
617
|
+
const functionParametersDef = defineNode({
|
|
618
|
+
kind: "FunctionParameters",
|
|
619
|
+
defaults: { params: [] }
|
|
620
|
+
});
|
|
621
|
+
/**
|
|
622
|
+
* Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* ```ts
|
|
626
|
+
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
627
|
+
* // { petId: string }
|
|
628
|
+
* ```
|
|
629
|
+
*/
|
|
630
|
+
const createTypeLiteral = typeLiteralDef.create;
|
|
631
|
+
/**
|
|
632
|
+
* Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* ```ts
|
|
636
|
+
* createIndexedAccessType({ target: 'DeletePetPathParams', key: 'petId' })
|
|
637
|
+
* // DeletePetPathParams['petId']
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
const createIndexedAccessType = indexedAccessTypeDef.create;
|
|
641
|
+
/**
|
|
642
|
+
* Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
|
|
643
|
+
*
|
|
644
|
+
* @example
|
|
645
|
+
* ```ts
|
|
646
|
+
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
647
|
+
* // { id, name }
|
|
648
|
+
* ```
|
|
649
|
+
*/
|
|
650
|
+
const createObjectBindingPattern = objectBindingPatternDef.create;
|
|
651
|
+
/**
|
|
465
652
|
* Creates a `FunctionParameterNode`. `optional` defaults to `false`.
|
|
466
653
|
*
|
|
467
654
|
* @example Optional param
|
|
@@ -478,13 +665,6 @@ const functionParameterDef = defineNode({
|
|
|
478
665
|
*/
|
|
479
666
|
const createFunctionParameter = functionParameterDef.create;
|
|
480
667
|
/**
|
|
481
|
-
* Definition for the {@link FunctionParametersNode}.
|
|
482
|
-
*/
|
|
483
|
-
const functionParametersDef = defineNode({
|
|
484
|
-
kind: "FunctionParameters",
|
|
485
|
-
defaults: { params: [] }
|
|
486
|
-
});
|
|
487
|
-
/**
|
|
488
668
|
* Creates a `FunctionParametersNode` from an ordered list of parameters.
|
|
489
669
|
*
|
|
490
670
|
* @example
|
|
@@ -516,8 +696,8 @@ const inputDef = defineNode({
|
|
|
516
696
|
});
|
|
517
697
|
/**
|
|
518
698
|
* Creates an `InputNode`. Pass `stream: true` for the streaming variant whose `schemas` and
|
|
519
|
-
* `operations` are `AsyncIterable` sources
|
|
520
|
-
*
|
|
699
|
+
* `operations` are `AsyncIterable` sources. Otherwise it builds the eager variant with array
|
|
700
|
+
* `schemas`/`operations`. Both variants get the defaulted `meta`.
|
|
521
701
|
*
|
|
522
702
|
* @example Eager
|
|
523
703
|
* ```ts
|
|
@@ -534,6 +714,10 @@ function createInput(options = {}) {
|
|
|
534
714
|
const { stream, ...overrides } = options;
|
|
535
715
|
if (stream) return {
|
|
536
716
|
kind: "Input",
|
|
717
|
+
meta: {
|
|
718
|
+
circularNames: [],
|
|
719
|
+
enumNames: []
|
|
720
|
+
},
|
|
537
721
|
...overrides
|
|
538
722
|
};
|
|
539
723
|
return inputDef.create(overrides);
|
|
@@ -541,18 +725,15 @@ function createInput(options = {}) {
|
|
|
541
725
|
//#endregion
|
|
542
726
|
//#region src/nodes/requestBody.ts
|
|
543
727
|
/**
|
|
544
|
-
* Definition for the {@link RequestBodyNode}
|
|
728
|
+
* Definition for the {@link RequestBodyNode}. Content entries are built upfront with
|
|
729
|
+
* {@link createContent}, mirroring how `parameters` and `responses` take prebuilt nodes.
|
|
545
730
|
*/
|
|
546
731
|
const requestBodyDef = defineNode({
|
|
547
732
|
kind: "RequestBody",
|
|
548
|
-
build: (props) => ({
|
|
549
|
-
...props,
|
|
550
|
-
content: props.content?.map(createContent)
|
|
551
|
-
}),
|
|
552
733
|
children: ["content"]
|
|
553
734
|
});
|
|
554
735
|
/**
|
|
555
|
-
* Creates a `RequestBodyNode
|
|
736
|
+
* Creates a `RequestBodyNode`.
|
|
556
737
|
*/
|
|
557
738
|
const createRequestBody = requestBodyDef.create;
|
|
558
739
|
//#endregion
|
|
@@ -611,22 +792,22 @@ function createOutput(overrides = {}) {
|
|
|
611
792
|
//#endregion
|
|
612
793
|
//#region src/nodes/parameter.ts
|
|
613
794
|
/**
|
|
614
|
-
* Definition for the {@link ParameterNode}. `required` defaults to `false`
|
|
615
|
-
* schema's `optional`/`nullish` flags are
|
|
795
|
+
* Definition for the {@link ParameterNode}. `required` defaults to `false`. When a `dialect` is
|
|
796
|
+
* passed to `create`, the schema's `optional`/`nullish` flags are derived through its
|
|
797
|
+
* `optionality`; without one, the schema is left as-is.
|
|
616
798
|
*/
|
|
617
799
|
const parameterDef = defineNode({
|
|
618
800
|
kind: "Parameter",
|
|
619
|
-
build: (props) => {
|
|
801
|
+
build: (props, dialect) => {
|
|
620
802
|
const required = props.required ?? false;
|
|
621
803
|
return {
|
|
622
804
|
...props,
|
|
623
805
|
required,
|
|
624
|
-
schema:
|
|
806
|
+
schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
|
|
625
807
|
};
|
|
626
808
|
},
|
|
627
809
|
children: ["schema"],
|
|
628
|
-
visitorKey: "parameter"
|
|
629
|
-
rebuild: true
|
|
810
|
+
visitorKey: "parameter"
|
|
630
811
|
});
|
|
631
812
|
/**
|
|
632
813
|
* Creates a `ParameterNode`.
|
|
@@ -643,6 +824,40 @@ const parameterDef = defineNode({
|
|
|
643
824
|
*/
|
|
644
825
|
const createParameter = parameterDef.create;
|
|
645
826
|
//#endregion
|
|
827
|
+
//#region src/nodes/property.ts
|
|
828
|
+
/**
|
|
829
|
+
* Definition for the {@link PropertyNode}. `required` defaults to `false`. When a `dialect` is
|
|
830
|
+
* passed to `create`, the schema's `optional`/`nullish` flags are derived through its
|
|
831
|
+
* `optionality`; without one, the schema is left as-is.
|
|
832
|
+
*/
|
|
833
|
+
const propertyDef = defineNode({
|
|
834
|
+
kind: "Property",
|
|
835
|
+
build: (props, dialect) => {
|
|
836
|
+
const required = props.required ?? false;
|
|
837
|
+
return {
|
|
838
|
+
...props,
|
|
839
|
+
required,
|
|
840
|
+
schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
|
|
841
|
+
};
|
|
842
|
+
},
|
|
843
|
+
children: ["schema"],
|
|
844
|
+
visitorKey: "property"
|
|
845
|
+
});
|
|
846
|
+
/**
|
|
847
|
+
* Creates a `PropertyNode`.
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* ```ts
|
|
851
|
+
* const property = createProperty({
|
|
852
|
+
* name: 'status',
|
|
853
|
+
* required: true,
|
|
854
|
+
* schema: createSchema({ type: 'string', nullable: true }),
|
|
855
|
+
* })
|
|
856
|
+
* // required=true, no optional/nullish
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
const createProperty = propertyDef.create;
|
|
860
|
+
//#endregion
|
|
646
861
|
//#region src/nodes/response.ts
|
|
647
862
|
/**
|
|
648
863
|
* Definition for the {@link ResponseNode}. A single legacy `schema` (with optional
|
|
@@ -652,14 +867,14 @@ const responseDef = defineNode({
|
|
|
652
867
|
kind: "Response",
|
|
653
868
|
build: (props) => {
|
|
654
869
|
const { schema, mediaType, keysToOmit, content, ...rest } = props;
|
|
655
|
-
const entries = content ?? (schema ? [{
|
|
870
|
+
const entries = content ?? (schema ? [createContent({
|
|
656
871
|
contentType: mediaType ?? "application/json",
|
|
657
872
|
schema,
|
|
658
873
|
keysToOmit: keysToOmit ?? null
|
|
659
|
-
}] : void 0);
|
|
874
|
+
})] : void 0);
|
|
660
875
|
return {
|
|
661
876
|
...rest,
|
|
662
|
-
content: entries
|
|
877
|
+
content: entries
|
|
663
878
|
};
|
|
664
879
|
},
|
|
665
880
|
children: ["content"],
|
|
@@ -672,12 +887,12 @@ const responseDef = defineNode({
|
|
|
672
887
|
* ```ts
|
|
673
888
|
* const response = createResponse({
|
|
674
889
|
* statusCode: '200',
|
|
675
|
-
* content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
|
|
890
|
+
* content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],
|
|
676
891
|
* })
|
|
677
892
|
* ```
|
|
678
893
|
*/
|
|
679
894
|
const createResponse = responseDef.create;
|
|
680
895
|
//#endregion
|
|
681
|
-
export {
|
|
896
|
+
export { schemaDef as $, fileDef as A, createConst as B, objectBindingPatternDef as C, createImport as D, createFile as E, arrowFunctionDef as F, functionDef as G, createJsx as H, breakDef as I, typeDef as J, jsxDef as K, constDef as L, sourceDef as M, contentDef as N, createSource as O, createContent as P, createSchema as Q, createArrowFunction as R, indexedAccessTypeDef as S, createExport as T, createText as U, createFunction as V, createType as W, camelCase as X, extractStringsFromNodes as Y, pascalCase as Z, createIndexedAccessType as _, createParameter as a, functionParameterDef as b, outputDef as c, createRequestBody as d, defineNode as et, requestBodyDef as f, createFunctionParameters as g, createFunctionParameter as h, propertyDef as i, importDef as j, exportDef as k, createOperation as l, inputDef as m, responseDef as n, parameterDef as o, createInput as p, textDef as q, createProperty as r, createOutput as s, createResponse as t, visitorKeys as tt, operationDef as u, createObjectBindingPattern as v, typeLiteralDef as w, functionParametersDef as x, createTypeLiteral as y, createBreak as z };
|
|
682
897
|
|
|
683
|
-
//# sourceMappingURL=response-
|
|
898
|
+
//# sourceMappingURL=response-Rd1uisM1.js.map
|