@kubb/ast 0.0.0-canary-20260313170904

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/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2026 Stijn Van Hulle
2
+
3
+ This repository contains software under two licenses:
4
+
5
+ 1. Most of the code in this repository is licensed under the
6
+ MIT License — see licenses/LICENSE-MIT for the full license text.
7
+
8
+ 2. The following components are licensed under the
9
+ GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)
10
+ — see licenses/LICENSE-AGPL-3.0 for the full license text:
11
+
12
+ - packages/agent (published as @kubb/agent)
13
+
14
+ Each package's own LICENSE file or package.json specifies its applicable license.
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ <div align="center">
2
+ <h1>@kubb/ast</h1>
3
+ <a href="https://kubb.dev" target="_blank" rel="noopener noreferrer">
4
+ <img width="180" src="https://raw.githubusercontent.com/kubb-labs/kubb/main/assets/logo.png" alt="Kubb logo">
5
+ </a>
6
+
7
+ [![npm version][npm-version-src]][npm-version-href]
8
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
9
+ [![Coverage][coverage-src]][coverage-href]
10
+ [![License][license-src]][license-href]
11
+ [![Sponsors][sponsors-src]][sponsors-href]
12
+
13
+ <h4>
14
+ <a href="https://kubb.dev/" target="_blank">Documentation</a>
15
+ <span> · </span>
16
+ <a href="https://github.com/kubb-labs/kubb/issues/" target="_blank">Report Bug</a>
17
+ <span> · </span>
18
+ <a href="https://github.com/kubb-labs/kubb/issues/" target="_blank">Request Feature</a>
19
+ </h4>
20
+ </div>
21
+
22
+ Spec-agnostic AST layer for Kubb. Defines nodes, visitor pattern, factory functions, and type guards used across codegen plugins.
23
+
24
+ ## Imports
25
+
26
+ | Path | Contents |
27
+ |---|---|
28
+ | `@kubb/ast` | Runtime: factory functions, guards, visitor, ref helpers, constants |
29
+ | `@kubb/ast/types` | Types only: all node interfaces, type aliases, visitor types |
30
+
31
+ ## Node tree
32
+
33
+ ```
34
+ RootNode
35
+ ├── schemas: SchemaNode[]
36
+ └── operations: OperationNode[]
37
+ ├── parameters: ParameterNode[] → SchemaNode
38
+ ├── requestBody?: SchemaNode
39
+ └── responses: ResponseNode[] → SchemaNode?
40
+
41
+ SchemaNode (discriminated union)
42
+ object → properties: PropertyNode[] → SchemaNode
43
+ array | tuple → items: SchemaNode[]
44
+ union | intersection → members: SchemaNode[]
45
+ enum | ref | string | number | integer | bigint
46
+ boolean | null | any | unknown | void
47
+ date | datetime | time | uuid | email | url | blob
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ### Factory
53
+
54
+ ```ts
55
+ import { createRoot, createOperation, createSchema, createProperty } from '@kubb/ast'
56
+
57
+ const root = createRoot({
58
+ schemas: [
59
+ createSchema({
60
+ name: 'Pet',
61
+ type: 'object',
62
+ properties: [
63
+ createProperty({ name: 'id', schema: createSchema({ type: 'integer' }), required: true }),
64
+ createProperty({ name: 'name', schema: createSchema({ type: 'string' }), required: true }),
65
+ ],
66
+ }),
67
+ ],
68
+ })
69
+ ```
70
+
71
+ ### Visitor
72
+
73
+ ```ts
74
+ import { walk, transform, collect } from '@kubb/ast'
75
+
76
+ // Side effects
77
+ await walk(root, {
78
+ schema(node) { console.log(node.type) },
79
+ })
80
+
81
+ // Immutable transformation
82
+ const updated = transform(root, {
83
+ schema(node) { return { ...node, description: 'generated' } },
84
+ })
85
+
86
+ // Extraction
87
+ const types = collect<string>(root, {
88
+ schema(node) { return node.type },
89
+ })
90
+ ```
91
+
92
+ ### Guards
93
+
94
+ ```ts
95
+ import { isSchemaNode, narrowSchema } from '@kubb/ast'
96
+ import type { Node } from '@kubb/ast/types'
97
+
98
+ function process(node: Node) {
99
+ if (isSchemaNode(node)) {
100
+ const obj = narrowSchema(node, 'object')
101
+ obj?.properties?.forEach(p => console.log(p.name))
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### Refs
107
+
108
+ ```ts
109
+ import { buildRefMap, resolveRef } from '@kubb/ast'
110
+
111
+ const refMap = buildRefMap(root)
112
+ const pet = resolveRef(refMap, 'Pet')
113
+ ```
114
+
115
+ ## Supporting Kubb
116
+
117
+ Kubb uses an MIT-licensed open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:
118
+
119
+ - [Become a Sponsor on GitHub](https://github.com/sponsors/stijnvanhulle)
120
+
121
+ <p align="center">
122
+ <a href="https://github.com/sponsors/stijnvanhulle">
123
+ <img src="https://raw.githubusercontent.com/stijnvanhulle/sponsors/main/sponsors.svg" alt="My sponsors" />
124
+ </a>
125
+ </p>
126
+
127
+ <!-- Badges -->
128
+
129
+ [npm-version-src]: https://img.shields.io/npm/v/@kubb/ast?flat&colorA=18181B&colorB=f58517
130
+ [npm-version-href]: https://npmjs.com/package/@kubb/ast
131
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@kubb/ast?flat&colorA=18181B&colorB=f58517
132
+ [npm-downloads-href]: https://npmjs.com/package/@kubb/ast
133
+ [license-src]: https://img.shields.io/github/license/kubb-labs/kubb.svg?flat&colorA=18181B&colorB=f58517
134
+ [license-href]: https://github.com/kubb-labs/kubb/blob/main/LICENSE
135
+ [coverage-src]: https://img.shields.io/codecov/c/github/kubb-labs/kubb?style=flat&colorA=18181B&colorB=f58517
136
+ [coverage-href]: https://www.npmjs.com/package/@kubb/ast
137
+ [sponsors-src]: https://img.shields.io/github/sponsors/stijnvanhulle?style=flat&colorA=18181B&colorB=f58517
138
+ [sponsors-href]: https://github.com/sponsors/stijnvanhulle/
@@ -0,0 +1,8 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", {
4
+ value,
5
+ configurable: true
6
+ });
7
+ //#endregion
8
+ export { __name as t };
package/dist/index.cjs ADDED
@@ -0,0 +1,366 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ Object.defineProperty;
3
+ //#endregion
4
+ //#region src/constants.ts
5
+ const visitorDepths = {
6
+ shallow: "shallow",
7
+ deep: "deep"
8
+ };
9
+ const nodeKinds = {
10
+ root: "Root",
11
+ operation: "Operation",
12
+ schema: "Schema",
13
+ property: "Property",
14
+ parameter: "Parameter",
15
+ response: "Response"
16
+ };
17
+ const schemaTypes = {
18
+ string: "string",
19
+ number: "number",
20
+ integer: "integer",
21
+ bigint: "bigint",
22
+ boolean: "boolean",
23
+ null: "null",
24
+ any: "any",
25
+ unknown: "unknown",
26
+ void: "void",
27
+ object: "object",
28
+ array: "array",
29
+ tuple: "tuple",
30
+ union: "union",
31
+ intersection: "intersection",
32
+ enum: "enum",
33
+ ref: "ref",
34
+ date: "date",
35
+ datetime: "datetime",
36
+ time: "time",
37
+ uuid: "uuid",
38
+ email: "email",
39
+ url: "url",
40
+ blob: "blob"
41
+ };
42
+ const httpMethods = {
43
+ get: "GET",
44
+ post: "POST",
45
+ put: "PUT",
46
+ patch: "PATCH",
47
+ delete: "DELETE",
48
+ head: "HEAD",
49
+ options: "OPTIONS",
50
+ trace: "TRACE"
51
+ };
52
+ const mediaTypes = {
53
+ applicationJson: "application/json",
54
+ applicationXml: "application/xml",
55
+ applicationFormUrlEncoded: "application/x-www-form-urlencoded",
56
+ applicationOctetStream: "application/octet-stream",
57
+ applicationPdf: "application/pdf",
58
+ applicationZip: "application/zip",
59
+ applicationGraphql: "application/graphql",
60
+ multipartFormData: "multipart/form-data",
61
+ textPlain: "text/plain",
62
+ textHtml: "text/html",
63
+ textCsv: "text/csv",
64
+ textXml: "text/xml",
65
+ imagePng: "image/png",
66
+ imageJpeg: "image/jpeg",
67
+ imageGif: "image/gif",
68
+ imageWebp: "image/webp",
69
+ imageSvgXml: "image/svg+xml",
70
+ audioMpeg: "audio/mpeg",
71
+ videoMp4: "video/mp4"
72
+ };
73
+ //#endregion
74
+ //#region src/factory.ts
75
+ /**
76
+ * Creates a `RootNode`.
77
+ */
78
+ function createRoot(overrides = {}) {
79
+ return {
80
+ schemas: [],
81
+ operations: [],
82
+ ...overrides,
83
+ kind: "Root"
84
+ };
85
+ }
86
+ /**
87
+ * Creates an `OperationNode`.
88
+ */
89
+ function createOperation(props) {
90
+ return {
91
+ tags: [],
92
+ parameters: [],
93
+ responses: [],
94
+ ...props,
95
+ kind: "Operation"
96
+ };
97
+ }
98
+ /**
99
+ * Creates a `SchemaNode`, narrowed to the variant of `props.type`.
100
+ */
101
+ function createSchema(props) {
102
+ return {
103
+ ...props,
104
+ kind: "Schema"
105
+ };
106
+ }
107
+ /**
108
+ * Creates a `PropertyNode`. `required` defaults to `false`.
109
+ */
110
+ function createProperty(props) {
111
+ return {
112
+ required: false,
113
+ ...props,
114
+ kind: "Property"
115
+ };
116
+ }
117
+ /**
118
+ * Creates a `ParameterNode`. `required` defaults to `false`.
119
+ */
120
+ function createParameter(props) {
121
+ return {
122
+ required: false,
123
+ ...props,
124
+ kind: "Parameter"
125
+ };
126
+ }
127
+ /**
128
+ * Creates a `ResponseNode`.
129
+ */
130
+ function createResponse(props) {
131
+ return {
132
+ ...props,
133
+ kind: "Response"
134
+ };
135
+ }
136
+ //#endregion
137
+ //#region src/guards.ts
138
+ /**
139
+ * Narrows a `SchemaNode` to the specific variant matching `type`.
140
+ */
141
+ function narrowSchema(node, type) {
142
+ return node?.type === type ? node : void 0;
143
+ }
144
+ function isKind(kind) {
145
+ return (node) => node.kind === kind;
146
+ }
147
+ /**
148
+ * Type guard for `RootNode`.
149
+ */
150
+ const isRootNode = isKind("Root");
151
+ /**
152
+ * Type guard for `OperationNode`.
153
+ */
154
+ const isOperationNode = isKind("Operation");
155
+ /**
156
+ * Type guard for `SchemaNode`.
157
+ */
158
+ const isSchemaNode = isKind("Schema");
159
+ /**
160
+ * Type guard for `PropertyNode`.
161
+ */
162
+ const isPropertyNode = isKind("Property");
163
+ /**
164
+ * Type guard for `ParameterNode`.
165
+ */
166
+ const isParameterNode = isKind("Parameter");
167
+ /**
168
+ * Type guard for `ResponseNode`.
169
+ */
170
+ const isResponseNode = isKind("Response");
171
+ //#endregion
172
+ //#region src/refs.ts
173
+ /**
174
+ * Indexes named schemas from `root.schemas` by name. Unnamed schemas are skipped.
175
+ */
176
+ function buildRefMap(root) {
177
+ const map = /* @__PURE__ */ new Map();
178
+ for (const schema of root.schemas) if (schema.name) map.set(schema.name, schema);
179
+ return map;
180
+ }
181
+ /**
182
+ * Looks up a schema by name. Prefer over `RefMap.get()` to keep the resolution strategy swappable.
183
+ */
184
+ function resolveRef(refMap, ref) {
185
+ return refMap.get(ref);
186
+ }
187
+ /**
188
+ * Converts a `RefMap` to a plain object.
189
+ */
190
+ function refMapToObject(refMap) {
191
+ return Object.fromEntries(refMap);
192
+ }
193
+ //#endregion
194
+ //#region src/visitor.ts
195
+ /**
196
+ * Traversable children of `node`, respecting `recurse` for schema nodes.
197
+ */
198
+ function getChildren(node, recurse) {
199
+ switch (node.kind) {
200
+ case "Root": return [...node.schemas, ...node.operations];
201
+ case "Operation": return [
202
+ ...node.parameters,
203
+ ...node.requestBody ? [node.requestBody] : [],
204
+ ...node.responses
205
+ ];
206
+ case "Schema": {
207
+ const children = [];
208
+ if (!recurse) return [];
209
+ if ("properties" in node && node.properties) children.push(...node.properties);
210
+ if ("items" in node && node.items) children.push(...node.items);
211
+ if ("members" in node && node.members) children.push(...node.members);
212
+ return children;
213
+ }
214
+ case "Property": return [node.schema];
215
+ case "Parameter": return [node.schema];
216
+ case "Response": return node.schema ? [node.schema] : [];
217
+ }
218
+ }
219
+ /**
220
+ * Depth-first traversal for side effects. Visitor return values are ignored.
221
+ */
222
+ async function walk(node, visitor, options = {}) {
223
+ const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep;
224
+ switch (node.kind) {
225
+ case "Root":
226
+ await visitor.root?.(node);
227
+ break;
228
+ case "Operation":
229
+ await visitor.operation?.(node);
230
+ break;
231
+ case "Schema":
232
+ await visitor.schema?.(node);
233
+ break;
234
+ case "Property":
235
+ await visitor.property?.(node);
236
+ break;
237
+ case "Parameter":
238
+ await visitor.parameter?.(node);
239
+ break;
240
+ case "Response":
241
+ await visitor.response?.(node);
242
+ break;
243
+ }
244
+ for (const child of getChildren(node, recurse)) await walk(child, visitor, options);
245
+ }
246
+ function transform(node, visitor, options = {}) {
247
+ const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep;
248
+ switch (node.kind) {
249
+ case "Root": {
250
+ let root = node;
251
+ const replaced = visitor.root?.(root);
252
+ if (replaced) root = replaced;
253
+ return {
254
+ ...root,
255
+ schemas: root.schemas.map((s) => transform(s, visitor, options)),
256
+ operations: root.operations.map((op) => transform(op, visitor, options))
257
+ };
258
+ }
259
+ case "Operation": {
260
+ let op = node;
261
+ const replaced = visitor.operation?.(op);
262
+ if (replaced) op = replaced;
263
+ return {
264
+ ...op,
265
+ parameters: op.parameters.map((p) => transform(p, visitor, options)),
266
+ requestBody: op.requestBody ? transform(op.requestBody, visitor, options) : void 0,
267
+ responses: op.responses.map((r) => transform(r, visitor, options))
268
+ };
269
+ }
270
+ case "Schema": {
271
+ let schema = node;
272
+ const replaced = visitor.schema?.(schema);
273
+ if (replaced) schema = replaced;
274
+ return {
275
+ ...schema,
276
+ ..."properties" in schema && recurse ? { properties: schema.properties?.map((p) => transform(p, visitor, options)) } : {},
277
+ ..."items" in schema && recurse ? { items: schema.items?.map((i) => transform(i, visitor, options)) } : {},
278
+ ..."members" in schema && recurse ? { members: schema.members?.map((m) => transform(m, visitor, options)) } : {}
279
+ };
280
+ }
281
+ case "Property": {
282
+ let prop = node;
283
+ const replaced = visitor.property?.(prop);
284
+ if (replaced) prop = replaced;
285
+ return {
286
+ ...prop,
287
+ schema: transform(prop.schema, visitor, options)
288
+ };
289
+ }
290
+ case "Parameter": {
291
+ let param = node;
292
+ const replaced = visitor.parameter?.(param);
293
+ if (replaced) param = replaced;
294
+ return {
295
+ ...param,
296
+ schema: transform(param.schema, visitor, options)
297
+ };
298
+ }
299
+ case "Response": {
300
+ let response = node;
301
+ const replaced = visitor.response?.(response);
302
+ if (replaced) response = replaced;
303
+ return {
304
+ ...response,
305
+ schema: response.schema ? transform(response.schema, visitor, options) : void 0
306
+ };
307
+ }
308
+ }
309
+ }
310
+ /**
311
+ * Depth-first synchronous reduction. Collects non-`undefined` visitor return values into an array.
312
+ */
313
+ function collect(node, visitor, options = {}) {
314
+ const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep;
315
+ const results = [];
316
+ let v;
317
+ switch (node.kind) {
318
+ case "Root":
319
+ v = visitor.root?.(node);
320
+ break;
321
+ case "Operation":
322
+ v = visitor.operation?.(node);
323
+ break;
324
+ case "Schema":
325
+ v = visitor.schema?.(node);
326
+ break;
327
+ case "Property":
328
+ v = visitor.property?.(node);
329
+ break;
330
+ case "Parameter":
331
+ v = visitor.parameter?.(node);
332
+ break;
333
+ case "Response":
334
+ v = visitor.response?.(node);
335
+ break;
336
+ }
337
+ if (v !== void 0) results.push(v);
338
+ for (const child of getChildren(node, recurse)) for (const item of collect(child, visitor, options)) results.push(item);
339
+ return results;
340
+ }
341
+ //#endregion
342
+ exports.buildRefMap = buildRefMap;
343
+ exports.collect = collect;
344
+ exports.createOperation = createOperation;
345
+ exports.createParameter = createParameter;
346
+ exports.createProperty = createProperty;
347
+ exports.createResponse = createResponse;
348
+ exports.createRoot = createRoot;
349
+ exports.createSchema = createSchema;
350
+ exports.httpMethods = httpMethods;
351
+ exports.isOperationNode = isOperationNode;
352
+ exports.isParameterNode = isParameterNode;
353
+ exports.isPropertyNode = isPropertyNode;
354
+ exports.isResponseNode = isResponseNode;
355
+ exports.isRootNode = isRootNode;
356
+ exports.isSchemaNode = isSchemaNode;
357
+ exports.mediaTypes = mediaTypes;
358
+ exports.narrowSchema = narrowSchema;
359
+ exports.nodeKinds = nodeKinds;
360
+ exports.refMapToObject = refMapToObject;
361
+ exports.resolveRef = resolveRef;
362
+ exports.schemaTypes = schemaTypes;
363
+ exports.transform = transform;
364
+ exports.walk = walk;
365
+
366
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/constants.ts","../src/factory.ts","../src/guards.ts","../src/refs.ts","../src/visitor.ts"],"sourcesContent":["import type { NodeKind } from './nodes/base.ts'\nimport type { MediaType } from './nodes/http.ts'\nimport type { HttpMethod } from './nodes/operation.ts'\nimport type { ParameterLocation } from './nodes/parameter.ts'\nimport type { SchemaType } from './nodes/schema.ts'\n\n/**\n * Depth for schema traversal in visitor functions.\n */\nexport type VisitorDepth = 'shallow' | 'deep'\n\nexport const visitorDepths = {\n shallow: 'shallow',\n deep: 'deep',\n} as const satisfies Record<VisitorDepth, VisitorDepth>\n\nexport const nodeKinds = {\n root: 'Root',\n operation: 'Operation',\n schema: 'Schema',\n property: 'Property',\n parameter: 'Parameter',\n response: 'Response',\n} as const satisfies Record<Lowercase<NodeKind>, NodeKind>\n\nexport const schemaTypes = {\n string: 'string',\n /**\n * Floating-point number (`float`, `double`).\n */\n number: 'number',\n /**\n * Whole number (`int32`). Use `bigint` for `int64`.\n */\n integer: 'integer',\n /**\n * 64-bit integer (`int64`). Only used when `integerType` is set to `'bigint'`.\n */\n bigint: 'bigint',\n boolean: 'boolean',\n null: 'null',\n any: 'any',\n unknown: 'unknown',\n void: 'void',\n object: 'object',\n array: 'array',\n tuple: 'tuple',\n union: 'union',\n intersection: 'intersection',\n enum: 'enum',\n ref: 'ref',\n date: 'date',\n datetime: 'datetime',\n time: 'time',\n uuid: 'uuid',\n email: 'email',\n url: 'url',\n blob: 'blob',\n} as const satisfies Record<SchemaType, SchemaType>\n\nexport const httpMethods = {\n get: 'GET',\n post: 'POST',\n put: 'PUT',\n patch: 'PATCH',\n delete: 'DELETE',\n head: 'HEAD',\n options: 'OPTIONS',\n trace: 'TRACE',\n} as const satisfies Record<Lowercase<HttpMethod>, HttpMethod>\n\nexport const parameterLocations = {\n path: 'path',\n query: 'query',\n header: 'header',\n cookie: 'cookie',\n} as const satisfies Record<ParameterLocation, ParameterLocation>\n\n/**\n * Fallback status code string for API spec responses.\n */\nexport const DEFAULT_STATUS_CODE = 'default' as const\n\nexport const mediaTypes = {\n applicationJson: 'application/json',\n applicationXml: 'application/xml',\n applicationFormUrlEncoded: 'application/x-www-form-urlencoded',\n applicationOctetStream: 'application/octet-stream',\n applicationPdf: 'application/pdf',\n applicationZip: 'application/zip',\n applicationGraphql: 'application/graphql',\n multipartFormData: 'multipart/form-data',\n textPlain: 'text/plain',\n textHtml: 'text/html',\n textCsv: 'text/csv',\n textXml: 'text/xml',\n imagePng: 'image/png',\n imageJpeg: 'image/jpeg',\n imageGif: 'image/gif',\n imageWebp: 'image/webp',\n imageSvgXml: 'image/svg+xml',\n audioMpeg: 'audio/mpeg',\n videoMp4: 'video/mp4',\n} as const satisfies Record<string, MediaType>\n","import type { OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'\n\n/**\n * Distributive variant of `Omit` that preserves union members.\n */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/**\n * Creates a `RootNode`.\n */\nexport function createRoot(overrides: Partial<Omit<RootNode, 'kind'>> = {}): RootNode {\n return {\n schemas: [],\n operations: [],\n ...overrides,\n kind: 'Root',\n }\n}\n\n/**\n * Creates an `OperationNode`.\n */\nexport function createOperation(\n props: Pick<OperationNode, 'operationId' | 'method' | 'path'> & Partial<Omit<OperationNode, 'kind' | 'operationId' | 'method' | 'path'>>,\n): OperationNode {\n return {\n tags: [],\n parameters: [],\n responses: [],\n ...props,\n kind: 'Operation',\n }\n}\n\n/**\n * Creates a `SchemaNode`, narrowed to the variant of `props.type`.\n */\nexport function createSchema<T extends DistributiveOmit<SchemaNode, 'kind'>>(props: T): T & { kind: 'Schema' } {\n return { ...props, kind: 'Schema' } as T & { kind: 'Schema' }\n}\n\n/**\n * Creates a `PropertyNode`. `required` defaults to `false`.\n */\nexport function createProperty(props: Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>): PropertyNode {\n return {\n required: false,\n ...props,\n kind: 'Property',\n }\n}\n\n/**\n * Creates a `ParameterNode`. `required` defaults to `false`.\n */\nexport function createParameter(\n props: Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>,\n): ParameterNode {\n return {\n required: false,\n ...props,\n kind: 'Parameter',\n }\n}\n\n/**\n * Creates a `ResponseNode`.\n */\nexport function createResponse(props: Pick<ResponseNode, 'statusCode'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode'>>): ResponseNode {\n return {\n ...props,\n kind: 'Response',\n }\n}\n","import type { Node, NodeKind, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode, SchemaNodeByType } from './nodes/index.ts'\n\n/**\n * Narrows a `SchemaNode` to the specific variant matching `type`.\n */\nexport function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | undefined {\n return node?.type === type ? (node as SchemaNodeByType[T]) : undefined\n}\n\nfunction isKind<T extends Node>(kind: NodeKind) {\n return (node: Node): node is T => node.kind === kind\n}\n\n/**\n * Type guard for `RootNode`.\n */\nexport const isRootNode = isKind<RootNode>('Root')\n\n/**\n * Type guard for `OperationNode`.\n */\nexport const isOperationNode = isKind<OperationNode>('Operation')\n\n/**\n * Type guard for `SchemaNode`.\n */\nexport const isSchemaNode = isKind<SchemaNode>('Schema')\n\n/**\n * Type guard for `PropertyNode`.\n */\nexport const isPropertyNode = isKind<PropertyNode>('Property')\n\n/**\n * Type guard for `ParameterNode`.\n */\nexport const isParameterNode = isKind<ParameterNode>('Parameter')\n\n/**\n * Type guard for `ResponseNode`.\n */\nexport const isResponseNode = isKind<ResponseNode>('Response')\n","import type { RootNode } from './nodes/root.ts'\nimport type { SchemaNode } from './nodes/schema.ts'\n\n/**\n * Schema name to `SchemaNode` mapping.\n */\nexport type RefMap = Map<string, SchemaNode>\n\n/**\n * Indexes named schemas from `root.schemas` by name. Unnamed schemas are skipped.\n */\nexport function buildRefMap(root: RootNode): RefMap {\n const map: RefMap = new Map()\n\n for (const schema of root.schemas) {\n if (schema.name) {\n map.set(schema.name, schema)\n }\n }\n return map\n}\n\n/**\n * Looks up a schema by name. Prefer over `RefMap.get()` to keep the resolution strategy swappable.\n */\nexport function resolveRef(refMap: RefMap, ref: string): SchemaNode | undefined {\n return refMap.get(ref)\n}\n\n/**\n * Converts a `RefMap` to a plain object.\n */\nexport function refMapToObject(refMap: RefMap): Record<string, SchemaNode> {\n return Object.fromEntries(refMap)\n}\n","import type { VisitorDepth } from './constants.ts'\nimport { visitorDepths } from './constants.ts'\nimport type { Node, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'\n\n/**\n * Shared options for `walk`, `transform`, and `collect`.\n */\nexport type VisitorOptions = {\n depth?: VisitorDepth\n}\n\n/**\n * Synchronous visitor for `transform` and `walk`.\n */\nexport interface Visitor {\n root?(node: RootNode): void | RootNode\n operation?(node: OperationNode): void | OperationNode\n schema?(node: SchemaNode): void | SchemaNode\n property?(node: PropertyNode): void | PropertyNode\n parameter?(node: ParameterNode): void | ParameterNode\n response?(node: ResponseNode): void | ResponseNode\n}\n\ntype MaybePromise<T> = T | Promise<T>\n\n/**\n * Async visitor for `walk`. Synchronous `Visitor` objects are compatible.\n */\nexport interface AsyncVisitor {\n root?(node: RootNode): MaybePromise<void | RootNode>\n operation?(node: OperationNode): MaybePromise<void | OperationNode>\n schema?(node: SchemaNode): MaybePromise<void | SchemaNode>\n property?(node: PropertyNode): MaybePromise<void | PropertyNode>\n parameter?(node: ParameterNode): MaybePromise<void | ParameterNode>\n response?(node: ResponseNode): MaybePromise<void | ResponseNode>\n}\n\n/**\n * Visitor for `collect`.\n */\nexport interface CollectVisitor<T> {\n root?(node: RootNode): T | undefined\n operation?(node: OperationNode): T | undefined\n schema?(node: SchemaNode): T | undefined\n property?(node: PropertyNode): T | undefined\n parameter?(node: ParameterNode): T | undefined\n response?(node: ResponseNode): T | undefined\n}\n\n/**\n * Traversable children of `node`, respecting `recurse` for schema nodes.\n */\nfunction getChildren(node: Node, recurse: boolean): Array<Node> {\n switch (node.kind) {\n case 'Root':\n return [...node.schemas, ...node.operations]\n case 'Operation':\n return [...node.parameters, ...(node.requestBody ? [node.requestBody] : []), ...node.responses]\n case 'Schema': {\n const children: Array<Node> = []\n\n if (!recurse) return []\n\n if ('properties' in node && node.properties) children.push(...node.properties)\n if ('items' in node && node.items) children.push(...node.items)\n if ('members' in node && node.members) children.push(...node.members)\n\n return children\n }\n case 'Property':\n return [node.schema]\n case 'Parameter':\n return [node.schema]\n case 'Response':\n return node.schema ? [node.schema] : []\n }\n}\n\n/**\n * Depth-first traversal for side effects. Visitor return values are ignored.\n */\nexport async function walk(node: Node, visitor: AsyncVisitor, options: VisitorOptions = {}): Promise<void> {\n const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep\n\n switch (node.kind) {\n case 'Root':\n await visitor.root?.(node)\n break\n case 'Operation':\n await visitor.operation?.(node)\n break\n case 'Schema':\n await visitor.schema?.(node)\n break\n case 'Property':\n await visitor.property?.(node)\n break\n case 'Parameter':\n await visitor.parameter?.(node)\n break\n case 'Response':\n await visitor.response?.(node)\n break\n }\n\n for (const child of getChildren(node, recurse)) {\n await walk(child, visitor, options)\n }\n}\n\n/**\n * Depth-first immutable transformation. Visitor return values replace nodes; `undefined` keeps the original.\n */\nexport function transform(node: RootNode, visitor: Visitor, options?: VisitorOptions): RootNode\nexport function transform(node: OperationNode, visitor: Visitor, options?: VisitorOptions): OperationNode\nexport function transform(node: SchemaNode, visitor: Visitor, options?: VisitorOptions): SchemaNode\nexport function transform(node: PropertyNode, visitor: Visitor, options?: VisitorOptions): PropertyNode\nexport function transform(node: ParameterNode, visitor: Visitor, options?: VisitorOptions): ParameterNode\nexport function transform(node: ResponseNode, visitor: Visitor, options?: VisitorOptions): ResponseNode\nexport function transform(node: Node, visitor: Visitor, options?: VisitorOptions): Node\nexport function transform(node: Node, visitor: Visitor, options: VisitorOptions = {}): Node {\n const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep\n\n switch (node.kind) {\n case 'Root': {\n let root = node\n const replaced = visitor.root?.(root)\n if (replaced) root = replaced\n\n return {\n ...root,\n schemas: root.schemas.map((s) => transform(s, visitor, options)),\n operations: root.operations.map((op) => transform(op, visitor, options)),\n }\n }\n case 'Operation': {\n let op = node\n const replaced = visitor.operation?.(op)\n if (replaced) op = replaced\n\n return {\n ...op,\n parameters: op.parameters.map((p) => transform(p, visitor, options)),\n requestBody: op.requestBody ? transform(op.requestBody, visitor, options) : undefined,\n responses: op.responses.map((r) => transform(r, visitor, options)),\n }\n }\n case 'Schema': {\n let schema = node\n const replaced = visitor.schema?.(schema)\n if (replaced) schema = replaced\n\n return {\n ...schema,\n ...('properties' in schema && recurse ? { properties: schema.properties?.map((p) => transform(p, visitor, options)) } : {}),\n ...('items' in schema && recurse ? { items: schema.items?.map((i) => transform(i, visitor, options)) } : {}),\n ...('members' in schema && recurse ? { members: schema.members?.map((m) => transform(m, visitor, options)) } : {}),\n }\n }\n case 'Property': {\n let prop = node\n const replaced = visitor.property?.(prop)\n if (replaced) prop = replaced\n\n return {\n ...prop,\n schema: transform(prop.schema, visitor, options),\n }\n }\n case 'Parameter': {\n let param = node\n const replaced = visitor.parameter?.(param)\n if (replaced) param = replaced\n\n return {\n ...param,\n schema: transform(param.schema, visitor, options),\n }\n }\n case 'Response': {\n let response = node\n const replaced = visitor.response?.(response)\n if (replaced) response = replaced\n\n return {\n ...response,\n schema: response.schema ? transform(response.schema, visitor, options) : undefined,\n }\n }\n }\n}\n\n/**\n * Depth-first synchronous reduction. Collects non-`undefined` visitor return values into an array.\n */\nexport function collect<T>(node: Node, visitor: CollectVisitor<T>, options: VisitorOptions = {}): Array<T> {\n const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep\n const results: Array<T> = []\n\n let v: T | undefined\n switch (node.kind) {\n case 'Root':\n v = visitor.root?.(node)\n break\n case 'Operation':\n v = visitor.operation?.(node)\n break\n case 'Schema':\n v = visitor.schema?.(node)\n break\n case 'Property':\n v = visitor.property?.(node)\n break\n case 'Parameter':\n v = visitor.parameter?.(node)\n break\n case 'Response':\n v = visitor.response?.(node)\n break\n }\n if (v !== undefined) results.push(v)\n\n for (const child of getChildren(node, recurse)) {\n for (const item of collect(child, visitor, options)) {\n results.push(item)\n }\n }\n\n return results\n}\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { t as __name } from "./chunk--u3MIqq1.js";
2
+ import { $ as httpMethods, C as ResponseNode, H as SchemaNode, O as ParameterNode, S as OperationNode, U as SchemaNodeByType, Y as PropertyNode, _ as createRoot, a as collect, b as RootNode, d as resolveRef, et as mediaTypes, g as createResponse, h as createProperty, l as buildRefMap, m as createParameter, nt as schemaTypes, o as transform, p as createOperation, s as walk, tt as nodeKinds, u as refMapToObject, v as createSchema, y as Node } from "./visitor-D9_Eb8I1.js";
3
+
4
+ //#region src/guards.d.ts
5
+ /**
6
+ * Narrows a `SchemaNode` to the specific variant matching `type`.
7
+ */
8
+ declare function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | undefined;
9
+ /**
10
+ * Type guard for `RootNode`.
11
+ */
12
+ declare const isRootNode: (node: Node) => node is RootNode;
13
+ /**
14
+ * Type guard for `OperationNode`.
15
+ */
16
+ declare const isOperationNode: (node: Node) => node is OperationNode;
17
+ /**
18
+ * Type guard for `SchemaNode`.
19
+ */
20
+ declare const isSchemaNode: (node: Node) => node is SchemaNode;
21
+ /**
22
+ * Type guard for `PropertyNode`.
23
+ */
24
+ declare const isPropertyNode: (node: Node) => node is PropertyNode;
25
+ /**
26
+ * Type guard for `ParameterNode`.
27
+ */
28
+ declare const isParameterNode: (node: Node) => node is ParameterNode;
29
+ /**
30
+ * Type guard for `ResponseNode`.
31
+ */
32
+ declare const isResponseNode: (node: Node) => node is ResponseNode;
33
+ //#endregion
34
+ export { buildRefMap, collect, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, httpMethods, isOperationNode, isParameterNode, isPropertyNode, isResponseNode, isRootNode, isSchemaNode, mediaTypes, narrowSchema, nodeKinds, refMapToObject, resolveRef, schemaTypes, transform, walk };
35
+ //# sourceMappingURL=index.d.ts.map