@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
|
@@ -1567,6 +1567,22 @@ type FunctionParamNode = FunctionParameterNode | ParameterGroupNode | FunctionPa
|
|
|
1567
1567
|
*/
|
|
1568
1568
|
type FunctionNodeType = 'functionParameter' | 'parameterGroup' | 'functionParameters' | 'paramsType';
|
|
1569
1569
|
//#endregion
|
|
1570
|
+
//#region ../../internals/utils/src/promise.d.ts
|
|
1571
|
+
/**
|
|
1572
|
+
* Container that switches between an eager `Array<T>` and a lazy `AsyncIterable<T>`.
|
|
1573
|
+
*
|
|
1574
|
+
* `Array<T>` by default. With `Stream` set to `true` it becomes `AsyncIterable<T>`, so large
|
|
1575
|
+
* collections can be produced lazily without holding every item in memory. Pairs with
|
|
1576
|
+
* {@link arrayToAsyncIterable}, which lifts a plain array into the streaming form.
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* ```ts
|
|
1580
|
+
* type Eager = Streamable<number> // Array<number>
|
|
1581
|
+
* type Lazy = Streamable<number, true> // AsyncIterable<number>
|
|
1582
|
+
* ```
|
|
1583
|
+
*/
|
|
1584
|
+
type Streamable<T, Stream extends boolean = false> = Stream extends true ? AsyncIterable<T> : Array<T>;
|
|
1585
|
+
//#endregion
|
|
1570
1586
|
//#region src/nodes/parameter.d.ts
|
|
1571
1587
|
type ParameterLocation = 'path' | 'query' | 'header' | 'cookie';
|
|
1572
1588
|
/**
|
|
@@ -1606,6 +1622,47 @@ type ParameterNode = BaseNode & {
|
|
|
1606
1622
|
required: boolean;
|
|
1607
1623
|
};
|
|
1608
1624
|
//#endregion
|
|
1625
|
+
//#region src/nodes/requestBody.d.ts
|
|
1626
|
+
/**
|
|
1627
|
+
* AST node representing an operation request body.
|
|
1628
|
+
*
|
|
1629
|
+
* Body schemas live exclusively inside the `content` array (one entry per content type),
|
|
1630
|
+
* mirroring {@link ResponseNode}.
|
|
1631
|
+
*
|
|
1632
|
+
* @example
|
|
1633
|
+
* ```ts
|
|
1634
|
+
* const requestBody: RequestBodyNode = {
|
|
1635
|
+
* kind: 'RequestBody',
|
|
1636
|
+
* required: true,
|
|
1637
|
+
* content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
|
|
1638
|
+
* }
|
|
1639
|
+
* ```
|
|
1640
|
+
*/
|
|
1641
|
+
type RequestBodyNode = BaseNode & {
|
|
1642
|
+
/**
|
|
1643
|
+
* Node kind.
|
|
1644
|
+
*/
|
|
1645
|
+
kind: 'RequestBody';
|
|
1646
|
+
/**
|
|
1647
|
+
* Human-readable request body description.
|
|
1648
|
+
*/
|
|
1649
|
+
description?: string;
|
|
1650
|
+
/**
|
|
1651
|
+
* Whether the request body is required (`requestBody.required: true` in the spec).
|
|
1652
|
+
* When `false` or absent, the generated `data` parameter should be optional.
|
|
1653
|
+
*/
|
|
1654
|
+
required?: boolean;
|
|
1655
|
+
/**
|
|
1656
|
+
* All available content type entries for this request body.
|
|
1657
|
+
*
|
|
1658
|
+
* When the adapter `contentType` option is set, this array contains exactly one entry for
|
|
1659
|
+
* that content type. Otherwise it contains one entry per content type declared in the spec,
|
|
1660
|
+
* so that plugins can generate code for every variant (e.g. separate hooks for
|
|
1661
|
+
* `application/json` and `multipart/form-data`).
|
|
1662
|
+
*/
|
|
1663
|
+
content?: Array<ContentNode>;
|
|
1664
|
+
};
|
|
1665
|
+
//#endregion
|
|
1609
1666
|
//#region src/nodes/http.d.ts
|
|
1610
1667
|
/**
|
|
1611
1668
|
* All supported HTTP status code literals as strings, as used in API specs
|
|
@@ -1679,45 +1736,6 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTION
|
|
|
1679
1736
|
* Transport an operation belongs to.
|
|
1680
1737
|
*/
|
|
1681
1738
|
type OperationProtocol = 'http';
|
|
1682
|
-
/**
|
|
1683
|
-
* AST node representing an operation request body.
|
|
1684
|
-
*
|
|
1685
|
-
* Body schemas live exclusively inside the `content` array (one entry per content type),
|
|
1686
|
-
* mirroring {@link ResponseNode}.
|
|
1687
|
-
*
|
|
1688
|
-
* @example
|
|
1689
|
-
* ```ts
|
|
1690
|
-
* const requestBody: RequestBodyNode = {
|
|
1691
|
-
* kind: 'RequestBody',
|
|
1692
|
-
* required: true,
|
|
1693
|
-
* content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
|
|
1694
|
-
* }
|
|
1695
|
-
* ```
|
|
1696
|
-
*/
|
|
1697
|
-
type RequestBodyNode = BaseNode & {
|
|
1698
|
-
/**
|
|
1699
|
-
* Node kind.
|
|
1700
|
-
*/
|
|
1701
|
-
kind: 'RequestBody';
|
|
1702
|
-
/**
|
|
1703
|
-
* Human-readable request body description.
|
|
1704
|
-
*/
|
|
1705
|
-
description?: string;
|
|
1706
|
-
/**
|
|
1707
|
-
* Whether the request body is required (`requestBody.required: true` in the spec).
|
|
1708
|
-
* When `false` or absent, the generated `data` parameter should be optional.
|
|
1709
|
-
*/
|
|
1710
|
-
required?: boolean;
|
|
1711
|
-
/**
|
|
1712
|
-
* All available content type entries for this request body.
|
|
1713
|
-
*
|
|
1714
|
-
* When the adapter `contentType` option is set, this array contains exactly one entry for
|
|
1715
|
-
* that content type. Otherwise it contains one entry per content type declared in the spec,
|
|
1716
|
-
* so that plugins can generate code for every variant (e.g. separate hooks for
|
|
1717
|
-
* `application/json` and `multipart/form-data`).
|
|
1718
|
-
*/
|
|
1719
|
-
content?: Array<ContentNode>;
|
|
1720
|
-
};
|
|
1721
1739
|
/**
|
|
1722
1740
|
* Fields shared by every operation, regardless of transport.
|
|
1723
1741
|
*/
|
|
@@ -1811,32 +1829,7 @@ type GenericOperationNode = OperationNodeBase & {
|
|
|
1811
1829
|
*/
|
|
1812
1830
|
type OperationNode = HttpOperationNode | GenericOperationNode;
|
|
1813
1831
|
//#endregion
|
|
1814
|
-
//#region src/nodes/
|
|
1815
|
-
/**
|
|
1816
|
-
* Output AST node that groups all generated file output for one API document.
|
|
1817
|
-
*
|
|
1818
|
-
* Produced by generators and consumed by the build pipeline to write files.
|
|
1819
|
-
*
|
|
1820
|
-
* @example
|
|
1821
|
-
* ```ts
|
|
1822
|
-
* const output: OutputNode = {
|
|
1823
|
-
* kind: 'Output',
|
|
1824
|
-
* files: [],
|
|
1825
|
-
* }
|
|
1826
|
-
* ```
|
|
1827
|
-
*/
|
|
1828
|
-
type OutputNode = BaseNode & {
|
|
1829
|
-
/**
|
|
1830
|
-
* Node kind.
|
|
1831
|
-
*/
|
|
1832
|
-
kind: 'Output';
|
|
1833
|
-
/**
|
|
1834
|
-
* Generated file nodes.
|
|
1835
|
-
*/
|
|
1836
|
-
files: Array<FileNode>;
|
|
1837
|
-
};
|
|
1838
|
-
//#endregion
|
|
1839
|
-
//#region src/nodes/root.d.ts
|
|
1832
|
+
//#region src/nodes/input.d.ts
|
|
1840
1833
|
/**
|
|
1841
1834
|
* Metadata for an API document, populated by the adapter and available to every generator.
|
|
1842
1835
|
*
|
|
@@ -1899,16 +1892,28 @@ type InputMeta = {
|
|
|
1899
1892
|
* Input AST node that contains all schemas and operations for one API document.
|
|
1900
1893
|
* Produced by the adapter and consumed by all Kubb plugins.
|
|
1901
1894
|
*
|
|
1895
|
+
* `Stream` switches `schemas` and `operations` between eager `Array`s (the default) and lazy
|
|
1896
|
+
* `AsyncIterable`s. The streaming variant `InputNode<true>` yields nodes one at a time and makes
|
|
1897
|
+
* `meta` optional, since the adapter can emit metadata before the first node is parsed.
|
|
1898
|
+
*
|
|
1902
1899
|
* @example
|
|
1903
1900
|
* ```ts
|
|
1904
1901
|
* const input: InputNode = {
|
|
1905
1902
|
* kind: 'Input',
|
|
1906
1903
|
* schemas: [],
|
|
1907
1904
|
* operations: [],
|
|
1905
|
+
* meta: { circularNames: [], enumNames: [] },
|
|
1906
|
+
* }
|
|
1907
|
+
* ```
|
|
1908
|
+
*
|
|
1909
|
+
* @example Streaming variant for large specs
|
|
1910
|
+
* ```ts
|
|
1911
|
+
* for await (const schema of inputNode.schemas) {
|
|
1912
|
+
* // only this one SchemaNode is live here. Previous ones are GC-eligible
|
|
1908
1913
|
* }
|
|
1909
1914
|
* ```
|
|
1910
1915
|
*/
|
|
1911
|
-
type InputNode = BaseNode & {
|
|
1916
|
+
type InputNode<Stream extends boolean = false> = BaseNode & {
|
|
1912
1917
|
/**
|
|
1913
1918
|
* Node kind.
|
|
1914
1919
|
*/
|
|
@@ -1916,46 +1921,40 @@ type InputNode = BaseNode & {
|
|
|
1916
1921
|
/**
|
|
1917
1922
|
* All schema nodes in the document.
|
|
1918
1923
|
*/
|
|
1919
|
-
schemas:
|
|
1924
|
+
schemas: Streamable<SchemaNode, Stream>;
|
|
1920
1925
|
/**
|
|
1921
1926
|
* All operation nodes in the document.
|
|
1922
1927
|
*/
|
|
1923
|
-
operations:
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1928
|
+
operations: Streamable<OperationNode, Stream>;
|
|
1929
|
+
} & (Stream extends true ? {
|
|
1930
|
+
meta?: InputMeta;
|
|
1931
|
+
} : {
|
|
1927
1932
|
meta: InputMeta;
|
|
1928
|
-
};
|
|
1933
|
+
});
|
|
1934
|
+
//#endregion
|
|
1935
|
+
//#region src/nodes/output.d.ts
|
|
1929
1936
|
/**
|
|
1930
|
-
*
|
|
1937
|
+
* Output AST node that groups all generated file output for one API document.
|
|
1931
1938
|
*
|
|
1932
|
-
*
|
|
1933
|
-
* loop creates a fresh parse pass from the cached in-memory document, so multiple
|
|
1934
|
-
* consumers (plugins) can iterate independently without keeping all nodes in memory.
|
|
1939
|
+
* Produced by generators and consumed by the build pipeline to write files.
|
|
1935
1940
|
*
|
|
1936
1941
|
* @example
|
|
1937
1942
|
* ```ts
|
|
1938
|
-
*
|
|
1939
|
-
*
|
|
1943
|
+
* const output: OutputNode = {
|
|
1944
|
+
* kind: 'Output',
|
|
1945
|
+
* files: [],
|
|
1940
1946
|
* }
|
|
1941
1947
|
* ```
|
|
1942
1948
|
*/
|
|
1943
|
-
type
|
|
1944
|
-
kind: 'Input';
|
|
1945
|
-
/**
|
|
1946
|
-
* Lazily parsed schema nodes. Each `for await` creates a fresh parse pass, so
|
|
1947
|
-
* multiple plugins can iterate independently without sharing state.
|
|
1948
|
-
*/
|
|
1949
|
-
schemas: AsyncIterable<SchemaNode>;
|
|
1949
|
+
type OutputNode = BaseNode & {
|
|
1950
1950
|
/**
|
|
1951
|
-
*
|
|
1952
|
-
* multiple plugins can iterate independently without sharing state.
|
|
1951
|
+
* Node kind.
|
|
1953
1952
|
*/
|
|
1954
|
-
|
|
1953
|
+
kind: 'Output';
|
|
1955
1954
|
/**
|
|
1956
|
-
*
|
|
1955
|
+
* Generated file nodes.
|
|
1957
1956
|
*/
|
|
1958
|
-
|
|
1957
|
+
files: Array<FileNode>;
|
|
1959
1958
|
};
|
|
1960
1959
|
//#endregion
|
|
1961
1960
|
//#region src/nodes/index.d.ts
|
|
@@ -2005,12 +2004,21 @@ type DedupePlan = {
|
|
|
2005
2004
|
* Maps a structural signature to the canonical schema that represents it.
|
|
2006
2005
|
*/
|
|
2007
2006
|
canonicalBySignature: Map<string, DedupeCanonical>;
|
|
2007
|
+
/**
|
|
2008
|
+
* Maps the name of a top-level schema that duplicates a canonical one to that canonical, so
|
|
2009
|
+
* references to the duplicate can be repointed at the first schema with the same content.
|
|
2010
|
+
*/
|
|
2011
|
+
aliasNames: Map<string, DedupeCanonical>;
|
|
2008
2012
|
/**
|
|
2009
2013
|
* New top-level schema definitions created for inline shapes that had no existing
|
|
2010
2014
|
* named component. Nested duplicates inside each definition are already collapsed.
|
|
2011
2015
|
*/
|
|
2012
2016
|
hoisted: Array<SchemaNode>;
|
|
2013
2017
|
};
|
|
2018
|
+
/**
|
|
2019
|
+
* The lookups {@link applyDedupe} needs from a {@link DedupePlan}.
|
|
2020
|
+
*/
|
|
2021
|
+
type DedupeLookups = Pick<DedupePlan, 'canonicalBySignature' | 'aliasNames'>;
|
|
2014
2022
|
/**
|
|
2015
2023
|
* Options that inject the naming and candidate policy into {@link buildDedupePlan}.
|
|
2016
2024
|
* The mechanics (grouping, counting, rewriting) live here. The policy lives in the caller.
|
|
@@ -2041,25 +2049,29 @@ type BuildDedupePlanOptions = {
|
|
|
2041
2049
|
/**
|
|
2042
2050
|
* Rewrites a node, replacing every candidate sub-schema whose signature has a canonical
|
|
2043
2051
|
* target with a `ref` to that target. Replacing a node with a `ref` prunes its subtree,
|
|
2044
|
-
* so nested duplicates inside a replaced shape are not visited again.
|
|
2052
|
+
* so nested duplicates inside a replaced shape are not visited again. A `ref` that points
|
|
2053
|
+
* at a duplicate top-level schema (see `aliasNames`) is repointed at the first schema with
|
|
2054
|
+
* the same content.
|
|
2045
2055
|
*
|
|
2046
2056
|
* Pass `skipRootMatch` when rewriting a canonical definition so its own root is not
|
|
2047
2057
|
* turned into a reference to itself. Nested duplicates are still collapsed.
|
|
2048
2058
|
*
|
|
2049
2059
|
* @example
|
|
2050
2060
|
* ```ts
|
|
2051
|
-
* const next = applyDedupe(operationNode, plan
|
|
2061
|
+
* const next = applyDedupe(operationNode, plan)
|
|
2052
2062
|
* ```
|
|
2053
2063
|
*/
|
|
2054
|
-
declare function applyDedupe(node: SchemaNode,
|
|
2055
|
-
declare function applyDedupe(node: OperationNode,
|
|
2064
|
+
declare function applyDedupe(node: SchemaNode, plan: DedupeLookups, skipRootMatch?: boolean): SchemaNode;
|
|
2065
|
+
declare function applyDedupe(node: OperationNode, plan: DedupeLookups, skipRootMatch?: boolean): OperationNode;
|
|
2056
2066
|
/**
|
|
2057
2067
|
* Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
|
|
2058
2068
|
*
|
|
2059
2069
|
* A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
|
|
2060
|
-
* is a named top-level schema,
|
|
2061
|
-
* and inline copies turn into references to it).
|
|
2062
|
-
*
|
|
2070
|
+
* is a named top-level schema, the first one becomes the canonical (so other top-level
|
|
2071
|
+
* duplicates and inline copies turn into references to it). Every other top-level name with
|
|
2072
|
+
* the same content is recorded in `aliasNames`, so refs to it can be repointed at the
|
|
2073
|
+
* canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
|
|
2074
|
+
* per node with {@link applyDedupe}.
|
|
2063
2075
|
*
|
|
2064
2076
|
* @example
|
|
2065
2077
|
* ```ts
|
|
@@ -2074,38 +2086,39 @@ declare function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedup
|
|
|
2074
2086
|
//#endregion
|
|
2075
2087
|
//#region src/dialect.d.ts
|
|
2076
2088
|
/**
|
|
2077
|
-
* The spec-specific
|
|
2078
|
-
*
|
|
2079
|
-
*
|
|
2080
|
-
* targeting Postgres vs MySQL. Pair it with {@link dispatch}: the rule table picks which converter
|
|
2081
|
-
* runs, the dialect answers the spec-specific questions inside it.
|
|
2082
|
-
*
|
|
2083
|
-
* The guards (`isReference`, `isDiscriminator`) are type predicates, so converters narrow the
|
|
2084
|
-
* schema after a check and the type parameters carry the narrowed types through.
|
|
2085
|
-
*
|
|
2086
|
-
* This is the seam for the JSON Schema family: OpenAPI, AsyncAPI, and plain JSON Schema share
|
|
2087
|
-
* `$ref`, `allOf`/`oneOf`, `enum`, and `format` and differ only in these few decisions. A spec on
|
|
2088
|
-
* a different type system (GraphQL, with non-null wrappers and named-type references instead of
|
|
2089
|
-
* `$ref`) skips `SchemaDialect` and reuses the universal layer directly: the `Adapter` port, the
|
|
2090
|
-
* AST factories, and {@link dispatch} with its own rule table.
|
|
2091
|
-
*
|
|
2092
|
-
* @typeParam TSchema - The adapter's schema object type (e.g. an OpenAPI `SchemaObject`).
|
|
2093
|
-
* @typeParam TRef - The narrowed `$ref` pointer type `isReference` proves.
|
|
2094
|
-
* @typeParam TDiscriminated - The narrowed discriminated-schema type `isDiscriminator` proves.
|
|
2095
|
-
* @typeParam TDocument - The source document `resolveRef` resolves against.
|
|
2089
|
+
* The spec-specific questions a schema parser answers while turning a source document into Kubb
|
|
2090
|
+
* AST nodes. The rest of the pipeline is generic JSON Schema, so this is the one seam where
|
|
2091
|
+
* OpenAPI, AsyncAPI, and plain JSON Schema differ.
|
|
2096
2092
|
*/
|
|
2097
2093
|
type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {
|
|
2098
|
-
/**
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2094
|
+
/**
|
|
2095
|
+
* Identifies the dialect in logs and diagnostics.
|
|
2096
|
+
*/
|
|
2097
|
+
name: string;
|
|
2098
|
+
/**
|
|
2099
|
+
* Whether the schema is nullable.
|
|
2100
|
+
*/
|
|
2101
|
+
isNullable: (schema?: TSchema) => boolean;
|
|
2102
|
+
/**
|
|
2103
|
+
* Whether the value is a `$ref` pointer.
|
|
2104
|
+
*/
|
|
2105
|
+
isReference: (value?: unknown) => value is TRef;
|
|
2106
|
+
/**
|
|
2107
|
+
* Whether the schema carries a discriminator for polymorphism.
|
|
2108
|
+
*/
|
|
2109
|
+
isDiscriminator: (value?: unknown) => value is TDiscriminated;
|
|
2110
|
+
/**
|
|
2111
|
+
* Whether the schema is binary data, converted to a `blob` node.
|
|
2112
|
+
*/
|
|
2113
|
+
isBinary: (schema: TSchema) => boolean;
|
|
2114
|
+
/**
|
|
2115
|
+
* Resolves a local `$ref` against the document, or nullish when it cannot.
|
|
2116
|
+
*/
|
|
2103
2117
|
resolveRef: <TResolved>(document: TDocument, ref: string) => TResolved | null | undefined;
|
|
2104
2118
|
};
|
|
2105
2119
|
/**
|
|
2106
|
-
*
|
|
2107
|
-
*
|
|
2108
|
-
* inference and gives adapter authors a discoverable anchor.
|
|
2120
|
+
* Types a {@link SchemaDialect} for an adapter. Adds no runtime behavior and only pins the
|
|
2121
|
+
* dialect's type for inference.
|
|
2109
2122
|
*
|
|
2110
2123
|
* @example
|
|
2111
2124
|
* ```ts
|
|
@@ -2121,50 +2134,6 @@ type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema,
|
|
|
2121
2134
|
*/
|
|
2122
2135
|
declare function defineSchemaDialect<TSchema, TRef, TDiscriminated, TDocument>(dialect: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>): SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>;
|
|
2123
2136
|
//#endregion
|
|
2124
|
-
//#region src/dispatch.d.ts
|
|
2125
|
-
/**
|
|
2126
|
-
* One entry in an ordered dispatch table: a predicate paired with a converter.
|
|
2127
|
-
*
|
|
2128
|
-
* @typeParam TContext - Per-input context handed to every rule. A spec adapter typically
|
|
2129
|
-
* pre-computes this once per node (the source spec node plus derived fields like a
|
|
2130
|
-
* normalized type or resolved options) so individual rules stay cheap predicates.
|
|
2131
|
-
* @typeParam TNode - The node a rule produces, e.g. a Kubb AST `SchemaNode`.
|
|
2132
|
-
*/
|
|
2133
|
-
type DispatchRule<TContext, TNode> = {
|
|
2134
|
-
/** Identifies the rule when reading the table or debugging which branch ran. */name: string; /** Returns `true` when this rule is responsible for the given context. */
|
|
2135
|
-
match: (context: TContext) => boolean;
|
|
2136
|
-
/**
|
|
2137
|
-
* Produces a node for the context, or `null` to fall through to the next rule.
|
|
2138
|
-
*
|
|
2139
|
-
* Returning `null` lets a broad `match` defer: e.g. "has a `format`" matches many schemas,
|
|
2140
|
-
* but only some formats are convertible, the rest fall through to plain `type` handling.
|
|
2141
|
-
*/
|
|
2142
|
-
convert: (context: TContext) => TNode | null;
|
|
2143
|
-
};
|
|
2144
|
-
/**
|
|
2145
|
-
* Walks an ordered list of {@link DispatchRule}s and returns the first node produced.
|
|
2146
|
-
*
|
|
2147
|
-
* This is the shared backbone for spec adapters (OpenAPI today, AsyncAPI and others later).
|
|
2148
|
-
* The contract an adapter follows is intentionally minimal:
|
|
2149
|
-
*
|
|
2150
|
-
* context → [rule.match → rule.convert] → node
|
|
2151
|
-
*
|
|
2152
|
-
* An adapter derives a context from a source spec node, then declares an ordered table of
|
|
2153
|
-
* rules mapping spec shapes onto Kubb AST nodes. To add support for a new spec, write a new
|
|
2154
|
-
* context type and a new rules table, the traversal here is reused unchanged.
|
|
2155
|
-
*
|
|
2156
|
-
* Order is significant: earlier rules win, so list higher-precedence or more specific shapes
|
|
2157
|
-
* first (e.g. composition keywords before plain `type`). A rule whose `match` returns `true`
|
|
2158
|
-
* may still `convert` to `null` to defer to later rules. When no rule produces a node this
|
|
2159
|
-
* returns `null`, leaving the caller to apply its own fallback.
|
|
2160
|
-
*
|
|
2161
|
-
* @example
|
|
2162
|
-
* ```ts
|
|
2163
|
-
* const node = dispatch(schemaRules, schemaContext) ?? createSchema({ type: fallbackType })
|
|
2164
|
-
* ```
|
|
2165
|
-
*/
|
|
2166
|
-
declare function dispatch<TContext, TNode>(rules: ReadonlyArray<DispatchRule<TContext, TNode>>, context: TContext): TNode | null;
|
|
2167
|
-
//#endregion
|
|
2168
2137
|
//#region src/infer.d.ts
|
|
2169
2138
|
/**
|
|
2170
2139
|
* Shared parser options used by OAS-to-AST inference and parser flows.
|
|
@@ -2378,14 +2347,14 @@ type CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & {
|
|
|
2378
2347
|
*/
|
|
2379
2348
|
declare function createInput(overrides?: Partial<Omit<InputNode, 'kind'>>): InputNode;
|
|
2380
2349
|
/**
|
|
2381
|
-
* Creates
|
|
2350
|
+
* Creates a streaming `InputNode<true>` from pre-built `AsyncIterable` sources.
|
|
2382
2351
|
*
|
|
2383
2352
|
* @example
|
|
2384
2353
|
* ```ts
|
|
2385
2354
|
* const node = createStreamInput(schemasIterable, operationsIterable, { title: 'My API' })
|
|
2386
2355
|
* ```
|
|
2387
2356
|
*/
|
|
2388
|
-
declare function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta):
|
|
2357
|
+
declare function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta): InputNode<true>;
|
|
2389
2358
|
/**
|
|
2390
2359
|
* Creates an `OutputNode` with a stable default for `files`.
|
|
2391
2360
|
*
|
|
@@ -3571,5 +3540,5 @@ declare function containsCircularRef(node: SchemaNode | undefined, {
|
|
|
3571
3540
|
excludeName?: string;
|
|
3572
3541
|
}): boolean;
|
|
3573
3542
|
//#endregion
|
|
3574
|
-
export {
|
|
3575
|
-
//# sourceMappingURL=types-
|
|
3543
|
+
export { DedupeCanonical as $, schemaTypes as $t, createFunctionParameter as A, NumberSchemaNode as At, createProperty as B, UnionSchemaNode as Bt, UserFileNode as C, ImportNode as Ct, createExport as D, DatetimeSchemaNode as Dt, createConst as E, DateSchemaNode as Et, createOperation as F, SchemaNode as Ft, createText as G, ConstNode as Gt, createSchema as H, PropertyNode as Ht, createOutput as I, SchemaNodeByType as It, update as J, JsxNode as Jt, createType as K, FunctionNode as Kt, createParameter as L, SchemaType as Lt, createImport as M, PrimitiveSchemaType as Mt, createInput as N, RefSchemaNode as Nt, createFile as O, EnumSchemaNode as Ot, createJsx as P, ScalarSchemaType as Pt, defineSchemaDialect as Q, httpMethods as Qt, createParameterGroup as R, StringSchemaNode as Rt, DistributiveOmit as S, FileNode as St, createBreak as T, ArraySchemaNode as Tt, createSource as U, ArrowFunctionNode as Ut, createResponse as V, UrlSchemaNode as Vt, createStreamInput as W, CodeNode as Wt, ParserOptions as X, TypeNode as Xt, InferSchemaNode as Y, TextNode as Yt, SchemaDialect as Z, NodeKind as Zt, Printer as _, FunctionParameterNode as _t, createDiscriminantNode as a, OutputNode as at, createPrinterFactory as b, ParamsTypeNode as bt, findCircularSchemas as c, HttpMethod as ct, ParentOf as d, ResponseNode as dt, DedupeLookups as et, Visitor as f, StatusCode as ft, walk as g, FunctionParamNode as gt, transform as h, FunctionNodeType as ht, containsCircularRef as i, Node as it, createFunctionParameters as j, ObjectSchemaNode as jt, createFunction as k, IntersectionSchemaNode as kt, isStringType as l, HttpOperationNode as lt, collect as m, ParameterNode as mt, caseParams as n, applyDedupe as nt, createOperationParams as o, InputMeta as ot, VisitorContext as p, ParameterLocation as pt, syncOptionality as q, JSDocNode as qt, collectUsedSchemaNames as r, buildDedupePlan as rt, extractStringsFromNodes as s, InputNode as st, OperationParamsResolver as t, DedupePlan as tt, syncSchemaRef as u, OperationNode as ut, PrinterFactoryOptions as v, FunctionParametersNode as vt, createArrowFunction as w, SourceNode as wt, definePrinter as x, ExportNode as xt, PrinterPartial as y, ParameterGroupNode as yt, createParamsType as z, TimeSchemaNode as zt };
|
|
3544
|
+
//# sourceMappingURL=types-BL7RpQAE.d.ts.map
|
package/dist/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode,
|
|
1
|
+
import { $ as DedupeCanonical, At as NumberSchemaNode, Bt as UnionSchemaNode, C as UserFileNode, Ct as ImportNode, Dt as DatetimeSchemaNode, Et as DateSchemaNode, Ft as SchemaNode, Gt as ConstNode, Ht as PropertyNode, It as SchemaNodeByType, Jt as JsxNode, Kt as FunctionNode, Lt as SchemaType, Mt as PrimitiveSchemaType, Nt as RefSchemaNode, Ot as EnumSchemaNode, Pt as ScalarSchemaType, Rt as StringSchemaNode, S as DistributiveOmit, St as FileNode, Tt as ArraySchemaNode, Ut as ArrowFunctionNode, Vt as UrlSchemaNode, Wt as CodeNode, X as ParserOptions, Xt as TypeNode, Y as InferSchemaNode, Yt as TextNode, Z as SchemaDialect, Zt as NodeKind, _ as Printer, _t as FunctionParameterNode, at as OutputNode, bt as ParamsTypeNode, ct as HttpMethod, d as ParentOf, dt as ResponseNode, et as DedupeLookups, f as Visitor, ft as StatusCode, gt as FunctionParamNode, ht as FunctionNodeType, it as Node, jt as ObjectSchemaNode, kt as IntersectionSchemaNode, lt as HttpOperationNode, mt as ParameterNode, ot as InputMeta, p as VisitorContext, pt as ParameterLocation, qt as JSDocNode, st as InputNode, t as OperationParamsResolver, tt as DedupePlan, ut as OperationNode, v as PrinterFactoryOptions, vt as FunctionParametersNode, wt as SourceNode, xt as ExportNode, y as PrinterPartial, yt as ParameterGroupNode, zt as TimeSchemaNode } from "./types-BL7RpQAE.js";
|
|
2
|
+
export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode, DedupeCanonical, DedupeLookups, DedupePlan, DistributiveOmit, EnumSchemaNode, ExportNode, FileNode, FunctionNode, FunctionNodeType, FunctionParamNode, FunctionParameterNode, FunctionParametersNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, IntersectionSchemaNode, JSDocNode, JsxNode, Node, NodeKind, NumberSchemaNode, ObjectSchemaNode, OperationNode, OperationParamsResolver, OutputNode, ParameterGroupNode, ParameterLocation, ParameterNode, ParamsTypeNode, ParentOf, ParserOptions, PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, PropertyNode, RefSchemaNode, ResponseNode, ScalarSchemaType, SchemaDialect, SchemaNode, SchemaNodeByType, SchemaType, SourceNode, StatusCode, StringSchemaNode, TextNode, TimeSchemaNode, TypeNode, UnionSchemaNode, UrlSchemaNode, UserFileNode, Visitor, VisitorContext };
|
|
@@ -168,56 +168,31 @@ const INDENT = Array.from({ length: 2 }, () => " ").join("");
|
|
|
168
168
|
function toCamelOrPascal(text, pascal) {
|
|
169
169
|
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) => {
|
|
170
170
|
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
171
|
-
|
|
172
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
171
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
173
172
|
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
174
173
|
}
|
|
175
174
|
/**
|
|
176
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
177
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
178
|
-
* Segments are joined with `/` to form a file path.
|
|
179
|
-
*
|
|
180
|
-
* Only splits on dots followed by a letter so that version numbers
|
|
181
|
-
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
182
|
-
*
|
|
183
|
-
* Empty segments are filtered before joining. They arise when the text starts with
|
|
184
|
-
* a dot followed immediately by a letter (e.g. `..Schema` splits into `['..', 'Schema']`
|
|
185
|
-
* and `'..'` transforms to an empty string). Without this filter the join would produce
|
|
186
|
-
* a leading `/`, which `path.resolve` would interpret as an absolute path, allowing
|
|
187
|
-
* generated files to escape the configured output directory.
|
|
188
|
-
*/
|
|
189
|
-
function applyToFileParts(text, transformPart) {
|
|
190
|
-
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
191
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).filter(Boolean).join("/");
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
175
|
* Converts `text` to camelCase.
|
|
195
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
196
176
|
*
|
|
197
|
-
* @example
|
|
198
|
-
* camelCase('hello-world')
|
|
199
|
-
*
|
|
177
|
+
* @example Word boundaries
|
|
178
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
179
|
+
*
|
|
180
|
+
* @example With a prefix
|
|
181
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
200
182
|
*/
|
|
201
|
-
function camelCase(text, {
|
|
202
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
203
|
-
prefix,
|
|
204
|
-
suffix
|
|
205
|
-
} : {}));
|
|
183
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
206
184
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
207
185
|
}
|
|
208
186
|
/**
|
|
209
187
|
* Converts `text` to PascalCase.
|
|
210
|
-
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
211
188
|
*
|
|
212
|
-
* @example
|
|
213
|
-
* pascalCase('hello-world')
|
|
214
|
-
*
|
|
189
|
+
* @example Word boundaries
|
|
190
|
+
* `pascalCase('hello-world') // 'HelloWorld'`
|
|
191
|
+
*
|
|
192
|
+
* @example With a suffix
|
|
193
|
+
* `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
|
|
215
194
|
*/
|
|
216
|
-
function pascalCase(text, {
|
|
217
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
218
|
-
prefix,
|
|
219
|
-
suffix
|
|
220
|
-
}) : camelCase(part));
|
|
195
|
+
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
221
196
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
222
197
|
}
|
|
223
198
|
//#endregion
|
|
@@ -324,22 +299,6 @@ function isValidVarName(name) {
|
|
|
324
299
|
return isIdentifier(name);
|
|
325
300
|
}
|
|
326
301
|
/**
|
|
327
|
-
* Returns `name` when it is already a valid JavaScript variable name, otherwise prefixes it with `_`
|
|
328
|
-
* so the result can be used as an identifier. Useful for sanitizing schema names or operation IDs
|
|
329
|
-
* that start with a digit (`409`, `504AccountCancel`) or collide with a reserved word.
|
|
330
|
-
*
|
|
331
|
-
* @example
|
|
332
|
-
* ```ts
|
|
333
|
-
* ensureValidVarName('409') // '_409'
|
|
334
|
-
* ensureValidVarName('Pet') // 'Pet'
|
|
335
|
-
* ensureValidVarName('class') // '_class'
|
|
336
|
-
* ```
|
|
337
|
-
*/
|
|
338
|
-
function ensureValidVarName(name) {
|
|
339
|
-
if (!name || isValidVarName(name)) return name;
|
|
340
|
-
return `_${name}`;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
302
|
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
344
303
|
*
|
|
345
304
|
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
@@ -371,21 +330,6 @@ function singleQuote(value) {
|
|
|
371
330
|
if (value === void 0 || value === null) return "''";
|
|
372
331
|
return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
373
332
|
}
|
|
374
|
-
/**
|
|
375
|
-
* Strips the file extension from a path or file name.
|
|
376
|
-
* Only removes the last `.ext` segment when the dot is not part of a directory name.
|
|
377
|
-
*
|
|
378
|
-
* @example
|
|
379
|
-
* trimExtName('petStore.ts') // 'petStore'
|
|
380
|
-
* trimExtName('/src/models/pet.ts') // '/src/models/pet'
|
|
381
|
-
* trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
|
|
382
|
-
* trimExtName('noExtension') // 'noExtension'
|
|
383
|
-
*/
|
|
384
|
-
function trimExtName(text) {
|
|
385
|
-
const dotIndex = text.lastIndexOf(".");
|
|
386
|
-
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
387
|
-
return text;
|
|
388
|
-
}
|
|
389
333
|
//#endregion
|
|
390
334
|
//#region src/utils/index.ts
|
|
391
335
|
/**
|
|
@@ -621,6 +565,6 @@ function findDiscriminator(mapping, ref) {
|
|
|
621
565
|
return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
|
|
622
566
|
}
|
|
623
567
|
//#endregion
|
|
624
|
-
export {
|
|
568
|
+
export { httpMethods as _, enumPropName as a, visitorDepths as b, getNestedAccessor as c, stringify as d, stringifyObject as f, camelCase as g, isValidVarName as h, childName as i, jsStringEscape as l, trimQuotes as m, buildList as n, extractRefName as o, toRegExpString as p, buildObject as r, findDiscriminator as s, buildJSDoc as t, objectKey as u, isScalarPrimitive as v, schemaTypes as y };
|
|
625
569
|
|
|
626
|
-
//# sourceMappingURL=utils-
|
|
570
|
+
//# sourceMappingURL=utils-0p8ZO287.js.map
|