@kubb/ast 5.0.0-beta.53 → 5.0.0-beta.55
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/index.cjs +75 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -26
- package/dist/index.js +74 -106
- package/dist/index.js.map +1 -1
- package/dist/{types-IHUK_alM.d.ts → types-BL7RpQAE.d.ts} +141 -172
- package/dist/types.d.ts +2 -2
- package/dist/{utils-BIcKgbbc.js → utils-0p8ZO287.js} +15 -71
- package/dist/utils-0p8ZO287.js.map +1 -0
- package/dist/{utils-CMRZrT-w.cjs → utils-cdQ6Pzyi.cjs} +14 -82
- package/dist/utils-cdQ6Pzyi.cjs.map +1 -0
- package/dist/utils.cjs +1 -2
- package/dist/utils.d.ts +1 -14
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/src/dedupe.ts +47 -16
- package/src/dialect.ts +23 -28
- package/src/factory.ts +2 -3
- package/src/index.ts +1 -3
- package/src/mocks.ts +1 -1
- package/src/nodes/index.ts +6 -4
- package/src/nodes/{root.ts → input.ts} +16 -39
- package/src/nodes/operation.ts +1 -41
- package/src/nodes/requestBody.ts +42 -0
- package/src/signature.ts +23 -48
- package/src/types.ts +1 -3
- package/src/utils/index.ts +3 -1
- package/dist/utils-BIcKgbbc.js.map +0 -1
- package/dist/utils-CMRZrT-w.cjs.map +0 -1
- package/src/dispatch.ts +0 -53
- package/src/resolvers.ts +0 -31
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_utils = require("./utils-
|
|
2
|
+
const require_utils = require("./utils-cdQ6Pzyi.cjs");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
node_path = require_utils.__toESM(node_path, 1);
|
|
6
|
+
//#region ../../internals/utils/src/fs.ts
|
|
7
|
+
/**
|
|
8
|
+
* Strips the file extension from a path or file name.
|
|
9
|
+
* Only removes the last `.ext` segment when the dot is not part of a directory name.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* trimExtName('petStore.ts') // 'petStore'
|
|
13
|
+
* trimExtName('/src/models/pet.ts') // '/src/models/pet'
|
|
14
|
+
* trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
|
|
15
|
+
* trimExtName('noExtension') // 'noExtension'
|
|
16
|
+
*/
|
|
17
|
+
function trimExtName(text) {
|
|
18
|
+
const dotIndex = text.lastIndexOf(".");
|
|
19
|
+
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
20
|
+
return text;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
6
23
|
//#region ../../internals/utils/src/promise.ts
|
|
7
24
|
/**
|
|
8
25
|
* Wraps `factory` with a keyed cache backed by the provided store.
|
|
@@ -1055,7 +1072,7 @@ function createInput(overrides = {}) {
|
|
|
1055
1072
|
};
|
|
1056
1073
|
}
|
|
1057
1074
|
/**
|
|
1058
|
-
* Creates
|
|
1075
|
+
* Creates a streaming `InputNode<true>` from pre-built `AsyncIterable` sources.
|
|
1059
1076
|
*
|
|
1060
1077
|
* @example
|
|
1061
1078
|
* ```ts
|
|
@@ -1482,7 +1499,7 @@ function createFile(input) {
|
|
|
1482
1499
|
kind: "File",
|
|
1483
1500
|
...input,
|
|
1484
1501
|
id: (0, node_crypto.hash)("sha256", input.path, "hex"),
|
|
1485
|
-
name:
|
|
1502
|
+
name: trimExtName(input.baseName),
|
|
1486
1503
|
extname,
|
|
1487
1504
|
imports: resolvedImports,
|
|
1488
1505
|
exports: resolvedExports,
|
|
@@ -1678,9 +1695,7 @@ function createJsx(value) {
|
|
|
1678
1695
|
//#endregion
|
|
1679
1696
|
//#region src/signature.ts
|
|
1680
1697
|
/**
|
|
1681
|
-
* The
|
|
1682
|
-
* Documentation and usage-slot flags (`optional`/`nullish`/`readOnly`/`writeOnly`) are
|
|
1683
|
-
* intentionally excluded, they describe the property slot, not the type.
|
|
1698
|
+
* The flags shared by every node kind that affect its type: `primitive`, `format`, `nullable`.
|
|
1684
1699
|
*/
|
|
1685
1700
|
function flagsDescriptor(node) {
|
|
1686
1701
|
return `${node.primitive ?? ""};${node.format ?? ""};${node.nullable ? 1 : 0}`;
|
|
@@ -1753,9 +1768,8 @@ const rangeFields = [{
|
|
|
1753
1768
|
prefix: "mx"
|
|
1754
1769
|
}];
|
|
1755
1770
|
/**
|
|
1756
|
-
* Maps each
|
|
1757
|
-
*
|
|
1758
|
-
* back to `${type}|${flags}` with no additional fields.
|
|
1771
|
+
* Maps each node `type` to its ordered shape-contributing fields. Types absent from the map
|
|
1772
|
+
* (boolean, null, any, and other scalars) fall back to `${type}|${flags}`.
|
|
1759
1773
|
*/
|
|
1760
1774
|
const SHAPE_KEYS = {
|
|
1761
1775
|
object: [
|
|
@@ -1892,9 +1906,8 @@ function serializeShapeField(field, node, record) {
|
|
|
1892
1906
|
}
|
|
1893
1907
|
}
|
|
1894
1908
|
/**
|
|
1895
|
-
* Builds the local
|
|
1896
|
-
* children's signatures.
|
|
1897
|
-
* fixed-length signature rather than their own full descriptor, which keeps the result bounded.
|
|
1909
|
+
* Builds the local shape descriptor that {@link signatureOf} hashes: the node's kind, flags,
|
|
1910
|
+
* constraints, and its children's signatures.
|
|
1898
1911
|
*/
|
|
1899
1912
|
function describeShape(node) {
|
|
1900
1913
|
const flags = flagsDescriptor(node);
|
|
@@ -1906,22 +1919,23 @@ function describeShape(node) {
|
|
|
1906
1919
|
return parts.join("|");
|
|
1907
1920
|
}
|
|
1908
1921
|
/**
|
|
1909
|
-
*
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1912
|
-
* during dedupe planning is not re-hashed when the same tree is rewritten during streaming
|
|
1913
|
-
* (where `schemaSignature` and `applyDedupe` would otherwise each walk it from scratch). Reuse
|
|
1914
|
-
* across calls is sound because a signature depends only on a node's content, and schema nodes
|
|
1915
|
-
* are immutable once created, transforms allocate new objects rather than mutating in place.
|
|
1922
|
+
* Node → digest cache, keyed by identity. A `WeakMap` so entries die with the node, and so a tree
|
|
1923
|
+
* hashed during dedupe planning is not walked again when it is rewritten during streaming. Reuse
|
|
1924
|
+
* is safe because a signature depends only on content, and nodes are immutable once created.
|
|
1916
1925
|
*/
|
|
1917
1926
|
const signatureCache = /* @__PURE__ */ new WeakMap();
|
|
1918
1927
|
/**
|
|
1919
|
-
*
|
|
1920
|
-
*
|
|
1921
|
-
*
|
|
1922
|
-
*
|
|
1923
|
-
*
|
|
1924
|
-
*
|
|
1928
|
+
* Computes a deterministic, shape-only signature (a content hash) for a schema node. Two schemas
|
|
1929
|
+
* share a signature when they are structurally identical, ignoring documentation (`name`, `title`,
|
|
1930
|
+
* `description`, `example`, `default`, `deprecated`) and usage-slot flags (`optional`, `nullish`,
|
|
1931
|
+
* `readOnly`, `writeOnly`). `nullable` is kept because it changes the produced type, and `ref`
|
|
1932
|
+
* nodes compare by target name, which also terminates on circular shapes.
|
|
1933
|
+
*
|
|
1934
|
+
* @example Two enums with different descriptions share a signature
|
|
1935
|
+
* ```ts
|
|
1936
|
+
* signatureOf(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'], description: 'x' })) ===
|
|
1937
|
+
* signatureOf(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'] }))
|
|
1938
|
+
* ```
|
|
1925
1939
|
*/
|
|
1926
1940
|
function signatureOf(node) {
|
|
1927
1941
|
const cached = signatureCache.get(node);
|
|
@@ -1930,24 +1944,6 @@ function signatureOf(node) {
|
|
|
1930
1944
|
signatureCache.set(node, signature);
|
|
1931
1945
|
return signature;
|
|
1932
1946
|
}
|
|
1933
|
-
/**
|
|
1934
|
-
* Computes a deterministic, shape-only signature (a fixed-length content hash) for a schema node.
|
|
1935
|
-
*
|
|
1936
|
-
* Two schemas share a signature when they are structurally identical, ignoring
|
|
1937
|
-
* documentation (`name`, `title`, `description`, `example`, `default`, `deprecated`)
|
|
1938
|
-
* and usage-slot flags (`optional`, `nullish`, `readOnly`, `writeOnly`). `nullable`
|
|
1939
|
-
* is kept because it changes the produced type. `ref` nodes compare by target name,
|
|
1940
|
-
* which also keeps the algorithm terminating on circular shapes.
|
|
1941
|
-
*
|
|
1942
|
-
* @example Two enums with different descriptions share a signature
|
|
1943
|
-
* ```ts
|
|
1944
|
-
* schemaSignature(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'], description: 'x' })) ===
|
|
1945
|
-
* schemaSignature(createSchema({ type: 'enum', primitive: 'string', enumValues: ['a', 'b'] }))
|
|
1946
|
-
* ```
|
|
1947
|
-
*/
|
|
1948
|
-
function schemaSignature(node) {
|
|
1949
|
-
return signatureOf(node);
|
|
1950
|
-
}
|
|
1951
1947
|
//#endregion
|
|
1952
1948
|
//#region src/dedupe.ts
|
|
1953
1949
|
/**
|
|
@@ -1969,10 +1965,20 @@ function createRefNode(node, canonical) {
|
|
|
1969
1965
|
example: node.example
|
|
1970
1966
|
});
|
|
1971
1967
|
}
|
|
1972
|
-
function applyDedupe(node,
|
|
1973
|
-
|
|
1968
|
+
function applyDedupe(node, plan, skipRootMatch = false) {
|
|
1969
|
+
const { canonicalBySignature, aliasNames } = plan;
|
|
1970
|
+
if (canonicalBySignature.size === 0 && aliasNames.size === 0) return node;
|
|
1974
1971
|
const root = node;
|
|
1975
1972
|
return transform(node, { schema(schemaNode) {
|
|
1973
|
+
if (schemaNode.type === "ref") {
|
|
1974
|
+
const target = schemaNode.ref ? require_utils.extractRefName(schemaNode.ref) : schemaNode.name;
|
|
1975
|
+
const canonical = target ? aliasNames.get(target) : void 0;
|
|
1976
|
+
return canonical ? {
|
|
1977
|
+
...schemaNode,
|
|
1978
|
+
name: canonical.name,
|
|
1979
|
+
ref: canonical.ref
|
|
1980
|
+
} : void 0;
|
|
1981
|
+
}
|
|
1976
1982
|
const signature = signatureOf(schemaNode);
|
|
1977
1983
|
if (skipRootMatch && schemaNode === root) return void 0;
|
|
1978
1984
|
const canonical = canonicalBySignature.get(signature);
|
|
@@ -1996,9 +2002,11 @@ function cleanDefinition(node, name) {
|
|
|
1996
2002
|
* Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
|
|
1997
2003
|
*
|
|
1998
2004
|
* A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
|
|
1999
|
-
* is a named top-level schema,
|
|
2000
|
-
* and inline copies turn into references to it).
|
|
2001
|
-
*
|
|
2005
|
+
* is a named top-level schema, the first one becomes the canonical (so other top-level
|
|
2006
|
+
* duplicates and inline copies turn into references to it). Every other top-level name with
|
|
2007
|
+
* the same content is recorded in `aliasNames`, so refs to it can be repointed at the
|
|
2008
|
+
* canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
|
|
2009
|
+
* per node with {@link applyDedupe}.
|
|
2002
2010
|
*
|
|
2003
2011
|
* @example
|
|
2004
2012
|
* ```ts
|
|
@@ -2020,11 +2028,11 @@ function buildDedupePlan(roots, options) {
|
|
|
2020
2028
|
const group = groups.get(signature);
|
|
2021
2029
|
if (group) {
|
|
2022
2030
|
group.count++;
|
|
2023
|
-
if (isTopLevel
|
|
2031
|
+
if (isTopLevel) group.topLevelNames.push(schemaNode.name);
|
|
2024
2032
|
} else groups.set(signature, {
|
|
2025
2033
|
count: 1,
|
|
2026
2034
|
representative: schemaNode,
|
|
2027
|
-
|
|
2035
|
+
topLevelNames: isTopLevel ? [schemaNode.name] : []
|
|
2028
2036
|
});
|
|
2029
2037
|
}
|
|
2030
2038
|
for (const root of roots) {
|
|
@@ -2032,14 +2040,18 @@ function buildDedupePlan(roots, options) {
|
|
|
2032
2040
|
for (const schemaNode of collectLazy(root, { schema: (node) => node })) record(schemaNode);
|
|
2033
2041
|
}
|
|
2034
2042
|
const canonicalBySignature = /* @__PURE__ */ new Map();
|
|
2043
|
+
const aliasNames = /* @__PURE__ */ new Map();
|
|
2035
2044
|
const pendingHoists = [];
|
|
2036
2045
|
for (const [signature, group] of groups) {
|
|
2037
2046
|
if (group.count < minOccurrences) continue;
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2047
|
+
const [firstName, ...duplicateNames] = group.topLevelNames;
|
|
2048
|
+
if (firstName) {
|
|
2049
|
+
const canonical = {
|
|
2050
|
+
name: firstName,
|
|
2051
|
+
ref: refFor(firstName)
|
|
2052
|
+
};
|
|
2053
|
+
canonicalBySignature.set(signature, canonical);
|
|
2054
|
+
for (const duplicate of duplicateNames) aliasNames.set(duplicate, canonical);
|
|
2043
2055
|
continue;
|
|
2044
2056
|
}
|
|
2045
2057
|
const name = nameFor(group.representative, signature);
|
|
@@ -2055,15 +2067,18 @@ function buildDedupePlan(roots, options) {
|
|
|
2055
2067
|
}
|
|
2056
2068
|
return {
|
|
2057
2069
|
canonicalBySignature,
|
|
2058
|
-
|
|
2070
|
+
aliasNames,
|
|
2071
|
+
hoisted: pendingHoists.map(({ name, representative }) => cleanDefinition(applyDedupe(representative, {
|
|
2072
|
+
canonicalBySignature,
|
|
2073
|
+
aliasNames
|
|
2074
|
+
}, true), name))
|
|
2059
2075
|
};
|
|
2060
2076
|
}
|
|
2061
2077
|
//#endregion
|
|
2062
2078
|
//#region src/dialect.ts
|
|
2063
2079
|
/**
|
|
2064
|
-
*
|
|
2065
|
-
*
|
|
2066
|
-
* inference and gives adapter authors a discoverable anchor.
|
|
2080
|
+
* Types a {@link SchemaDialect} for an adapter. Adds no runtime behavior and only pins the
|
|
2081
|
+
* dialect's type for inference.
|
|
2067
2082
|
*
|
|
2068
2083
|
* @example
|
|
2069
2084
|
* ```ts
|
|
@@ -2081,38 +2096,6 @@ function defineSchemaDialect(dialect) {
|
|
|
2081
2096
|
return dialect;
|
|
2082
2097
|
}
|
|
2083
2098
|
//#endregion
|
|
2084
|
-
//#region src/dispatch.ts
|
|
2085
|
-
/**
|
|
2086
|
-
* Walks an ordered list of {@link DispatchRule}s and returns the first node produced.
|
|
2087
|
-
*
|
|
2088
|
-
* This is the shared backbone for spec adapters (OpenAPI today, AsyncAPI and others later).
|
|
2089
|
-
* The contract an adapter follows is intentionally minimal:
|
|
2090
|
-
*
|
|
2091
|
-
* context → [rule.match → rule.convert] → node
|
|
2092
|
-
*
|
|
2093
|
-
* An adapter derives a context from a source spec node, then declares an ordered table of
|
|
2094
|
-
* rules mapping spec shapes onto Kubb AST nodes. To add support for a new spec, write a new
|
|
2095
|
-
* context type and a new rules table, the traversal here is reused unchanged.
|
|
2096
|
-
*
|
|
2097
|
-
* Order is significant: earlier rules win, so list higher-precedence or more specific shapes
|
|
2098
|
-
* first (e.g. composition keywords before plain `type`). A rule whose `match` returns `true`
|
|
2099
|
-
* may still `convert` to `null` to defer to later rules. When no rule produces a node this
|
|
2100
|
-
* returns `null`, leaving the caller to apply its own fallback.
|
|
2101
|
-
*
|
|
2102
|
-
* @example
|
|
2103
|
-
* ```ts
|
|
2104
|
-
* const node = dispatch(schemaRules, schemaContext) ?? createSchema({ type: fallbackType })
|
|
2105
|
-
* ```
|
|
2106
|
-
*/
|
|
2107
|
-
function dispatch(rules, context) {
|
|
2108
|
-
for (const rule of rules) {
|
|
2109
|
-
if (!rule.match(context)) continue;
|
|
2110
|
-
const node = rule.convert(context);
|
|
2111
|
-
if (node !== null && node !== void 0) return node;
|
|
2112
|
-
}
|
|
2113
|
-
return null;
|
|
2114
|
-
}
|
|
2115
|
-
//#endregion
|
|
2116
2099
|
//#region src/printer.ts
|
|
2117
2100
|
/**
|
|
2118
2101
|
* Defines a schema printer: a function that takes a `SchemaNode` and emits
|
|
@@ -2190,21 +2173,6 @@ function createPrinterFactory(getKey) {
|
|
|
2190
2173
|
};
|
|
2191
2174
|
}
|
|
2192
2175
|
//#endregion
|
|
2193
|
-
//#region src/resolvers.ts
|
|
2194
|
-
/**
|
|
2195
|
-
* Collects import entries for all `ref` schema nodes in `node`.
|
|
2196
|
-
*/
|
|
2197
|
-
function collectImports({ node, nameMapping, resolve }) {
|
|
2198
|
-
return collect(node, { schema(schemaNode) {
|
|
2199
|
-
const schemaRef = narrowSchema(schemaNode, "ref");
|
|
2200
|
-
if (!schemaRef?.ref) return null;
|
|
2201
|
-
const rawName = require_utils.extractRefName(schemaRef.ref);
|
|
2202
|
-
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
2203
|
-
if (!result) return null;
|
|
2204
|
-
return result;
|
|
2205
|
-
} });
|
|
2206
|
-
}
|
|
2207
|
-
//#endregion
|
|
2208
2176
|
//#region src/transformers.ts
|
|
2209
2177
|
/**
|
|
2210
2178
|
* Replaces a discriminator property's schema with a string enum of allowed values.
|
|
@@ -2316,7 +2284,6 @@ exports.applyDedupe = applyDedupe;
|
|
|
2316
2284
|
exports.buildDedupePlan = buildDedupePlan;
|
|
2317
2285
|
exports.caseParams = caseParams;
|
|
2318
2286
|
exports.collect = collect;
|
|
2319
|
-
exports.collectImports = collectImports;
|
|
2320
2287
|
exports.collectUsedSchemaNames = collectUsedSchemaNames;
|
|
2321
2288
|
exports.containsCircularRef = containsCircularRef;
|
|
2322
2289
|
exports.createArrowFunction = createArrowFunction;
|
|
@@ -2347,7 +2314,6 @@ exports.createText = createText;
|
|
|
2347
2314
|
exports.createType = createType;
|
|
2348
2315
|
exports.definePrinter = definePrinter;
|
|
2349
2316
|
exports.defineSchemaDialect = defineSchemaDialect;
|
|
2350
|
-
exports.dispatch = dispatch;
|
|
2351
2317
|
exports.extractStringsFromNodes = extractStringsFromNodes;
|
|
2352
2318
|
exports.findCircularSchemas = findCircularSchemas;
|
|
2353
2319
|
exports.httpMethods = require_utils.httpMethods;
|
|
@@ -2359,10 +2325,10 @@ exports.isSchemaNode = isSchemaNode;
|
|
|
2359
2325
|
exports.isStringType = isStringType;
|
|
2360
2326
|
exports.mergeAdjacentObjectsLazy = mergeAdjacentObjectsLazy;
|
|
2361
2327
|
exports.narrowSchema = narrowSchema;
|
|
2362
|
-
exports.schemaSignature = schemaSignature;
|
|
2363
2328
|
exports.schemaTypes = require_utils.schemaTypes;
|
|
2364
2329
|
exports.setDiscriminatorEnum = setDiscriminatorEnum;
|
|
2365
2330
|
exports.setEnumName = setEnumName;
|
|
2331
|
+
exports.signatureOf = signatureOf;
|
|
2366
2332
|
exports.simplifyUnion = simplifyUnion;
|
|
2367
2333
|
exports.syncOptionality = syncOptionality;
|
|
2368
2334
|
exports.syncSchemaRef = syncSchemaRef;
|