@kubb/ast 5.0.0-beta.98 → 5.0.0
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 +5 -14
- package/dist/index.cjs +88 -354
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +33 -155
- package/dist/index.js +85 -340
- package/dist/index.js.map +1 -1
- package/dist/{types-CqXMgUzC.d.ts → types-BPqinVNh.d.ts} +26 -9
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -331,33 +331,6 @@ const contentDef = defineNode({
|
|
|
331
331
|
*/
|
|
332
332
|
const createContent = contentDef.create;
|
|
333
333
|
//#endregion
|
|
334
|
-
//#region ../../internals/utils/src/casing.ts
|
|
335
|
-
/**
|
|
336
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
337
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
338
|
-
* and capitalizes each word according to `pascal`.
|
|
339
|
-
*
|
|
340
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
341
|
-
*/
|
|
342
|
-
function toCamelOrPascal(text, pascal) {
|
|
343
|
-
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
344
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
345
|
-
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
346
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Converts `text` to PascalCase.
|
|
350
|
-
*
|
|
351
|
-
* @example Word boundaries
|
|
352
|
-
* `pascalCase('hello-world') // 'HelloWorld'`
|
|
353
|
-
*
|
|
354
|
-
* @example With a suffix
|
|
355
|
-
* `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
|
|
356
|
-
*/
|
|
357
|
-
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
358
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
359
|
-
}
|
|
360
|
-
//#endregion
|
|
361
334
|
//#region ../../internals/utils/src/fs.ts
|
|
362
335
|
/**
|
|
363
336
|
* Strips the file extension from a path or file name.
|
|
@@ -452,6 +425,17 @@ function extractStringsFromNodes(nodes) {
|
|
|
452
425
|
}
|
|
453
426
|
//#endregion
|
|
454
427
|
//#region src/utils/combineFileMembers.ts
|
|
428
|
+
const IDENTIFIER_RUN = /[\w$]+/g;
|
|
429
|
+
/**
|
|
430
|
+
* How many imports a file needs before indexing the source beats scanning it once per name.
|
|
431
|
+
*/
|
|
432
|
+
const INDEX_ABOVE_IMPORTS = 128;
|
|
433
|
+
/**
|
|
434
|
+
* Every unbroken run of identifier characters in the source.
|
|
435
|
+
*/
|
|
436
|
+
function collectIdentifiers(source) {
|
|
437
|
+
return new Set(source.match(IDENTIFIER_RUN));
|
|
438
|
+
}
|
|
455
439
|
function sourceKey(source) {
|
|
456
440
|
return `${source.name ?? extractStringsFromNodes(source.nodes)}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`;
|
|
457
441
|
}
|
|
@@ -546,7 +530,8 @@ function combineExports(exports) {
|
|
|
546
530
|
*/
|
|
547
531
|
function combineImports(imports, exports, source) {
|
|
548
532
|
const exportedNames = new Set(exports.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
|
|
549
|
-
const
|
|
533
|
+
const identifiers = source && imports.length > INDEX_ABOVE_IMPORTS ? collectIdentifiers(source) : null;
|
|
534
|
+
const isUsed = (importName) => !source || identifiers?.has(importName) || source.includes(importName) || exportedNames.has(importName);
|
|
550
535
|
const importNameMemo = /* @__PURE__ */ new Map();
|
|
551
536
|
const canonicalizeName = (n) => {
|
|
552
537
|
if (typeof n === "string") return n;
|
|
@@ -1065,9 +1050,9 @@ function* getChildren(node, recurse) {
|
|
|
1065
1050
|
* context. The result is a replacement node, a collected value, or `undefined`
|
|
1066
1051
|
* when no callback is registered for the kind.
|
|
1067
1052
|
*
|
|
1068
|
-
* Shared by `transform` and `
|
|
1053
|
+
* Shared by `transform` and `collect` so node-kind dispatch lives in one place.
|
|
1069
1054
|
* `TResult` is the caller's expected return: the same node type for `transform`,
|
|
1070
|
-
* the collected value type for `
|
|
1055
|
+
* the collected value type for `collect`.
|
|
1071
1056
|
*/
|
|
1072
1057
|
function applyVisitor(node, visitor, parent) {
|
|
1073
1058
|
const key = VISITOR_KEY_BY_KIND[node.kind];
|
|
@@ -1125,12 +1110,12 @@ function transformChildren(node, visitor, recurse) {
|
|
|
1125
1110
|
}
|
|
1126
1111
|
/**
|
|
1127
1112
|
* Lazy depth-first collection pass. Yields every non-null value returned by
|
|
1128
|
-
* the visitor callbacks. Use `
|
|
1113
|
+
* the visitor callbacks. Use `collectSync` for the eager array form.
|
|
1129
1114
|
*
|
|
1130
1115
|
* @example Collect every operationId
|
|
1131
1116
|
* ```ts
|
|
1132
1117
|
* const ids: string[] = []
|
|
1133
|
-
* for (const id of
|
|
1118
|
+
* for (const id of collect<string>(root, {
|
|
1134
1119
|
* operation(node) {
|
|
1135
1120
|
* return node.operationId
|
|
1136
1121
|
* },
|
|
@@ -1139,7 +1124,7 @@ function transformChildren(node, visitor, recurse) {
|
|
|
1139
1124
|
* }
|
|
1140
1125
|
* ```
|
|
1141
1126
|
*/
|
|
1142
|
-
function*
|
|
1127
|
+
function* collect(node, options) {
|
|
1143
1128
|
const { depth, parent, ...visitor } = options;
|
|
1144
1129
|
yield* collectNode(node, visitor, (depth ?? visitorDepths.deep) === visitorDepths.deep, parent);
|
|
1145
1130
|
}
|
|
@@ -1154,15 +1139,15 @@ function* collectNode(node, visitor, recurse, parent) {
|
|
|
1154
1139
|
*
|
|
1155
1140
|
* @example Collect every operationId
|
|
1156
1141
|
* ```ts
|
|
1157
|
-
* const ids =
|
|
1142
|
+
* const ids = collectSync<string>(root, {
|
|
1158
1143
|
* operation(node) {
|
|
1159
1144
|
* return node.operationId
|
|
1160
1145
|
* },
|
|
1161
1146
|
* })
|
|
1162
1147
|
* ```
|
|
1163
1148
|
*/
|
|
1164
|
-
function
|
|
1165
|
-
return Array.from(
|
|
1149
|
+
function collectSync(node, options) {
|
|
1150
|
+
return Array.from(collect(node, options));
|
|
1166
1151
|
}
|
|
1167
1152
|
//#endregion
|
|
1168
1153
|
//#region src/defineMacro.ts
|
|
@@ -1202,7 +1187,7 @@ function chain({ macros, key, node, context }) {
|
|
|
1202
1187
|
for (const macro of macros) {
|
|
1203
1188
|
const callback = macro[key];
|
|
1204
1189
|
if (!callback) continue;
|
|
1205
|
-
if (macro.
|
|
1190
|
+
if (macro.match && !macro.match(current)) continue;
|
|
1206
1191
|
const next = callback(current, context);
|
|
1207
1192
|
if (next != null) current = next;
|
|
1208
1193
|
}
|
|
@@ -1329,54 +1314,7 @@ function createPrinter(build) {
|
|
|
1329
1314
|
};
|
|
1330
1315
|
}
|
|
1331
1316
|
//#endregion
|
|
1332
|
-
//#region src/utils/mergeAdjacentSchemas.ts
|
|
1333
|
-
/**
|
|
1334
|
-
* Merges a run of adjacent anonymous object members into one. Named or non-object members break the
|
|
1335
|
-
* run and pass through unchanged. The merge follows member order, so callers control which members
|
|
1336
|
-
* combine by where they place them in the sequence.
|
|
1337
|
-
*
|
|
1338
|
-
* @example
|
|
1339
|
-
* ```ts
|
|
1340
|
-
* const merged = [...mergeAdjacentObjectsLazy([objectA, objectB])]
|
|
1341
|
-
* ```
|
|
1342
|
-
*/
|
|
1343
|
-
function* mergeAdjacentObjectsLazy(members) {
|
|
1344
|
-
let acc;
|
|
1345
|
-
for (const member of members) {
|
|
1346
|
-
const objectMember = narrowSchema(member, "object");
|
|
1347
|
-
if (objectMember && !objectMember.name && acc !== void 0) {
|
|
1348
|
-
const accObject = narrowSchema(acc, "object");
|
|
1349
|
-
if (accObject && !accObject.name) {
|
|
1350
|
-
acc = createSchema({
|
|
1351
|
-
...accObject,
|
|
1352
|
-
properties: [...accObject.properties ?? [], ...objectMember.properties ?? []]
|
|
1353
|
-
});
|
|
1354
|
-
continue;
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
if (acc !== void 0) yield acc;
|
|
1358
|
-
acc = member;
|
|
1359
|
-
}
|
|
1360
|
-
if (acc !== void 0) yield acc;
|
|
1361
|
-
}
|
|
1362
|
-
//#endregion
|
|
1363
1317
|
//#region src/utils/refs.ts
|
|
1364
|
-
const plainStringTypes = /* @__PURE__ */ new Set([
|
|
1365
|
-
"string",
|
|
1366
|
-
"uuid",
|
|
1367
|
-
"email",
|
|
1368
|
-
"url",
|
|
1369
|
-
"datetime"
|
|
1370
|
-
]);
|
|
1371
|
-
/**
|
|
1372
|
-
* Returns the last path segment of a reference string.
|
|
1373
|
-
*
|
|
1374
|
-
* @example
|
|
1375
|
-
* `extractRefName('#/components/schemas/Pet') // 'Pet'`
|
|
1376
|
-
*/
|
|
1377
|
-
function extractRefName(ref) {
|
|
1378
|
-
return ref.split("/").at(-1) ?? ref;
|
|
1379
|
-
}
|
|
1380
1318
|
/**
|
|
1381
1319
|
* Resolves the emitted name of the schema a ref node points at. Prefers `targetName` (set when
|
|
1382
1320
|
* the referenced schema was renamed, e.g. to break a collision), then the last segment of `ref`,
|
|
@@ -1393,73 +1331,9 @@ function extractRefName(ref) {
|
|
|
1393
1331
|
function resolveRefName(node) {
|
|
1394
1332
|
if (!node || node.type !== "ref") return null;
|
|
1395
1333
|
if (node.targetName) return node.targetName;
|
|
1396
|
-
if (node.ref) return
|
|
1334
|
+
if (node.ref) return node.ref.split("/").at(-1) ?? node.ref;
|
|
1397
1335
|
return node.name ?? node.schema?.name ?? null;
|
|
1398
1336
|
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Builds a PascalCase child schema name by joining a parent name and property name.
|
|
1401
|
-
* Returns `null` when there is no parent to nest under.
|
|
1402
|
-
*
|
|
1403
|
-
* @example Nested under a parent
|
|
1404
|
-
* `childName('Order', 'shipping_address') // 'OrderShippingAddress'`
|
|
1405
|
-
*
|
|
1406
|
-
* @example No parent
|
|
1407
|
-
* `childName(undefined, 'params') // null`
|
|
1408
|
-
*/
|
|
1409
|
-
function childName(parentName, propName) {
|
|
1410
|
-
return parentName ? pascalCase([parentName, propName].join(" ")) : null;
|
|
1411
|
-
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Builds a PascalCase enum name from the parent name, property name, and a suffix, skipping any
|
|
1414
|
-
* empty parts.
|
|
1415
|
-
*
|
|
1416
|
-
* @example
|
|
1417
|
-
* `enumPropName('Order', 'status', 'enum') // 'OrderStatusEnum'`
|
|
1418
|
-
*/
|
|
1419
|
-
function enumPropName(parentName, propName, enumSuffix) {
|
|
1420
|
-
return pascalCase([
|
|
1421
|
-
parentName,
|
|
1422
|
-
propName,
|
|
1423
|
-
enumSuffix
|
|
1424
|
-
].filter(Boolean).join(" "));
|
|
1425
|
-
}
|
|
1426
|
-
/**
|
|
1427
|
-
* Merges a ref node with its resolved schema, giving usage-site fields precedence.
|
|
1428
|
-
*
|
|
1429
|
-
* Every field set on the ref node except `kind`, `type`, `name`, `ref`, and `schema` overrides the
|
|
1430
|
-
* same field in the resolved `node.schema` (for example `description`, `nullable`, `readOnly`,
|
|
1431
|
-
* `deprecated`). Fields left `undefined` on the ref do not shadow the resolved schema. Non-ref
|
|
1432
|
-
* nodes and refs without a resolved `schema` are returned unchanged.
|
|
1433
|
-
*
|
|
1434
|
-
* @example
|
|
1435
|
-
* ```ts
|
|
1436
|
-
* const ref = createSchema({ type: 'ref', ref: '#/components/schemas/Pet', description: 'A cute pet' })
|
|
1437
|
-
* const merged = syncSchemaRef(ref) // merges with resolved Pet schema
|
|
1438
|
-
* ```
|
|
1439
|
-
*/
|
|
1440
|
-
function syncSchemaRef(node) {
|
|
1441
|
-
const ref = narrowSchema(node, "ref");
|
|
1442
|
-
if (!ref) return node;
|
|
1443
|
-
if (!ref.schema) return node;
|
|
1444
|
-
const { kind: _kind, type: _type, name: _name, ref: _ref, schema: _schema, ...overrides } = ref;
|
|
1445
|
-
const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== void 0));
|
|
1446
|
-
return createSchema({
|
|
1447
|
-
...ref.schema,
|
|
1448
|
-
...definedOverrides
|
|
1449
|
-
});
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* Returns `true` when a schema emits as a plain `string` type.
|
|
1453
|
-
*
|
|
1454
|
-
* Covers `string`, `uuid`, `email`, `url`, and `datetime` types. For `date` and `time`
|
|
1455
|
-
* types, returns `true` only when `representation` is `'string'` rather than `'date'`.
|
|
1456
|
-
*/
|
|
1457
|
-
function isStringType(node) {
|
|
1458
|
-
if (plainStringTypes.has(node.type)) return true;
|
|
1459
|
-
const temporal = narrowSchema(node, "date") ?? narrowSchema(node, "time");
|
|
1460
|
-
if (temporal) return temporal.representation !== "date";
|
|
1461
|
-
return false;
|
|
1462
|
-
}
|
|
1463
1337
|
//#endregion
|
|
1464
1338
|
//#region src/utils/schemaGraph.ts
|
|
1465
1339
|
/**
|
|
@@ -1467,7 +1341,7 @@ function isStringType(node) {
|
|
|
1467
1341
|
*/
|
|
1468
1342
|
const collectSchemaRefs = memoize(/* @__PURE__ */ new WeakMap(), (node) => {
|
|
1469
1343
|
const refs = /* @__PURE__ */ new Set();
|
|
1470
|
-
|
|
1344
|
+
collectSync(node, { schema(child) {
|
|
1471
1345
|
if (child.type === "ref") {
|
|
1472
1346
|
const name = resolveRefName(child);
|
|
1473
1347
|
if (name) refs.add(name);
|
|
@@ -1500,6 +1374,36 @@ function collectReferencedSchemaNames(node, out = /* @__PURE__ */ new Set()) {
|
|
|
1500
1374
|
for (const name of collectSchemaRefs(node)) out.add(name);
|
|
1501
1375
|
return out;
|
|
1502
1376
|
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Collects the de-duplicated target names of every pointer-carrying ref in a node's subtree, in
|
|
1379
|
+
* first-occurrence order. The walk is memoized by node identity, so the subtree is scanned once and
|
|
1380
|
+
* `resolver.imports` reads the same result across the ts, zod, and faker plugins instead of
|
|
1381
|
+
* re-scanning the same schema per plugin.
|
|
1382
|
+
*
|
|
1383
|
+
* Only refs that carry a `$ref` pointer count, so a synthesized ref pointing at a sibling in the
|
|
1384
|
+
* same file (a union member created by name) is left out. That leaves exactly the set
|
|
1385
|
+
* `resolver.imports` emits. This is the ordered, import-facing counterpart to
|
|
1386
|
+
* {@link collectReferencedSchemaNames}, which returns an unordered set for graph analysis.
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```ts
|
|
1390
|
+
* collectImportedRefNames(petSchema)
|
|
1391
|
+
* // ['Category', 'Tag']
|
|
1392
|
+
* ```
|
|
1393
|
+
*/
|
|
1394
|
+
const collectImportedRefNames = memoize(/* @__PURE__ */ new WeakMap(), (node) => {
|
|
1395
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1396
|
+
const names = [];
|
|
1397
|
+
collectSync(node, { schema(child) {
|
|
1398
|
+
if (child.type !== "ref" || !child.ref) return;
|
|
1399
|
+
const name = resolveRefName(child);
|
|
1400
|
+
if (name && !seen.has(name)) {
|
|
1401
|
+
seen.add(name);
|
|
1402
|
+
names.push(name);
|
|
1403
|
+
}
|
|
1404
|
+
} });
|
|
1405
|
+
return names;
|
|
1406
|
+
});
|
|
1503
1407
|
function computeUsedSchemaNames(operations, schemas) {
|
|
1504
1408
|
const schemaMap = /* @__PURE__ */ new Map();
|
|
1505
1409
|
for (const schema of schemas) if (schema.name) schemaMap.set(schema.name, schema);
|
|
@@ -1512,7 +1416,7 @@ function computeUsedSchemaNames(operations, schemas) {
|
|
|
1512
1416
|
if (namedSchema) visitSchema(namedSchema);
|
|
1513
1417
|
}
|
|
1514
1418
|
}
|
|
1515
|
-
for (const op of operations) for (const schema of
|
|
1419
|
+
for (const op of operations) for (const schema of collect(op, {
|
|
1516
1420
|
depth: "shallow",
|
|
1517
1421
|
schema: (node) => node
|
|
1518
1422
|
})) visitSchema(schema);
|
|
@@ -1542,12 +1446,24 @@ function collectUsedSchemaNames(operations, schemas) {
|
|
|
1542
1446
|
return computeUsedSchemaNames(operations, schemas);
|
|
1543
1447
|
}
|
|
1544
1448
|
const EMPTY_CIRCULAR_SET = /* @__PURE__ */ new Set();
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1449
|
+
/**
|
|
1450
|
+
* Finds every schema that takes part in a circular dependency chain in a schema dependency graph
|
|
1451
|
+
* that maps each schema name to the names it references directly.
|
|
1452
|
+
*
|
|
1453
|
+
* Use this when the graph was already collected during another pass (e.g. the adapter's convert
|
|
1454
|
+
* walk), so the schema nodes are not swept a second time. `findCircularSchemas` builds the graph
|
|
1455
|
+
* from schema nodes and delegates here.
|
|
1456
|
+
*
|
|
1457
|
+
* @example
|
|
1458
|
+
* ```ts
|
|
1459
|
+
* const graph = new Map([
|
|
1460
|
+
* ['Pet', new Set(['Category'])],
|
|
1461
|
+
* ['Category', new Set(['Pet'])],
|
|
1462
|
+
* ])
|
|
1463
|
+
* findCircularSchemasFromGraph(graph) // Set { 'Pet', 'Category' }
|
|
1464
|
+
* ```
|
|
1465
|
+
*/
|
|
1466
|
+
function findCircularSchemasFromGraph(graph) {
|
|
1551
1467
|
const circular = /* @__PURE__ */ new Set();
|
|
1552
1468
|
for (const start of graph.keys()) {
|
|
1553
1469
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -1565,6 +1481,14 @@ const findCircularSchemasMemo = memoize(/* @__PURE__ */ new WeakMap(), (schemas)
|
|
|
1565
1481
|
}
|
|
1566
1482
|
}
|
|
1567
1483
|
return circular;
|
|
1484
|
+
}
|
|
1485
|
+
const findCircularSchemasMemo = memoize(/* @__PURE__ */ new WeakMap(), (schemas) => {
|
|
1486
|
+
const graph = /* @__PURE__ */ new Map();
|
|
1487
|
+
for (const schema of schemas) {
|
|
1488
|
+
if (!schema.name) continue;
|
|
1489
|
+
graph.set(schema.name, collectReferencedSchemaNames(schema));
|
|
1490
|
+
}
|
|
1491
|
+
return findCircularSchemasFromGraph(graph);
|
|
1568
1492
|
});
|
|
1569
1493
|
/**
|
|
1570
1494
|
* Finds every schema that takes part in a circular dependency chain, including direct self-loops.
|
|
@@ -1579,174 +1503,6 @@ function findCircularSchemas(schemas) {
|
|
|
1579
1503
|
if (schemas.length === 0) return EMPTY_CIRCULAR_SET;
|
|
1580
1504
|
return findCircularSchemasMemo(schemas);
|
|
1581
1505
|
}
|
|
1582
|
-
/**
|
|
1583
|
-
* Returns `true` when a schema, or anything nested inside it, references a circular schema.
|
|
1584
|
-
*
|
|
1585
|
-
* Pass `excludeName` to skip refs to a specific schema, which helps when self-references are handled
|
|
1586
|
-
* on their own. Pair it with `findCircularSchemas()` to decide where lazy wrappers go.
|
|
1587
|
-
*
|
|
1588
|
-
* @note Stops at the first matching circular ref.
|
|
1589
|
-
*/
|
|
1590
|
-
function containsCircularRef(node, { circularSchemas, excludeName }) {
|
|
1591
|
-
if (!node || circularSchemas.size === 0) return false;
|
|
1592
|
-
for (const _ of collectLazy(node, { schema(child) {
|
|
1593
|
-
if (child.type !== "ref") return null;
|
|
1594
|
-
const name = resolveRefName(child);
|
|
1595
|
-
return name && name !== excludeName && circularSchemas.has(name) ? true : null;
|
|
1596
|
-
} })) return true;
|
|
1597
|
-
return false;
|
|
1598
|
-
}
|
|
1599
|
-
//#endregion
|
|
1600
|
-
//#region src/macros/macroDiscriminatorEnum.ts
|
|
1601
|
-
/**
|
|
1602
|
-
* Builds a macro that replaces a discriminator property's schema with a string enum of the given
|
|
1603
|
-
* values. Object schemas that lack the property are returned unchanged.
|
|
1604
|
-
*
|
|
1605
|
-
* @example
|
|
1606
|
-
* ```ts
|
|
1607
|
-
* const macro = macroDiscriminatorEnum({ propertyName: 'type', values: ['dog', 'cat'] })
|
|
1608
|
-
* const next = applyMacros(objectSchema, [macro], { depth: 'shallow' })
|
|
1609
|
-
* ```
|
|
1610
|
-
*/
|
|
1611
|
-
function macroDiscriminatorEnum({ propertyName, values, enumName }) {
|
|
1612
|
-
return defineMacro({
|
|
1613
|
-
name: "discriminator-enum",
|
|
1614
|
-
schema(node) {
|
|
1615
|
-
const objectNode = narrowSchema(node, "object");
|
|
1616
|
-
if (!objectNode?.properties?.length) return void 0;
|
|
1617
|
-
if (!objectNode.properties.some((prop) => prop.name === propertyName)) return void 0;
|
|
1618
|
-
return createSchema({
|
|
1619
|
-
...objectNode,
|
|
1620
|
-
properties: objectNode.properties.map((prop) => {
|
|
1621
|
-
if (prop.name !== propertyName) return prop;
|
|
1622
|
-
return createProperty({
|
|
1623
|
-
...prop,
|
|
1624
|
-
schema: createSchema({
|
|
1625
|
-
type: "enum",
|
|
1626
|
-
primitive: "string",
|
|
1627
|
-
enumValues: values,
|
|
1628
|
-
name: enumName,
|
|
1629
|
-
readOnly: prop.schema.readOnly,
|
|
1630
|
-
writeOnly: prop.schema.writeOnly
|
|
1631
|
-
})
|
|
1632
|
-
});
|
|
1633
|
-
})
|
|
1634
|
-
});
|
|
1635
|
-
}
|
|
1636
|
-
});
|
|
1637
|
-
}
|
|
1638
|
-
//#endregion
|
|
1639
|
-
//#region src/macros/macroEnumName.ts
|
|
1640
|
-
/**
|
|
1641
|
-
* Builds a macro that names an inline enum schema from its parent and property name. Boolean enums
|
|
1642
|
-
* are left anonymous. Non-enum nodes are returned unchanged.
|
|
1643
|
-
*
|
|
1644
|
-
* @example
|
|
1645
|
-
* ```ts
|
|
1646
|
-
* const macro = macroEnumName({ parentName: 'Pet', propName: 'status', enumSuffix: 'enum' })
|
|
1647
|
-
* const named = applyMacros(propSchema, [macro], { depth: 'shallow' })
|
|
1648
|
-
* ```
|
|
1649
|
-
*/
|
|
1650
|
-
function macroEnumName({ parentName, propName, enumSuffix }) {
|
|
1651
|
-
return defineMacro({
|
|
1652
|
-
name: "enum-name",
|
|
1653
|
-
schema(node) {
|
|
1654
|
-
const enumNode = narrowSchema(node, "enum");
|
|
1655
|
-
if (enumNode?.primitive === "boolean") return {
|
|
1656
|
-
...node,
|
|
1657
|
-
name: null
|
|
1658
|
-
};
|
|
1659
|
-
if (enumNode) return {
|
|
1660
|
-
...node,
|
|
1661
|
-
name: enumPropName(parentName, propName, enumSuffix)
|
|
1662
|
-
};
|
|
1663
|
-
}
|
|
1664
|
-
});
|
|
1665
|
-
}
|
|
1666
|
-
//#endregion
|
|
1667
|
-
//#region src/macros/macroRenameSchema.ts
|
|
1668
|
-
/**
|
|
1669
|
-
* Builds a macro that renames a schema consistently: the declaration (`name`) and every ref
|
|
1670
|
-
* pointing at it (`targetName`) change together, so imports and printed references stay in
|
|
1671
|
-
* sync. Renaming only one side by hand produces imports for files that are never generated.
|
|
1672
|
-
*
|
|
1673
|
-
* @example
|
|
1674
|
-
* `const macro = macroRenameSchema({ from: 'Order', to: 'StoreOrder' })`
|
|
1675
|
-
*/
|
|
1676
|
-
function macroRenameSchema({ from, to }) {
|
|
1677
|
-
return defineMacro({
|
|
1678
|
-
name: "rename-schema",
|
|
1679
|
-
schema(node) {
|
|
1680
|
-
const refNode = narrowSchema(node, "ref");
|
|
1681
|
-
if (!refNode) return node.name === from ? {
|
|
1682
|
-
...node,
|
|
1683
|
-
name: to
|
|
1684
|
-
} : void 0;
|
|
1685
|
-
const renamesDeclaration = refNode.name === from;
|
|
1686
|
-
const renamesTarget = resolveRefName(refNode) === from;
|
|
1687
|
-
if (!renamesDeclaration && !renamesTarget) return void 0;
|
|
1688
|
-
return {
|
|
1689
|
-
...refNode,
|
|
1690
|
-
...renamesDeclaration ? { name: to } : {},
|
|
1691
|
-
...renamesTarget ? { targetName: to } : {}
|
|
1692
|
-
};
|
|
1693
|
-
}
|
|
1694
|
-
});
|
|
1695
|
-
}
|
|
1696
|
-
//#endregion
|
|
1697
|
-
//#region src/macros/macroSimplifyUnion.ts
|
|
1698
|
-
/**
|
|
1699
|
-
* Scalar primitive schema types used for union simplification and type narrowing.
|
|
1700
|
-
*/
|
|
1701
|
-
const SCALAR_PRIMITIVE_TYPES = /* @__PURE__ */ new Set([
|
|
1702
|
-
"string",
|
|
1703
|
-
"number",
|
|
1704
|
-
"integer",
|
|
1705
|
-
"bigint",
|
|
1706
|
-
"boolean"
|
|
1707
|
-
]);
|
|
1708
|
-
function isScalarPrimitive(type) {
|
|
1709
|
-
return SCALAR_PRIMITIVE_TYPES.has(type);
|
|
1710
|
-
}
|
|
1711
|
-
/**
|
|
1712
|
-
* Filters union members, dropping enum members that a broader scalar primitive already covers.
|
|
1713
|
-
*/
|
|
1714
|
-
function simplifyUnionMembers(members) {
|
|
1715
|
-
const scalarPrimitives = new Set(members.filter((member) => isScalarPrimitive(member.type)).map((m) => m.type));
|
|
1716
|
-
if (!scalarPrimitives.size) return members;
|
|
1717
|
-
return members.filter((member) => {
|
|
1718
|
-
const enumNode = narrowSchema(member, "enum");
|
|
1719
|
-
if (!enumNode) return true;
|
|
1720
|
-
const primitive = enumNode.primitive;
|
|
1721
|
-
if (!primitive) return true;
|
|
1722
|
-
if ((enumNode.namedEnumValues?.length ?? enumNode.enumValues?.length ?? 0) <= 1) return true;
|
|
1723
|
-
if (scalarPrimitives.has(primitive)) return false;
|
|
1724
|
-
if ((primitive === "integer" || primitive === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
1725
|
-
return true;
|
|
1726
|
-
});
|
|
1727
|
-
}
|
|
1728
|
-
/**
|
|
1729
|
-
* Removes union members a broader scalar primitive already covers, such as a multi-value string enum
|
|
1730
|
-
* sitting next to a plain `string`. Single-value enums are kept.
|
|
1731
|
-
*
|
|
1732
|
-
* @example
|
|
1733
|
-
* ```ts
|
|
1734
|
-
* const next = applyMacros(unionSchema, [macroSimplifyUnion], { depth: 'shallow' })
|
|
1735
|
-
* ```
|
|
1736
|
-
*/
|
|
1737
|
-
const macroSimplifyUnion = defineMacro({
|
|
1738
|
-
name: "simplify-union",
|
|
1739
|
-
schema(node) {
|
|
1740
|
-
const unionNode = narrowSchema(node, "union");
|
|
1741
|
-
if (!unionNode?.members?.length) return void 0;
|
|
1742
|
-
const simplified = simplifyUnionMembers(unionNode.members);
|
|
1743
|
-
if (simplified.length === unionNode.members.length) return void 0;
|
|
1744
|
-
return {
|
|
1745
|
-
...unionNode,
|
|
1746
|
-
members: simplified
|
|
1747
|
-
};
|
|
1748
|
-
}
|
|
1749
|
-
});
|
|
1750
1506
|
//#endregion
|
|
1751
1507
|
//#region src/factory.ts
|
|
1752
1508
|
var factory_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1801,37 +1557,27 @@ var exports_exports = /* @__PURE__ */ __exportAll({
|
|
|
1801
1557
|
applyMacros: () => applyMacros,
|
|
1802
1558
|
arrowFunctionDef: () => arrowFunctionDef,
|
|
1803
1559
|
breakDef: () => breakDef,
|
|
1804
|
-
childName: () => childName,
|
|
1805
1560
|
collect: () => collect,
|
|
1561
|
+
collectImportedRefNames: () => collectImportedRefNames,
|
|
1562
|
+
collectSync: () => collectSync,
|
|
1806
1563
|
collectUsedSchemaNames: () => collectUsedSchemaNames,
|
|
1807
|
-
combineExports: () => combineExports,
|
|
1808
|
-
combineImports: () => combineImports,
|
|
1809
|
-
combineSources: () => combineSources,
|
|
1810
1564
|
composeMacros: () => composeMacros,
|
|
1811
1565
|
constDef: () => constDef,
|
|
1812
|
-
containsCircularRef: () => containsCircularRef,
|
|
1813
1566
|
contentDef: () => contentDef,
|
|
1814
1567
|
createPrinter: () => createPrinter,
|
|
1815
1568
|
defineMacro: () => defineMacro,
|
|
1816
1569
|
defineNode: () => defineNode,
|
|
1817
|
-
enumPropName: () => enumPropName,
|
|
1818
1570
|
exportDef: () => exportDef,
|
|
1819
|
-
extractRefName: () => extractRefName,
|
|
1820
1571
|
extractStringsFromNodes: () => extractStringsFromNodes,
|
|
1821
1572
|
factory: () => factory_exports,
|
|
1822
1573
|
fileDef: () => fileDef,
|
|
1823
1574
|
findCircularSchemas: () => findCircularSchemas,
|
|
1575
|
+
findCircularSchemasFromGraph: () => findCircularSchemasFromGraph,
|
|
1824
1576
|
functionDef: () => functionDef,
|
|
1825
1577
|
importDef: () => importDef,
|
|
1826
1578
|
inputDef: () => inputDef,
|
|
1827
1579
|
isHttpOperationNode: () => isHttpOperationNode,
|
|
1828
|
-
isStringType: () => isStringType,
|
|
1829
1580
|
jsxDef: () => jsxDef,
|
|
1830
|
-
macroDiscriminatorEnum: () => macroDiscriminatorEnum,
|
|
1831
|
-
macroEnumName: () => macroEnumName,
|
|
1832
|
-
macroRenameSchema: () => macroRenameSchema,
|
|
1833
|
-
macroSimplifyUnion: () => macroSimplifyUnion,
|
|
1834
|
-
mergeAdjacentObjectsLazy: () => mergeAdjacentObjectsLazy,
|
|
1835
1581
|
narrowSchema: () => narrowSchema,
|
|
1836
1582
|
nodeDefs: () => nodeDefs,
|
|
1837
1583
|
operationDef: () => operationDef,
|
|
@@ -1845,12 +1591,11 @@ var exports_exports = /* @__PURE__ */ __exportAll({
|
|
|
1845
1591
|
schemaDef: () => schemaDef,
|
|
1846
1592
|
schemaTypes: () => schemaTypes,
|
|
1847
1593
|
sourceDef: () => sourceDef,
|
|
1848
|
-
syncSchemaRef: () => syncSchemaRef,
|
|
1849
1594
|
textDef: () => textDef,
|
|
1850
1595
|
transform: () => transform,
|
|
1851
1596
|
typeDef: () => typeDef
|
|
1852
1597
|
});
|
|
1853
1598
|
//#endregion
|
|
1854
|
-
export { applyMacros, arrowFunctionDef, exports_exports as ast, breakDef,
|
|
1599
|
+
export { applyMacros, arrowFunctionDef, exports_exports as ast, breakDef, collect, collectImportedRefNames, collectSync, collectUsedSchemaNames, composeMacros, constDef, contentDef, createPrinter, defineMacro, defineNode, exportDef, extractStringsFromNodes, factory_exports as factory, fileDef, findCircularSchemas, findCircularSchemasFromGraph, functionDef, importDef, inputDef, isHttpOperationNode, jsxDef, narrowSchema, nodeDefs, operationDef, optionality, outputDef, parameterDef, propertyDef, requestBodyDef, resolveRefName, responseDef, schemaDef, schemaTypes, sourceDef, textDef, transform, typeDef };
|
|
1855
1600
|
|
|
1856
1601
|
//# sourceMappingURL=index.js.map
|