@kubb/ast 5.0.0-beta.61 → 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/dist/{defineMacro-Bv9R_9a2.cjs → defineMacro-BryDiuQl.cjs} +12 -20
- package/dist/defineMacro-BryDiuQl.cjs.map +1 -0
- package/dist/{defineMacro-BTXvS8nI.js → defineMacro-CNkUpxia.js} +12 -19
- package/dist/defineMacro-CNkUpxia.js.map +1 -0
- package/dist/{defineMacro-BLIR6k-j.d.ts → defineMacro-Vw-xQvq7.d.ts} +9 -17
- 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 +19 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +36 -37
- package/dist/index.js +19 -17
- package/dist/index.js.map +1 -1
- package/dist/macros.cjs +33 -20
- package/dist/macros.cjs.map +1 -1
- package/dist/macros.d.ts +13 -11
- package/dist/macros.js +33 -20
- package/dist/macros.js.map +1 -1
- package/dist/{operationParams-BZ07xDm0.d.ts → operationParams-B44p6EQy.d.ts} +2 -2
- package/dist/{response-hnSw2NKE.cjs → response-BeG6hq2D.cjs} +394 -147
- package/dist/response-BeG6hq2D.cjs.map +1 -0
- package/dist/{response-KUdWiDWw.js → response-Rd1uisM1.js} +376 -136
- package/dist/response-Rd1uisM1.js.map +1 -0
- package/dist/{types-DyDzizSf.d.ts → types-DQTgVSwE.d.ts} +4 -54
- package/dist/types.d.ts +5 -6
- package/dist/{utils-BLJwyza-.cjs → utils-BDI3kXlb.cjs} +5 -5
- package/dist/{utils-BLJwyza-.cjs.map → utils-BDI3kXlb.cjs.map} +1 -1
- package/dist/{utils-CF_-Pn_c.js → utils-DW9rnfsD.js} +5 -5
- package/dist/{utils-CF_-Pn_c.js.map → utils-DW9rnfsD.js.map} +1 -1
- package/dist/utils.cjs +4 -4
- package/dist/utils.d.ts +11 -3
- package/dist/utils.js +3 -3
- package/dist/{visitor-DpKZ9Tk0.cjs → visitor-B7Zlnp4c.cjs} +3 -53
- package/dist/visitor-B7Zlnp4c.cjs.map +1 -0
- package/dist/{visitor-DJ6ZEJvq.js → visitor-DepQEKyp.js} +4 -42
- package/dist/visitor-DepQEKyp.js.map +1 -0
- package/package.json +1 -1
- package/src/constants.ts +0 -30
- package/src/dedupe.ts +1 -9
- package/src/defineMacro.ts +19 -12
- package/src/{node.ts → defineNode.ts} +19 -42
- package/src/dialect.ts +42 -19
- package/src/factory.ts +3 -90
- package/src/index.ts +6 -8
- package/src/macros/macroDiscriminatorEnum.ts +7 -1
- package/src/macros/macroEnumName.ts +9 -1
- package/src/macros/macroSimplifyUnion.ts +29 -19
- 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 -5
- package/src/utils/extractStringsFromNodes.ts +1 -0
- package/src/utils/operationParams.ts +1 -1
- package/src/visitor.ts +2 -13
- package/dist/defineMacro-BTXvS8nI.js.map +0 -1
- package/dist/defineMacro-Bv9R_9a2.cjs.map +0 -1
- package/dist/extractStringsFromNodes-Cja-xxx5.js +0 -29
- package/dist/extractStringsFromNodes-Cja-xxx5.js.map +0 -1
- package/dist/extractStringsFromNodes-DKgDjFO0.cjs +0 -34
- package/dist/extractStringsFromNodes-DKgDjFO0.cjs.map +0 -1
- package/dist/extractStringsFromNodes-p4mX1TQD.d.ts +0 -14
- package/dist/factory-CZNOGI-N.js +0 -283
- package/dist/factory-CZNOGI-N.js.map +0 -1
- package/dist/factory-DG1CVkEb.cjs +0 -300
- package/dist/factory-DG1CVkEb.cjs.map +0 -1
- package/dist/response-KUdWiDWw.js.map +0 -1
- package/dist/response-hnSw2NKE.cjs.map +0 -1
- package/dist/visitor-DJ6ZEJvq.js.map +0 -1
- package/dist/visitor-DpKZ9Tk0.cjs.map +0 -1
- package/src/mocks.ts +0 -56
- package/src/nodes/http.ts +0 -85
- /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,12 +155,87 @@ 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
|
|
175
|
+
//#region src/utils/extractStringsFromNodes.ts
|
|
176
|
+
/**
|
|
177
|
+
* Extracts all string content from a `CodeNode` tree recursively.
|
|
178
|
+
*
|
|
179
|
+
* Collects text node values, identifier references in string fields (`params`, `generics`, `returnType`, `type`),
|
|
180
|
+
* and nested node content. Used to build the full source string for import filtering.
|
|
181
|
+
*/
|
|
182
|
+
function extractStringsFromNodes(nodes) {
|
|
183
|
+
if (!nodes?.length) return "";
|
|
184
|
+
return nodes.map((node) => {
|
|
185
|
+
if (typeof node === "string") return node;
|
|
186
|
+
if (node.kind === "Text") return node.value;
|
|
187
|
+
if (node.kind === "Break") return "";
|
|
188
|
+
if (node.kind === "Jsx") return node.value;
|
|
189
|
+
const parts = [];
|
|
190
|
+
if ("params" in node && node.params) parts.push(node.params);
|
|
191
|
+
if ("generics" in node && node.generics) parts.push(Array.isArray(node.generics) ? node.generics.join(", ") : node.generics);
|
|
192
|
+
if ("returnType" in node && node.returnType) parts.push(node.returnType);
|
|
193
|
+
if ("type" in node && typeof node.type === "string") parts.push(node.type);
|
|
194
|
+
const nested = extractStringsFromNodes(node.nodes);
|
|
195
|
+
if (nested) parts.push(nested);
|
|
196
|
+
return parts.join("\n");
|
|
197
|
+
}).filter(Boolean).join("\n");
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
166
200
|
//#region src/nodes/code.ts
|
|
167
201
|
/**
|
|
168
202
|
* Definition for the {@link ConstNode}.
|
|
169
203
|
*/
|
|
170
204
|
const constDef = defineNode({ kind: "Const" });
|
|
171
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 })
|
|
223
|
+
});
|
|
224
|
+
/**
|
|
225
|
+
* Definition for the {@link BreakNode}.
|
|
226
|
+
*/
|
|
227
|
+
const breakDef = defineNode({
|
|
228
|
+
kind: "Break",
|
|
229
|
+
build: () => ({})
|
|
230
|
+
});
|
|
231
|
+
/**
|
|
232
|
+
* Definition for the {@link JsxNode}.
|
|
233
|
+
*/
|
|
234
|
+
const jsxDef = defineNode({
|
|
235
|
+
kind: "Jsx",
|
|
236
|
+
build: (value) => ({ value })
|
|
237
|
+
});
|
|
238
|
+
/**
|
|
172
239
|
* Creates a `ConstNode` representing a TypeScript `const` declaration.
|
|
173
240
|
*
|
|
174
241
|
* @example Exported constant with type and `as const`
|
|
@@ -179,10 +246,6 @@ const constDef = defineNode({ kind: "Const" });
|
|
|
179
246
|
*/
|
|
180
247
|
const createConst = constDef.create;
|
|
181
248
|
/**
|
|
182
|
-
* Definition for the {@link TypeNode}.
|
|
183
|
-
*/
|
|
184
|
-
const typeDef = defineNode({ kind: "Type" });
|
|
185
|
-
/**
|
|
186
249
|
* Creates a `TypeNode` representing a TypeScript `type` alias declaration.
|
|
187
250
|
*
|
|
188
251
|
* @example
|
|
@@ -193,10 +256,6 @@ const typeDef = defineNode({ kind: "Type" });
|
|
|
193
256
|
*/
|
|
194
257
|
const createType = typeDef.create;
|
|
195
258
|
/**
|
|
196
|
-
* Definition for the {@link FunctionNode}.
|
|
197
|
-
*/
|
|
198
|
-
const functionDef = defineNode({ kind: "Function" });
|
|
199
|
-
/**
|
|
200
259
|
* Creates a `FunctionNode` representing a TypeScript `function` declaration.
|
|
201
260
|
*
|
|
202
261
|
* @example
|
|
@@ -207,10 +266,6 @@ const functionDef = defineNode({ kind: "Function" });
|
|
|
207
266
|
*/
|
|
208
267
|
const createFunction = functionDef.create;
|
|
209
268
|
/**
|
|
210
|
-
* Definition for the {@link ArrowFunctionNode}.
|
|
211
|
-
*/
|
|
212
|
-
const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
|
|
213
|
-
/**
|
|
214
269
|
* Creates an `ArrowFunctionNode` representing a TypeScript arrow function.
|
|
215
270
|
*
|
|
216
271
|
* @example
|
|
@@ -221,13 +276,6 @@ const arrowFunctionDef = defineNode({ kind: "ArrowFunction" });
|
|
|
221
276
|
*/
|
|
222
277
|
const createArrowFunction = arrowFunctionDef.create;
|
|
223
278
|
/**
|
|
224
|
-
* Definition for the {@link TextNode}.
|
|
225
|
-
*/
|
|
226
|
-
const textDef = defineNode({
|
|
227
|
-
kind: "Text",
|
|
228
|
-
build: (value) => ({ value })
|
|
229
|
-
});
|
|
230
|
-
/**
|
|
231
279
|
* Creates a {@link TextNode} representing a raw string fragment in the source output.
|
|
232
280
|
*
|
|
233
281
|
* @example
|
|
@@ -238,13 +286,6 @@ const textDef = defineNode({
|
|
|
238
286
|
*/
|
|
239
287
|
const createText = textDef.create;
|
|
240
288
|
/**
|
|
241
|
-
* Definition for the {@link BreakNode}.
|
|
242
|
-
*/
|
|
243
|
-
const breakDef = defineNode({
|
|
244
|
-
kind: "Break",
|
|
245
|
-
build: () => ({})
|
|
246
|
-
});
|
|
247
|
-
/**
|
|
248
289
|
* Creates a {@link BreakNode} representing a line break in the source output.
|
|
249
290
|
*
|
|
250
291
|
* @example
|
|
@@ -257,13 +298,6 @@ function createBreak() {
|
|
|
257
298
|
return breakDef.create();
|
|
258
299
|
}
|
|
259
300
|
/**
|
|
260
|
-
* Definition for the {@link JsxNode}.
|
|
261
|
-
*/
|
|
262
|
-
const jsxDef = defineNode({
|
|
263
|
-
kind: "Jsx",
|
|
264
|
-
build: (value) => ({ value })
|
|
265
|
-
});
|
|
266
|
-
/**
|
|
267
301
|
* Creates a {@link JsxNode} representing a raw JSX fragment in the source output.
|
|
268
302
|
*
|
|
269
303
|
* @example
|
|
@@ -287,12 +321,171 @@ const contentDef = defineNode({
|
|
|
287
321
|
*/
|
|
288
322
|
const createContent = contentDef.create;
|
|
289
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
|
|
290
470
|
//#region src/nodes/file.ts
|
|
291
471
|
/**
|
|
292
472
|
* Definition for the {@link ImportNode}.
|
|
293
473
|
*/
|
|
294
474
|
const importDef = defineNode({ kind: "Import" });
|
|
295
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
|
+
/**
|
|
296
489
|
* Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
|
|
297
490
|
*
|
|
298
491
|
* @example Named import
|
|
@@ -303,10 +496,6 @@ const importDef = defineNode({ kind: "Import" });
|
|
|
303
496
|
*/
|
|
304
497
|
const createImport = importDef.create;
|
|
305
498
|
/**
|
|
306
|
-
* Definition for the {@link ExportNode}.
|
|
307
|
-
*/
|
|
308
|
-
const exportDef = defineNode({ kind: "Export" });
|
|
309
|
-
/**
|
|
310
499
|
* Creates an `ExportNode` representing a language-agnostic export/public API declaration.
|
|
311
500
|
*
|
|
312
501
|
* @example Named export
|
|
@@ -317,10 +506,6 @@ const exportDef = defineNode({ kind: "Export" });
|
|
|
317
506
|
*/
|
|
318
507
|
const createExport = exportDef.create;
|
|
319
508
|
/**
|
|
320
|
-
* Definition for the {@link SourceNode}.
|
|
321
|
-
*/
|
|
322
|
-
const sourceDef = defineNode({ kind: "Source" });
|
|
323
|
-
/**
|
|
324
509
|
* Creates a `SourceNode` representing a fragment of source code within a file.
|
|
325
510
|
*
|
|
326
511
|
* @example
|
|
@@ -330,10 +515,64 @@ const sourceDef = defineNode({ kind: "Source" });
|
|
|
330
515
|
*/
|
|
331
516
|
const createSource = sourceDef.create;
|
|
332
517
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
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
|
+
* ```
|
|
335
545
|
*/
|
|
336
|
-
|
|
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
|
+
}
|
|
337
576
|
//#endregion
|
|
338
577
|
//#region src/nodes/function.ts
|
|
339
578
|
/**
|
|
@@ -341,44 +580,14 @@ const fileDef = defineNode({ kind: "File" });
|
|
|
341
580
|
*/
|
|
342
581
|
const typeLiteralDef = defineNode({ kind: "TypeLiteral" });
|
|
343
582
|
/**
|
|
344
|
-
* Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* ```ts
|
|
348
|
-
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
349
|
-
* // { petId: string }
|
|
350
|
-
* ```
|
|
351
|
-
*/
|
|
352
|
-
const createTypeLiteral = typeLiteralDef.create;
|
|
353
|
-
/**
|
|
354
583
|
* Definition for the {@link IndexedAccessTypeNode}.
|
|
355
584
|
*/
|
|
356
585
|
const indexedAccessTypeDef = defineNode({ kind: "IndexedAccessType" });
|
|
357
586
|
/**
|
|
358
|
-
* Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
|
|
359
|
-
*
|
|
360
|
-
* @example
|
|
361
|
-
* ```ts
|
|
362
|
-
* createIndexedAccessType({ objectType: 'DeletePetPathParams', indexType: 'petId' })
|
|
363
|
-
* // DeletePetPathParams['petId']
|
|
364
|
-
* ```
|
|
365
|
-
*/
|
|
366
|
-
const createIndexedAccessType = indexedAccessTypeDef.create;
|
|
367
|
-
/**
|
|
368
587
|
* Definition for the {@link ObjectBindingPatternNode}.
|
|
369
588
|
*/
|
|
370
589
|
const objectBindingPatternDef = defineNode({ kind: "ObjectBindingPattern" });
|
|
371
590
|
/**
|
|
372
|
-
* Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
|
|
373
|
-
*
|
|
374
|
-
* @example
|
|
375
|
-
* ```ts
|
|
376
|
-
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
377
|
-
* // { id, name }
|
|
378
|
-
* ```
|
|
379
|
-
*/
|
|
380
|
-
const createObjectBindingPattern = objectBindingPatternDef.create;
|
|
381
|
-
/**
|
|
382
591
|
* Definition for the {@link FunctionParameterNode}. `optional` defaults to `false`.
|
|
383
592
|
* Passing `properties` builds a destructured group: an {@link ObjectBindingPatternNode} name
|
|
384
593
|
* paired with a {@link TypeLiteralNode} type.
|
|
@@ -403,6 +612,43 @@ const functionParameterDef = defineNode({
|
|
|
403
612
|
}
|
|
404
613
|
});
|
|
405
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
|
+
/**
|
|
406
652
|
* Creates a `FunctionParameterNode`. `optional` defaults to `false`.
|
|
407
653
|
*
|
|
408
654
|
* @example Optional param
|
|
@@ -419,13 +665,6 @@ const functionParameterDef = defineNode({
|
|
|
419
665
|
*/
|
|
420
666
|
const createFunctionParameter = functionParameterDef.create;
|
|
421
667
|
/**
|
|
422
|
-
* Definition for the {@link FunctionParametersNode}.
|
|
423
|
-
*/
|
|
424
|
-
const functionParametersDef = defineNode({
|
|
425
|
-
kind: "FunctionParameters",
|
|
426
|
-
defaults: { params: [] }
|
|
427
|
-
});
|
|
428
|
-
/**
|
|
429
668
|
* Creates a `FunctionParametersNode` from an ordered list of parameters.
|
|
430
669
|
*
|
|
431
670
|
* @example
|
|
@@ -457,8 +696,8 @@ const inputDef = defineNode({
|
|
|
457
696
|
});
|
|
458
697
|
/**
|
|
459
698
|
* Creates an `InputNode`. Pass `stream: true` for the streaming variant whose `schemas` and
|
|
460
|
-
* `operations` are `AsyncIterable` sources
|
|
461
|
-
*
|
|
699
|
+
* `operations` are `AsyncIterable` sources. Otherwise it builds the eager variant with array
|
|
700
|
+
* `schemas`/`operations`. Both variants get the defaulted `meta`.
|
|
462
701
|
*
|
|
463
702
|
* @example Eager
|
|
464
703
|
* ```ts
|
|
@@ -475,6 +714,10 @@ function createInput(options = {}) {
|
|
|
475
714
|
const { stream, ...overrides } = options;
|
|
476
715
|
if (stream) return {
|
|
477
716
|
kind: "Input",
|
|
717
|
+
meta: {
|
|
718
|
+
circularNames: [],
|
|
719
|
+
enumNames: []
|
|
720
|
+
},
|
|
478
721
|
...overrides
|
|
479
722
|
};
|
|
480
723
|
return inputDef.create(overrides);
|
|
@@ -482,18 +725,15 @@ function createInput(options = {}) {
|
|
|
482
725
|
//#endregion
|
|
483
726
|
//#region src/nodes/requestBody.ts
|
|
484
727
|
/**
|
|
485
|
-
* 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.
|
|
486
730
|
*/
|
|
487
731
|
const requestBodyDef = defineNode({
|
|
488
732
|
kind: "RequestBody",
|
|
489
|
-
build: (props) => ({
|
|
490
|
-
...props,
|
|
491
|
-
content: props.content?.map(createContent)
|
|
492
|
-
}),
|
|
493
733
|
children: ["content"]
|
|
494
734
|
});
|
|
495
735
|
/**
|
|
496
|
-
* Creates a `RequestBodyNode
|
|
736
|
+
* Creates a `RequestBodyNode`.
|
|
497
737
|
*/
|
|
498
738
|
const createRequestBody = requestBodyDef.create;
|
|
499
739
|
//#endregion
|
|
@@ -552,22 +792,22 @@ function createOutput(overrides = {}) {
|
|
|
552
792
|
//#endregion
|
|
553
793
|
//#region src/nodes/parameter.ts
|
|
554
794
|
/**
|
|
555
|
-
* Definition for the {@link ParameterNode}. `required` defaults to `false`
|
|
556
|
-
* 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.
|
|
557
798
|
*/
|
|
558
799
|
const parameterDef = defineNode({
|
|
559
800
|
kind: "Parameter",
|
|
560
|
-
build: (props) => {
|
|
801
|
+
build: (props, dialect) => {
|
|
561
802
|
const required = props.required ?? false;
|
|
562
803
|
return {
|
|
563
804
|
...props,
|
|
564
805
|
required,
|
|
565
|
-
schema:
|
|
806
|
+
schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
|
|
566
807
|
};
|
|
567
808
|
},
|
|
568
809
|
children: ["schema"],
|
|
569
|
-
visitorKey: "parameter"
|
|
570
|
-
rebuild: true
|
|
810
|
+
visitorKey: "parameter"
|
|
571
811
|
});
|
|
572
812
|
/**
|
|
573
813
|
* Creates a `ParameterNode`.
|
|
@@ -586,22 +826,22 @@ const createParameter = parameterDef.create;
|
|
|
586
826
|
//#endregion
|
|
587
827
|
//#region src/nodes/property.ts
|
|
588
828
|
/**
|
|
589
|
-
* Definition for the {@link PropertyNode}. `required` defaults to `false`
|
|
590
|
-
* schema's `optional`/`nullish` flags are
|
|
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.
|
|
591
832
|
*/
|
|
592
833
|
const propertyDef = defineNode({
|
|
593
834
|
kind: "Property",
|
|
594
|
-
build: (props) => {
|
|
835
|
+
build: (props, dialect) => {
|
|
595
836
|
const required = props.required ?? false;
|
|
596
837
|
return {
|
|
597
838
|
...props,
|
|
598
839
|
required,
|
|
599
|
-
schema:
|
|
840
|
+
schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema
|
|
600
841
|
};
|
|
601
842
|
},
|
|
602
843
|
children: ["schema"],
|
|
603
|
-
visitorKey: "property"
|
|
604
|
-
rebuild: true
|
|
844
|
+
visitorKey: "property"
|
|
605
845
|
});
|
|
606
846
|
/**
|
|
607
847
|
* Creates a `PropertyNode`.
|
|
@@ -627,14 +867,14 @@ const responseDef = defineNode({
|
|
|
627
867
|
kind: "Response",
|
|
628
868
|
build: (props) => {
|
|
629
869
|
const { schema, mediaType, keysToOmit, content, ...rest } = props;
|
|
630
|
-
const entries = content ?? (schema ? [{
|
|
870
|
+
const entries = content ?? (schema ? [createContent({
|
|
631
871
|
contentType: mediaType ?? "application/json",
|
|
632
872
|
schema,
|
|
633
873
|
keysToOmit: keysToOmit ?? null
|
|
634
|
-
}] : void 0);
|
|
874
|
+
})] : void 0);
|
|
635
875
|
return {
|
|
636
876
|
...rest,
|
|
637
|
-
content: entries
|
|
877
|
+
content: entries
|
|
638
878
|
};
|
|
639
879
|
},
|
|
640
880
|
children: ["content"],
|
|
@@ -647,12 +887,12 @@ const responseDef = defineNode({
|
|
|
647
887
|
* ```ts
|
|
648
888
|
* const response = createResponse({
|
|
649
889
|
* statusCode: '200',
|
|
650
|
-
* content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
|
|
890
|
+
* content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],
|
|
651
891
|
* })
|
|
652
892
|
* ```
|
|
653
893
|
*/
|
|
654
894
|
const createResponse = responseDef.create;
|
|
655
895
|
//#endregion
|
|
656
|
-
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 };
|
|
657
897
|
|
|
658
|
-
//# sourceMappingURL=response-
|
|
898
|
+
//# sourceMappingURL=response-Rd1uisM1.js.map
|