@kubb/ast 5.0.0-beta.53 → 5.0.0-beta.54
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 +33 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +33 -13
- package/dist/index.js.map +1 -1
- package/dist/{types-IHUK_alM.d.ts → types-BYujEIxF.d.ts} +22 -9
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
- package/src/dedupe.ts +47 -16
- package/src/types.ts +1 -1
|
@@ -2005,12 +2005,21 @@ type DedupePlan = {
|
|
|
2005
2005
|
* Maps a structural signature to the canonical schema that represents it.
|
|
2006
2006
|
*/
|
|
2007
2007
|
canonicalBySignature: Map<string, DedupeCanonical>;
|
|
2008
|
+
/**
|
|
2009
|
+
* Maps the name of a top-level schema that duplicates a canonical one to that canonical, so
|
|
2010
|
+
* references to the duplicate can be repointed at the first schema with the same content.
|
|
2011
|
+
*/
|
|
2012
|
+
aliasNames: Map<string, DedupeCanonical>;
|
|
2008
2013
|
/**
|
|
2009
2014
|
* New top-level schema definitions created for inline shapes that had no existing
|
|
2010
2015
|
* named component. Nested duplicates inside each definition are already collapsed.
|
|
2011
2016
|
*/
|
|
2012
2017
|
hoisted: Array<SchemaNode>;
|
|
2013
2018
|
};
|
|
2019
|
+
/**
|
|
2020
|
+
* The lookups {@link applyDedupe} needs from a {@link DedupePlan}.
|
|
2021
|
+
*/
|
|
2022
|
+
type DedupeLookups = Pick<DedupePlan, 'canonicalBySignature' | 'aliasNames'>;
|
|
2014
2023
|
/**
|
|
2015
2024
|
* Options that inject the naming and candidate policy into {@link buildDedupePlan}.
|
|
2016
2025
|
* The mechanics (grouping, counting, rewriting) live here. The policy lives in the caller.
|
|
@@ -2041,25 +2050,29 @@ type BuildDedupePlanOptions = {
|
|
|
2041
2050
|
/**
|
|
2042
2051
|
* Rewrites a node, replacing every candidate sub-schema whose signature has a canonical
|
|
2043
2052
|
* 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.
|
|
2053
|
+
* so nested duplicates inside a replaced shape are not visited again. A `ref` that points
|
|
2054
|
+
* at a duplicate top-level schema (see `aliasNames`) is repointed at the first schema with
|
|
2055
|
+
* the same content.
|
|
2045
2056
|
*
|
|
2046
2057
|
* Pass `skipRootMatch` when rewriting a canonical definition so its own root is not
|
|
2047
2058
|
* turned into a reference to itself. Nested duplicates are still collapsed.
|
|
2048
2059
|
*
|
|
2049
2060
|
* @example
|
|
2050
2061
|
* ```ts
|
|
2051
|
-
* const next = applyDedupe(operationNode, plan
|
|
2062
|
+
* const next = applyDedupe(operationNode, plan)
|
|
2052
2063
|
* ```
|
|
2053
2064
|
*/
|
|
2054
|
-
declare function applyDedupe(node: SchemaNode,
|
|
2055
|
-
declare function applyDedupe(node: OperationNode,
|
|
2065
|
+
declare function applyDedupe(node: SchemaNode, plan: DedupeLookups, skipRootMatch?: boolean): SchemaNode;
|
|
2066
|
+
declare function applyDedupe(node: OperationNode, plan: DedupeLookups, skipRootMatch?: boolean): OperationNode;
|
|
2056
2067
|
/**
|
|
2057
2068
|
* Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
|
|
2058
2069
|
*
|
|
2059
2070
|
* 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
|
-
*
|
|
2071
|
+
* is a named top-level schema, the first one becomes the canonical (so other top-level
|
|
2072
|
+
* duplicates and inline copies turn into references to it). Every other top-level name with
|
|
2073
|
+
* the same content is recorded in `aliasNames`, so refs to it can be repointed at the
|
|
2074
|
+
* canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
|
|
2075
|
+
* per node with {@link applyDedupe}.
|
|
2063
2076
|
*
|
|
2064
2077
|
* @example
|
|
2065
2078
|
* ```ts
|
|
@@ -3571,5 +3584,5 @@ declare function containsCircularRef(node: SchemaNode | undefined, {
|
|
|
3571
3584
|
excludeName?: string;
|
|
3572
3585
|
}): boolean;
|
|
3573
3586
|
//#endregion
|
|
3574
|
-
export { SchemaDialect as $,
|
|
3575
|
-
//# sourceMappingURL=types-
|
|
3587
|
+
export { SchemaDialect as $, TypeNode as $t, createFunctionParameter as A, DatetimeSchemaNode as At, createProperty as B, SchemaType as Bt, UserFileNode as C, ParamsTypeNode as Ct, createExport as D, SourceNode as Dt, createConst as E, ImportNode as Et, createOperation as F, PrimitiveSchemaType as Ft, createText as G, PropertyNode as Gt, createSchema as H, TimeSchemaNode as Ht, createOutput as I, RefSchemaNode as It, update as J, ConstNode as Jt, createType as K, ArrowFunctionNode as Kt, createParameter as L, ScalarSchemaType as Lt, createImport as M, IntersectionSchemaNode as Mt, createInput as N, NumberSchemaNode as Nt, createFile as O, ArraySchemaNode as Ot, createJsx as P, ObjectSchemaNode as Pt, dispatch as Q, TextNode as Qt, createParameterGroup as R, SchemaNode as Rt, DistributiveOmit as S, ParameterGroupNode as St, createBreak as T, FileNode as Tt, createSource as U, UnionSchemaNode as Ut, createResponse as V, StringSchemaNode as Vt, createStreamInput as W, UrlSchemaNode as Wt, ParserOptions as X, JSDocNode as Xt, InferSchemaNode as Y, FunctionNode as Yt, DispatchRule as Z, JsxNode as Zt, Printer as _, ParameterNode as _t, createDiscriminantNode as a, buildDedupePlan as at, createPrinterFactory as b, FunctionParameterNode as bt, findCircularSchemas as c, InputNode as ct, ParentOf as d, HttpMethod as dt, NodeKind as en, defineSchemaDialect as et, Visitor as f, HttpOperationNode as ft, walk as g, ParameterLocation as gt, transform as h, StatusCode as ht, containsCircularRef as i, applyDedupe as it, createFunctionParameters as j, EnumSchemaNode as jt, createFunction as k, DateSchemaNode as kt, isStringType as l, InputStreamNode as lt, collect as m, ResponseNode as mt, caseParams as n, schemaTypes as nn, DedupeLookups as nt, createOperationParams as o, Node as ot, VisitorContext as p, OperationNode as pt, syncOptionality as q, CodeNode as qt, collectUsedSchemaNames as r, DedupePlan as rt, extractStringsFromNodes as s, InputMeta as st, OperationParamsResolver as t, httpMethods as tn, DedupeCanonical as tt, syncSchemaRef as u, OutputNode as ut, PrinterFactoryOptions as v, FunctionNodeType as vt, createArrowFunction as w, ExportNode as wt, definePrinter as x, FunctionParametersNode as xt, PrinterPartial as y, FunctionParamNode as yt, createParamsType as z, SchemaNodeByType as zt };
|
|
3588
|
+
//# sourceMappingURL=types-BYujEIxF.d.ts.map
|
package/dist/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as SchemaDialect, At as
|
|
2
|
-
export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode, DedupePlan, DispatchRule, DistributiveOmit, EnumSchemaNode, ExportNode, FileNode, FunctionNode, FunctionNodeType, FunctionParamNode, FunctionParameterNode, FunctionParametersNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, InputStreamNode, 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 };
|
|
1
|
+
import { $ as SchemaDialect, $t as TypeNode, At as DatetimeSchemaNode, Bt as SchemaType, C as UserFileNode, Ct as ParamsTypeNode, Dt as SourceNode, Et as ImportNode, Ft as PrimitiveSchemaType, Gt as PropertyNode, Ht as TimeSchemaNode, It as RefSchemaNode, Jt as ConstNode, Kt as ArrowFunctionNode, Lt as ScalarSchemaType, Mt as IntersectionSchemaNode, Nt as NumberSchemaNode, Ot as ArraySchemaNode, Pt as ObjectSchemaNode, Qt as TextNode, Rt as SchemaNode, S as DistributiveOmit, St as ParameterGroupNode, Tt as FileNode, Ut as UnionSchemaNode, Vt as StringSchemaNode, Wt as UrlSchemaNode, X as ParserOptions, Xt as JSDocNode, Y as InferSchemaNode, Yt as FunctionNode, Z as DispatchRule, Zt as JsxNode, _ as Printer, _t as ParameterNode, bt as FunctionParameterNode, ct as InputNode, d as ParentOf, dt as HttpMethod, en as NodeKind, f as Visitor, ft as HttpOperationNode, gt as ParameterLocation, ht as StatusCode, jt as EnumSchemaNode, kt as DateSchemaNode, lt as InputStreamNode, mt as ResponseNode, nt as DedupeLookups, ot as Node, p as VisitorContext, pt as OperationNode, qt as CodeNode, rt as DedupePlan, st as InputMeta, t as OperationParamsResolver, tt as DedupeCanonical, ut as OutputNode, v as PrinterFactoryOptions, vt as FunctionNodeType, wt as ExportNode, xt as FunctionParametersNode, y as PrinterPartial, yt as FunctionParamNode, zt as SchemaNodeByType } from "./types-BYujEIxF.js";
|
|
2
|
+
export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode, DedupeCanonical, DedupeLookups, DedupePlan, DispatchRule, DistributiveOmit, EnumSchemaNode, ExportNode, FileNode, FunctionNode, FunctionNodeType, FunctionParamNode, FunctionParameterNode, FunctionParametersNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, InputStreamNode, 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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/ast",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.54",
|
|
4
4
|
"description": "Spec-agnostic AST layer for Kubb. Defines the node tree, visitor pattern, factory functions, and type guards used across all code generation plugins.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ast",
|
package/src/dedupe.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSchema } from './factory.ts'
|
|
2
2
|
import type { Node, OperationNode, SchemaNode } from './nodes/index.ts'
|
|
3
3
|
import { signatureOf } from './signature.ts'
|
|
4
|
+
import { extractRefName } from './utils/index.ts'
|
|
4
5
|
import { collectLazy, transform } from './visitor.ts'
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -28,6 +29,11 @@ export type DedupePlan = {
|
|
|
28
29
|
* Maps a structural signature to the canonical schema that represents it.
|
|
29
30
|
*/
|
|
30
31
|
canonicalBySignature: Map<string, DedupeCanonical>
|
|
32
|
+
/**
|
|
33
|
+
* Maps the name of a top-level schema that duplicates a canonical one to that canonical, so
|
|
34
|
+
* references to the duplicate can be repointed at the first schema with the same content.
|
|
35
|
+
*/
|
|
36
|
+
aliasNames: Map<string, DedupeCanonical>
|
|
31
37
|
/**
|
|
32
38
|
* New top-level schema definitions created for inline shapes that had no existing
|
|
33
39
|
* named component. Nested duplicates inside each definition are already collapsed.
|
|
@@ -35,6 +41,11 @@ export type DedupePlan = {
|
|
|
35
41
|
hoisted: Array<SchemaNode>
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The lookups {@link applyDedupe} needs from a {@link DedupePlan}.
|
|
46
|
+
*/
|
|
47
|
+
export type DedupeLookups = Pick<DedupePlan, 'canonicalBySignature' | 'aliasNames'>
|
|
48
|
+
|
|
38
49
|
/**
|
|
39
50
|
* Options that inject the naming and candidate policy into {@link buildDedupePlan}.
|
|
40
51
|
* The mechanics (grouping, counting, rewriting) live here. The policy lives in the caller.
|
|
@@ -86,25 +97,35 @@ function createRefNode(node: SchemaNode, canonical: DedupeCanonical): SchemaNode
|
|
|
86
97
|
/**
|
|
87
98
|
* Rewrites a node, replacing every candidate sub-schema whose signature has a canonical
|
|
88
99
|
* target with a `ref` to that target. Replacing a node with a `ref` prunes its subtree,
|
|
89
|
-
* so nested duplicates inside a replaced shape are not visited again.
|
|
100
|
+
* so nested duplicates inside a replaced shape are not visited again. A `ref` that points
|
|
101
|
+
* at a duplicate top-level schema (see `aliasNames`) is repointed at the first schema with
|
|
102
|
+
* the same content.
|
|
90
103
|
*
|
|
91
104
|
* Pass `skipRootMatch` when rewriting a canonical definition so its own root is not
|
|
92
105
|
* turned into a reference to itself. Nested duplicates are still collapsed.
|
|
93
106
|
*
|
|
94
107
|
* @example
|
|
95
108
|
* ```ts
|
|
96
|
-
* const next = applyDedupe(operationNode, plan
|
|
109
|
+
* const next = applyDedupe(operationNode, plan)
|
|
97
110
|
* ```
|
|
98
111
|
*/
|
|
99
|
-
export function applyDedupe(node: SchemaNode,
|
|
100
|
-
export function applyDedupe(node: OperationNode,
|
|
101
|
-
export function applyDedupe(node: Node,
|
|
102
|
-
|
|
112
|
+
export function applyDedupe(node: SchemaNode, plan: DedupeLookups, skipRootMatch?: boolean): SchemaNode
|
|
113
|
+
export function applyDedupe(node: OperationNode, plan: DedupeLookups, skipRootMatch?: boolean): OperationNode
|
|
114
|
+
export function applyDedupe(node: Node, plan: DedupeLookups, skipRootMatch = false): Node {
|
|
115
|
+
const { canonicalBySignature, aliasNames } = plan
|
|
116
|
+
if (canonicalBySignature.size === 0 && aliasNames.size === 0) return node
|
|
103
117
|
|
|
104
118
|
const root = node
|
|
105
119
|
|
|
106
120
|
return transform(node, {
|
|
107
121
|
schema(schemaNode) {
|
|
122
|
+
if (schemaNode.type === 'ref') {
|
|
123
|
+
const target = schemaNode.ref ? extractRefName(schemaNode.ref) : schemaNode.name
|
|
124
|
+
const canonical = target ? aliasNames.get(target) : undefined
|
|
125
|
+
|
|
126
|
+
return canonical ? { ...schemaNode, name: canonical.name, ref: canonical.ref } : undefined
|
|
127
|
+
}
|
|
128
|
+
|
|
108
129
|
const signature = signatureOf(schemaNode)
|
|
109
130
|
if (skipRootMatch && schemaNode === root) return undefined
|
|
110
131
|
|
|
@@ -128,9 +149,11 @@ function cleanDefinition(node: SchemaNode, name: string): SchemaNode {
|
|
|
128
149
|
* Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
|
|
129
150
|
*
|
|
130
151
|
* A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
|
|
131
|
-
* is a named top-level schema,
|
|
132
|
-
* and inline copies turn into references to it).
|
|
133
|
-
*
|
|
152
|
+
* is a named top-level schema, the first one becomes the canonical (so other top-level
|
|
153
|
+
* duplicates and inline copies turn into references to it). Every other top-level name with
|
|
154
|
+
* the same content is recorded in `aliasNames`, so refs to it can be repointed at the
|
|
155
|
+
* canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
|
|
156
|
+
* per node with {@link applyDedupe}.
|
|
134
157
|
*
|
|
135
158
|
* @example
|
|
136
159
|
* ```ts
|
|
@@ -149,7 +172,7 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
149
172
|
type Group = {
|
|
150
173
|
count: number
|
|
151
174
|
representative: SchemaNode
|
|
152
|
-
|
|
175
|
+
topLevelNames: Array<string>
|
|
153
176
|
}
|
|
154
177
|
const groups = new Map<string, Group>()
|
|
155
178
|
|
|
@@ -161,9 +184,9 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
161
184
|
const group = groups.get(signature)
|
|
162
185
|
if (group) {
|
|
163
186
|
group.count++
|
|
164
|
-
if (isTopLevel
|
|
187
|
+
if (isTopLevel) group.topLevelNames.push(schemaNode.name!)
|
|
165
188
|
} else {
|
|
166
|
-
groups.set(signature, { count: 1, representative: schemaNode,
|
|
189
|
+
groups.set(signature, { count: 1, representative: schemaNode, topLevelNames: isTopLevel ? [schemaNode.name!] : [] })
|
|
167
190
|
}
|
|
168
191
|
}
|
|
169
192
|
|
|
@@ -175,13 +198,19 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
175
198
|
}
|
|
176
199
|
|
|
177
200
|
const canonicalBySignature = new Map<string, DedupeCanonical>()
|
|
201
|
+
const aliasNames = new Map<string, DedupeCanonical>()
|
|
178
202
|
const pendingHoists: Array<{ name: string; representative: SchemaNode }> = []
|
|
179
203
|
|
|
180
204
|
for (const [signature, group] of groups) {
|
|
181
205
|
if (group.count < minOccurrences) continue
|
|
182
206
|
|
|
183
|
-
|
|
184
|
-
|
|
207
|
+
const [firstName, ...duplicateNames] = group.topLevelNames
|
|
208
|
+
if (firstName) {
|
|
209
|
+
const canonical: DedupeCanonical = { name: firstName, ref: refFor(firstName) }
|
|
210
|
+
canonicalBySignature.set(signature, canonical)
|
|
211
|
+
for (const duplicate of duplicateNames) {
|
|
212
|
+
aliasNames.set(duplicate, canonical)
|
|
213
|
+
}
|
|
185
214
|
continue
|
|
186
215
|
}
|
|
187
216
|
|
|
@@ -194,7 +223,9 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
194
223
|
|
|
195
224
|
// Build hoisted definitions only after every canonical name is known, so nested
|
|
196
225
|
// duplicates inside a definition also resolve to refs.
|
|
197
|
-
const hoisted = pendingHoists.map(({ name, representative }) =>
|
|
226
|
+
const hoisted = pendingHoists.map(({ name, representative }) =>
|
|
227
|
+
cleanDefinition(applyDedupe(representative, { canonicalBySignature, aliasNames }, true), name),
|
|
228
|
+
)
|
|
198
229
|
|
|
199
|
-
return { canonicalBySignature, hoisted }
|
|
230
|
+
return { canonicalBySignature, aliasNames, hoisted }
|
|
200
231
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { DedupePlan } from './dedupe.ts'
|
|
1
|
+
export type { DedupeCanonical, DedupeLookups, DedupePlan } from './dedupe.ts'
|
|
2
2
|
export type { SchemaDialect } from './dialect.ts'
|
|
3
3
|
export type { DispatchRule } from './dispatch.ts'
|
|
4
4
|
export type { DistributiveOmit } from './factory.ts'
|