@kubb/ast
Advanced tools
| import { n as __name } from "./rolldown-runtime-CNktS9qV.js"; | ||
| import { et as SchemaNode, nt as SchemaType, tt as SchemaNodeByType } from "./index-Cu2zmNxv.js"; | ||
| //#region src/defineDialect.d.ts | ||
| /** | ||
| * The spec-specific questions a schema parser answers while turning a source document into Kubb | ||
| * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats | ||
| * differ. | ||
| */ | ||
| type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = { | ||
| /** | ||
| * Whether the schema is nullable. | ||
| */ | ||
| isNullable(schema?: TSchema): boolean; | ||
| /** | ||
| * Whether the value is a `$ref` pointer. | ||
| */ | ||
| isReference(value?: unknown): value is TRef; | ||
| /** | ||
| * Whether the schema carries a discriminator for polymorphism. | ||
| */ | ||
| isDiscriminator(value?: unknown): value is TDiscriminated; | ||
| /** | ||
| * Whether the schema is binary data, converted to a `blob` node. | ||
| */ | ||
| isBinary(schema: TSchema): boolean; | ||
| /** | ||
| * Resolves a local `$ref` against the document, or nullish when it cannot. | ||
| */ | ||
| resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined; | ||
| }; | ||
| /** | ||
| * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the | ||
| * spec-specific schema questions the parser answers. | ||
| */ | ||
| type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = { | ||
| /** | ||
| * Identifies the dialect in logs and diagnostics. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * The spec-specific schema behavior. See {@link SchemaDialect}. | ||
| */ | ||
| schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>; | ||
| }; | ||
| /** | ||
| * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the | ||
| * dialect's type for inference. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * export const oasDialect = defineDialect({ | ||
| * name: 'oas', | ||
| * schema: { | ||
| * isNullable, | ||
| * isReference, | ||
| * isDiscriminator, | ||
| * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream', | ||
| * resolveRef, | ||
| * }, | ||
| * }) | ||
| * ``` | ||
| */ | ||
| declare function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>): Dialect<TSchema, TRef, TDiscriminated, TDocument>; | ||
| //#endregion | ||
| //#region src/createPrinter.d.ts | ||
| /** | ||
| * Runtime context passed as `this` to printer handlers. | ||
| * | ||
| * `this.transform` dispatches to node-level handlers from `nodes`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const context: PrinterHandlerContext<string, {}> = { | ||
| * options: {}, | ||
| * transform: () => 'value', | ||
| * } | ||
| * ``` | ||
| */ | ||
| type PrinterHandlerContext<TOutput, TOptions extends object> = { | ||
| /** | ||
| * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers. | ||
| * Use `this.transform` inside `nodes` handlers and inside the `print` override. | ||
| */ | ||
| transform: (node: SchemaNode) => TOutput | null; | ||
| /** | ||
| * Run the printer's built-in handler for the node, ignoring any override for its type. | ||
| * Inside an override, `this.base(node)` returns what the printer would have emitted, | ||
| * so the override can wrap it instead of re-implementing the handler. Nested nodes | ||
| * still dispatch through the overrides. | ||
| */ | ||
| base: (node: SchemaNode) => TOutput | null; | ||
| /** | ||
| * Options for this printer instance. | ||
| */ | ||
| options: TOptions; | ||
| }; | ||
| /** | ||
| * Handler for one schema node type. | ||
| * | ||
| * Use a regular function (not an arrow function) if you need `this`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const handler: PrinterHandler<string, {}, 'string'> = function () { | ||
| * return 'string' | ||
| * } | ||
| * ``` | ||
| */ | ||
| type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (this: PrinterHandlerContext<TOutput, TOptions>, node: SchemaNodeByType[T]) => TOutput | null; | ||
| /** | ||
| * Partial map of per-node-type handler overrides for a printer. | ||
| * | ||
| * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`). | ||
| * Supply only the handlers you want to replace. The printer's built-in | ||
| * defaults fill in the rest. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * pluginZod({ | ||
| * printer: { | ||
| * nodes: { | ||
| * date(): string { | ||
| * return 'z.string().date()' | ||
| * }, | ||
| * } satisfies PrinterPartial<string, PrinterZodOptions>, | ||
| * }, | ||
| * }) | ||
| * ``` | ||
| */ | ||
| type PrinterPartial<TOutput, TOptions extends object> = Partial<{ [K in SchemaType]: PrinterHandler<TOutput, TOptions, K> }>; | ||
| /** | ||
| * Generic shape used by `definePrinter`. | ||
| * | ||
| * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`) | ||
| * - `TOptions` options passed to and stored on the printer instance | ||
| * - `TOutput` the type emitted by node handlers | ||
| * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string> | ||
| * ``` | ||
| */ | ||
| type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = { | ||
| name: TName; | ||
| options: TOptions; | ||
| output: TOutput; | ||
| printOutput: TPrintOutput; | ||
| }; | ||
| /** | ||
| * Printer instance returned by a printer factory. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({}) | ||
| * ``` | ||
| */ | ||
| type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = { | ||
| /** | ||
| * Unique identifier supplied at creation time. | ||
| */ | ||
| name: T['name']; | ||
| /** | ||
| * Options for this printer instance. | ||
| */ | ||
| options: T['options']; | ||
| /** | ||
| * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers. | ||
| * Always dispatches through the `nodes` map. Never calls the `print` override. | ||
| * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping. | ||
| */ | ||
| transform: (node: SchemaNode) => T['output'] | null; | ||
| /** | ||
| * Public printer. If the builder provides a root-level `print`, this calls that | ||
| * higher-level function (which may produce full declarations). | ||
| * Otherwise, falls back to the node-level dispatcher. | ||
| */ | ||
| print: (node: SchemaNode) => T['printOutput'] | null; | ||
| }; | ||
| /** | ||
| * Builder function passed to `definePrinter`. | ||
| * | ||
| * It receives resolved options and returns: | ||
| * - `name` | ||
| * - `options` | ||
| * - `nodes` handlers | ||
| * - optional top-level `print` override | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} }) | ||
| * ``` | ||
| */ | ||
| type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => { | ||
| name: T['name']; | ||
| /** | ||
| * Options to store on the printer. | ||
| */ | ||
| options: T['options']; | ||
| nodes: Partial<{ [K in SchemaType]: PrinterHandler<T['output'], T['options'], K> }>; | ||
| /** | ||
| * User-supplied handler overrides. An override wins over the matching `nodes` handler, | ||
| * and can call `this.base(node)` to reuse the handler it replaced. Pass overrides here | ||
| * instead of spreading them into `nodes`, otherwise `this.base` cannot find the original. | ||
| */ | ||
| overrides?: Partial<{ [K in SchemaType]: PrinterHandler<T['output'], T['options'], K> }>; | ||
| /** | ||
| * Optional root-level print override. When provided, becomes the public `printer.print`. | ||
| * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`), | ||
| * not the override itself, so recursion is safe. | ||
| */ | ||
| print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null; | ||
| }; | ||
| /** | ||
| * Creates a schema printer: a function that takes a `SchemaNode` and emits | ||
| * code in your target language. Each plugin that produces code from schemas | ||
| * (TypeScript types, Zod schemas, Faker factories) ships a printer built | ||
| * with this helper. | ||
| * | ||
| * The builder receives resolved options and returns: | ||
| * | ||
| * - `name` unique identifier for the printer. | ||
| * - `options` stored on the returned printer instance. | ||
| * - `nodes` map of `SchemaType` → handler. Handlers return the rendered | ||
| * output (a string, a TypeScript AST node, ...) for that schema type. | ||
| * - `overrides` (optional), user-supplied handlers that win over `nodes`. | ||
| * An override can call `this.base(node)` to reuse the handler it replaced. | ||
| * - `print` (optional), top-level override exposed as `printer.print`. | ||
| * Use `this.transform(node)` inside it to dispatch to `nodes` recursively. | ||
| * | ||
| * Without a `print` override, `printer.print` falls back to `printer.transform` | ||
| * (the node-level dispatcher). | ||
| * | ||
| * @example Tiny Zod printer | ||
| * ```ts | ||
| * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast' | ||
| * | ||
| * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string> | ||
| * | ||
| * export const zodPrinter = createPrinter<PrinterZod>((options) => ({ | ||
| * name: 'zod', | ||
| * options: { strict: options.strict ?? true }, | ||
| * nodes: { | ||
| * string: () => 'z.string()', | ||
| * object(node) { | ||
| * const props = node.properties | ||
| * .map((p) => `${p.name}: ${this.transform(p.schema)}`) | ||
| * .join(', ') | ||
| * return `z.object({ ${props} })` | ||
| * }, | ||
| * }, | ||
| * })) | ||
| * ``` | ||
| */ | ||
| declare function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T>; | ||
| //#endregion | ||
| export { Dialect as a, createPrinter as i, PrinterFactoryOptions as n, SchemaDialect as o, PrinterPartial as r, defineDialect as s, Printer as t }; | ||
| //# sourceMappingURL=types-CWF7DV0f.d.ts.map |
+12
-1
@@ -40,2 +40,4 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| * output (a string, a TypeScript AST node, ...) for that schema type. | ||
| * - `overrides` (optional), user-supplied handlers that win over `nodes`. | ||
| * An override can call `this.base(node)` to reuse the handler it replaced. | ||
| * - `print` (optional), top-level override exposed as `printer.print`. | ||
@@ -70,6 +72,15 @@ * Use `this.transform(node)` inside it to dispatch to `nodes` recursively. | ||
| return (options) => { | ||
| const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? {}); | ||
| const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build(options ?? {}); | ||
| const merged = overrides ? { | ||
| ...nodes, | ||
| ...overrides | ||
| } : nodes; | ||
| const context = { | ||
| options: resolvedOptions, | ||
| transform: (node) => { | ||
| const handler = merged[node.type]; | ||
| if (!handler) return null; | ||
| return handler.call(context, node); | ||
| }, | ||
| base: (node) => { | ||
| const handler = nodes[node.type]; | ||
@@ -76,0 +87,0 @@ if (!handler) return null; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.cjs","names":[],"sources":["../src/defineDialect.ts","../src/createPrinter.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["/**\n * The spec-specific questions a schema parser answers while turning a source document into Kubb\n * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats\n * differ.\n */\nexport type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Whether the schema is nullable.\n */\n isNullable(schema?: TSchema): boolean\n /**\n * Whether the value is a `$ref` pointer.\n */\n isReference(value?: unknown): value is TRef\n /**\n * Whether the schema carries a discriminator for polymorphism.\n */\n isDiscriminator(value?: unknown): value is TDiscriminated\n /**\n * Whether the schema is binary data, converted to a `blob` node.\n */\n isBinary(schema: TSchema): boolean\n /**\n * Resolves a local `$ref` against the document, or nullish when it cannot.\n */\n resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined\n}\n\n/**\n * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the\n * spec-specific schema questions the parser answers.\n */\nexport type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Identifies the dialect in logs and diagnostics.\n */\n name: string\n /**\n * The spec-specific schema behavior. See {@link SchemaDialect}.\n */\n schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>\n}\n\n/**\n * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the\n * dialect's type for inference.\n *\n * @example\n * ```ts\n * export const oasDialect = defineDialect({\n * name: 'oas',\n * schema: {\n * isNullable,\n * isReference,\n * isDiscriminator,\n * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',\n * resolveRef,\n * },\n * })\n * ```\n */\nexport function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(\n dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>,\n): Dialect<TSchema, TRef, TDiscriminated, TDocument> {\n return dialect\n}\n","import type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/index.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? ({} as T['options']))\n\n const context = {\n options: resolvedOptions,\n transform: (node: SchemaNode): T['output'] | null => {\n const handler = nodes[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n }\n }\n}\n","import type { Node } from './nodes/index.ts'\n\n// Node constructors, grouped under the `factory` namespace the way the TypeScript compiler exposes\n// `ts.factory.createX`. Aggregating them here lets `export * as factory from './factory.ts'` in the\n// barrel surface every `createX` alongside the `createFile`/`update` helpers from a single module.\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { defineDialect } from './defineDialect.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, transform, walk } from './visitor.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,cACd,SACmD;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC2HA,SAAgB,cAAuE,OAAkE;CACvJ,QAAQ,YAAY;EAClB,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,OAAO,kBAAkB,MAAM,WAAY,CAAC,CAAkB;EAE7G,MAAM,UAAU;GACd,SAAS;GACT,YAAY,SAAyC;IACnD,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;EACF;EAEA,OAAO;GACL;GACA,SAAS;GACT,WAAW,QAAQ;GACnB,OAAQ,gBAAgB,cAAc,KAAK,OAAO,IAAI,QAAQ;EAChE;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/KA,SAAgB,OAAuB,MAAS,SAAwB;CACtE,KAAK,MAAM,OAAO,SAChB,IAAI,QAAQ,SAAS,KAAK,MACxB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAQ;CAIjC,OAAO;AACT"} | ||
| {"version":3,"file":"index.cjs","names":[],"sources":["../src/defineDialect.ts","../src/createPrinter.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["/**\n * The spec-specific questions a schema parser answers while turning a source document into Kubb\n * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats\n * differ.\n */\nexport type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Whether the schema is nullable.\n */\n isNullable(schema?: TSchema): boolean\n /**\n * Whether the value is a `$ref` pointer.\n */\n isReference(value?: unknown): value is TRef\n /**\n * Whether the schema carries a discriminator for polymorphism.\n */\n isDiscriminator(value?: unknown): value is TDiscriminated\n /**\n * Whether the schema is binary data, converted to a `blob` node.\n */\n isBinary(schema: TSchema): boolean\n /**\n * Resolves a local `$ref` against the document, or nullish when it cannot.\n */\n resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined\n}\n\n/**\n * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the\n * spec-specific schema questions the parser answers.\n */\nexport type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Identifies the dialect in logs and diagnostics.\n */\n name: string\n /**\n * The spec-specific schema behavior. See {@link SchemaDialect}.\n */\n schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>\n}\n\n/**\n * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the\n * dialect's type for inference.\n *\n * @example\n * ```ts\n * export const oasDialect = defineDialect({\n * name: 'oas',\n * schema: {\n * isNullable,\n * isReference,\n * isDiscriminator,\n * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',\n * resolveRef,\n * },\n * })\n * ```\n */\nexport function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(\n dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>,\n): Dialect<TSchema, TRef, TDiscriminated, TDocument> {\n return dialect\n}\n","import type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/index.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Run the printer's built-in handler for the node, ignoring any override for its type.\n * Inside an override, `this.base(node)` returns what the printer would have emitted,\n * so the override can wrap it instead of re-implementing the handler. Nested nodes\n * still dispatch through the overrides.\n */\n base: (node: SchemaNode) => TOutput | null\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * User-supplied handler overrides. An override wins over the matching `nodes` handler,\n * and can call `this.base(node)` to reuse the handler it replaced. Pass overrides here\n * instead of spreading them into `nodes`, otherwise `this.base` cannot find the original.\n */\n overrides?: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `overrides` (optional), user-supplied handlers that win over `nodes`.\n * An override can call `this.base(node)` to reuse the handler it replaced.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build(options ?? ({} as T['options']))\n const merged = overrides ? { ...nodes, ...overrides } : nodes\n\n const context = {\n options: resolvedOptions,\n transform: (node: SchemaNode): T['output'] | null => {\n const handler = merged[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n base: (node: SchemaNode): T['output'] | null => {\n const handler = nodes[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n }\n }\n}\n","import type { Node } from './nodes/index.ts'\n\n// Node constructors, grouped under the `factory` namespace the way the TypeScript compiler exposes\n// `ts.factory.createX`. Aggregating them here lets `export * as factory from './factory.ts'` in the\n// barrel surface every `createX` alongside the `createFile`/`update` helpers from a single module.\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { defineDialect } from './defineDialect.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, transform, walk } from './visitor.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,cACd,SACmD;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC4IA,SAAgB,cAAuE,OAAkE;CACvJ,QAAQ,YAAY;EAClB,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,WAAW,OAAO,kBAAkB,MAAM,WAAY,CAAC,CAAkB;EACxH,MAAM,SAAS,YAAY;GAAE,GAAG;GAAO,GAAG;EAAU,IAAI;EAExD,MAAM,UAAU;GACd,SAAS;GACT,YAAY,SAAyC;IACnD,MAAM,UAAU,OAAO,KAAK;IAC5B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;GACA,OAAO,SAAyC;IAC9C,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;EACF;EAEA,OAAO;GACL;GACA,SAAS;GACT,WAAW,QAAQ;GACnB,OAAQ,gBAAgB,cAAc,KAAK,OAAO,IAAI,QAAQ;EAChE;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvMA,SAAgB,OAAuB,MAAS,SAAwB;CACtE,KAAK,MAAM,OAAO,SAChB,IAAI,QAAQ,SAAS,KAAK,MACxB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAQ;CAIjC,OAAO;AACT"} |
+3
-3
| import { n as __name, t as __exportAll } from "./rolldown-runtime-CNktS9qV.js"; | ||
| import { a as defineMacro, c as VisitorContext, d as walk, f as schemaTypes, i as composeMacros, l as collect, n as Macro, o as ParentOf, r as applyMacros, s as Visitor, t as Enforce, u as transform } from "./defineMacro-DzsACbFo.js"; | ||
| import { a as Dialect, i as createPrinter, n as PrinterFactoryOptions, o as SchemaDialect, r as PrinterPartial, s as defineDialect, t as Printer } from "./types-Ctz5NB1o.js"; | ||
| import { a as Dialect, i as createPrinter, n as PrinterFactoryOptions, o as SchemaDialect, r as PrinterPartial, s as defineDialect, t as Printer } from "./types-CWF7DV0f.js"; | ||
| import { $ as ScalarSchemaType, A as SourceNode, At as createFunction, B as ContentNode, Bt as defineNode, C as ParameterNode, Ct as TypeNode, D as ExportNode, Dt as createArrowFunction, E as parameterDef, Et as constDef, F as createSource, Ft as jsxDef, G as DatetimeSchemaNode, H as createContent, Ht as NodeKind, I as exportDef, It as textDef, J as NumberSchemaNode, K as EnumSchemaNode, L as fileDef, Lt as typeDef, M as createExport, Mt as createText, N as createFile, Nt as createType, O as FileNode, Ot as createBreak, P as createImport, Pt as functionDef, Q as ScalarSchemaNode, R as importDef, Rt as DistributiveOmit, S as ParameterLocation, St as TextNode, T as createParameter, Tt as breakDef, U as ArraySchemaNode, V as contentDef, Vt as BaseNode, W as DateSchemaNode, X as PrimitiveSchemaType, Y as ObjectSchemaNode, Z as RefSchemaNode, _ as createResponse, _t as CodeNode, a as InputMeta, at as UnionSchemaNode, b as createRequestBody, bt as JSDocNode, c as inputDef, ct as schemaDef, d as HttpOperationNode, dt as createProperty, et as SchemaNode, f as OperationNode, ft as propertyDef, g as StatusCode, gt as BreakNode, h as ResponseNode, ht as ArrowFunctionNode, i as outputDef, it as TimeSchemaNode, j as UserFileNode, jt as createJsx, k as ImportNode, kt as createConst, l as GenericOperationNode, lt as PropertyNode, m as operationDef, mt as ParserOptions, n as OutputNode, nt as SchemaType, o as InputNode, ot as UrlSchemaNode, p as createOperation, pt as InferSchemaNode, q as IntersectionSchemaNode, r as createOutput, rt as StringSchemaNode, s as createInput, st as createSchema, t as Node, tt as SchemaNodeByType, u as HttpMethod, ut as UserPropertyNode, v as responseDef, vt as ConstNode, w as ParameterStyle, wt as arrowFunctionDef, x as requestBodyDef, xt as JsxNode, y as RequestBodyNode, yt as FunctionNode, z as sourceDef, zt as NodeDef } from "./index-Cu2zmNxv.js"; | ||
@@ -61,3 +61,3 @@ | ||
| */ | ||
| declare const nodeDefs: (NodeDef<PropertyNode, UserPropertyNode> | NodeDef<ConstNode, Omit<ConstNode, "kind">> | NodeDef<TypeNode, Omit<TypeNode, "kind">> | NodeDef<FunctionNode, Omit<FunctionNode, "kind">> | NodeDef<ArrowFunctionNode, Omit<ArrowFunctionNode, "kind">> | NodeDef<TextNode, string> | NodeDef<BreakNode, void> | NodeDef<JsxNode, string> | NodeDef<SchemaNode, (Omit<ObjectSchemaNode, "kind" | "primitive" | "properties"> & { | ||
| declare const nodeDefs: (NodeDef<PropertyNode, UserPropertyNode> | NodeDef<ConstNode, Omit<ConstNode, "kind">> | NodeDef<TypeNode, Omit<TypeNode, "kind">> | NodeDef<FunctionNode, Omit<FunctionNode, "kind">> | NodeDef<ArrowFunctionNode, Omit<ArrowFunctionNode, "kind">> | NodeDef<TextNode, string> | NodeDef<BreakNode, void> | NodeDef<JsxNode, string> | NodeDef<SchemaNode, (Omit<ObjectSchemaNode, "properties" | "kind" | "primitive"> & { | ||
| properties?: Array<PropertyNode>; | ||
@@ -129,3 +129,3 @@ primitive?: "object"; | ||
| keysToOmit?: Array<string> | null; | ||
| }> | NodeDef<ParameterNode, Pick<ParameterNode, "name" | "schema" | "in"> & Partial<Omit<ParameterNode, "kind" | "name" | "schema" | "in">>> | NodeDef<ImportNode, Omit<ImportNode, "kind">> | NodeDef<ExportNode, Omit<ExportNode, "kind">> | NodeDef<SourceNode, Omit<SourceNode, "kind">> | NodeDef<FileNode<object>, Omit<FileNode<object>, "kind">>)[]; | ||
| }> | NodeDef<ParameterNode, Pick<ParameterNode, "name" | "schema" | "in"> & Partial<Omit<ParameterNode, "name" | "kind" | "schema" | "in">>> | NodeDef<ImportNode, Omit<ImportNode, "kind">> | NodeDef<ExportNode, Omit<ExportNode, "kind">> | NodeDef<SourceNode, Omit<SourceNode, "kind">> | NodeDef<FileNode<object>, Omit<FileNode<object>, "kind">>)[]; | ||
| declare namespace exports_d_exports { | ||
@@ -132,0 +132,0 @@ export { ArraySchemaNode, ArrowFunctionNode, BreakNode, CodeNode, ConstNode, ContentNode, DateSchemaNode, DatetimeSchemaNode, Dialect, DistributiveOmit, Enforce, EnumSchemaNode, ExportNode, FileNode, FunctionNode, GenericOperationNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, IntersectionSchemaNode, JSDocNode, JsxNode, Macro, Node, NodeDef, NodeKind, NumberSchemaNode, ObjectSchemaNode, OperationNode, OutputNode, ParameterLocation, ParameterNode, ParameterStyle, ParentOf, ParserOptions, PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, PropertyNode, RefSchemaNode, RequestBodyNode, ResponseNode, ScalarSchemaNode, ScalarSchemaType, SchemaDialect, SchemaNode, SchemaNodeByType, SchemaType, SourceNode, StatusCode, StringSchemaNode, TextNode, TimeSchemaNode, TypeNode, UnionSchemaNode, UrlSchemaNode, UserFileNode, Visitor, VisitorContext, applyMacros, arrowFunctionDef, breakDef, collect, composeMacros, constDef, contentDef, createPrinter, defineDialect, defineMacro, defineNode, exportDef, factory_d_exports as factory, fileDef, functionDef, importDef, inputDef, isHttpOperationNode, jsxDef, narrowSchema, nodeDefs, operationDef, optionality, outputDef, parameterDef, propertyDef, requestBodyDef, responseDef, schemaDef, schemaTypes, sourceDef, textDef, transform, typeDef, walk }; |
+12
-1
@@ -40,2 +40,4 @@ import { t as __exportAll } from "./rolldown-runtime-CNktS9qV.js"; | ||
| * output (a string, a TypeScript AST node, ...) for that schema type. | ||
| * - `overrides` (optional), user-supplied handlers that win over `nodes`. | ||
| * An override can call `this.base(node)` to reuse the handler it replaced. | ||
| * - `print` (optional), top-level override exposed as `printer.print`. | ||
@@ -70,6 +72,15 @@ * Use `this.transform(node)` inside it to dispatch to `nodes` recursively. | ||
| return (options) => { | ||
| const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? {}); | ||
| const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build(options ?? {}); | ||
| const merged = overrides ? { | ||
| ...nodes, | ||
| ...overrides | ||
| } : nodes; | ||
| const context = { | ||
| options: resolvedOptions, | ||
| transform: (node) => { | ||
| const handler = merged[node.type]; | ||
| if (!handler) return null; | ||
| return handler.call(context, node); | ||
| }, | ||
| base: (node) => { | ||
| const handler = nodes[node.type]; | ||
@@ -76,0 +87,0 @@ if (!handler) return null; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","names":[],"sources":["../src/defineDialect.ts","../src/createPrinter.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["/**\n * The spec-specific questions a schema parser answers while turning a source document into Kubb\n * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats\n * differ.\n */\nexport type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Whether the schema is nullable.\n */\n isNullable(schema?: TSchema): boolean\n /**\n * Whether the value is a `$ref` pointer.\n */\n isReference(value?: unknown): value is TRef\n /**\n * Whether the schema carries a discriminator for polymorphism.\n */\n isDiscriminator(value?: unknown): value is TDiscriminated\n /**\n * Whether the schema is binary data, converted to a `blob` node.\n */\n isBinary(schema: TSchema): boolean\n /**\n * Resolves a local `$ref` against the document, or nullish when it cannot.\n */\n resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined\n}\n\n/**\n * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the\n * spec-specific schema questions the parser answers.\n */\nexport type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Identifies the dialect in logs and diagnostics.\n */\n name: string\n /**\n * The spec-specific schema behavior. See {@link SchemaDialect}.\n */\n schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>\n}\n\n/**\n * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the\n * dialect's type for inference.\n *\n * @example\n * ```ts\n * export const oasDialect = defineDialect({\n * name: 'oas',\n * schema: {\n * isNullable,\n * isReference,\n * isDiscriminator,\n * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',\n * resolveRef,\n * },\n * })\n * ```\n */\nexport function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(\n dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>,\n): Dialect<TSchema, TRef, TDiscriminated, TDocument> {\n return dialect\n}\n","import type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/index.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? ({} as T['options']))\n\n const context = {\n options: resolvedOptions,\n transform: (node: SchemaNode): T['output'] | null => {\n const handler = nodes[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n }\n }\n}\n","import type { Node } from './nodes/index.ts'\n\n// Node constructors, grouped under the `factory` namespace the way the TypeScript compiler exposes\n// `ts.factory.createX`. Aggregating them here lets `export * as factory from './factory.ts'` in the\n// barrel surface every `createX` alongside the `createFile`/`update` helpers from a single module.\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { defineDialect } from './defineDialect.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, transform, walk } from './visitor.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,cACd,SACmD;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC2HA,SAAgB,cAAuE,OAAkE;CACvJ,QAAQ,YAAY;EAClB,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,OAAO,kBAAkB,MAAM,WAAY,CAAC,CAAkB;EAE7G,MAAM,UAAU;GACd,SAAS;GACT,YAAY,SAAyC;IACnD,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;EACF;EAEA,OAAO;GACL;GACA,SAAS;GACT,WAAW,QAAQ;GACnB,OAAQ,gBAAgB,cAAc,KAAK,OAAO,IAAI,QAAQ;EAChE;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/KA,SAAgB,OAAuB,MAAS,SAAwB;CACtE,KAAK,MAAM,OAAO,SAChB,IAAI,QAAQ,SAAS,KAAK,MACxB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAQ;CAIjC,OAAO;AACT"} | ||
| {"version":3,"file":"index.js","names":[],"sources":["../src/defineDialect.ts","../src/createPrinter.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["/**\n * The spec-specific questions a schema parser answers while turning a source document into Kubb\n * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats\n * differ.\n */\nexport type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Whether the schema is nullable.\n */\n isNullable(schema?: TSchema): boolean\n /**\n * Whether the value is a `$ref` pointer.\n */\n isReference(value?: unknown): value is TRef\n /**\n * Whether the schema carries a discriminator for polymorphism.\n */\n isDiscriminator(value?: unknown): value is TDiscriminated\n /**\n * Whether the schema is binary data, converted to a `blob` node.\n */\n isBinary(schema: TSchema): boolean\n /**\n * Resolves a local `$ref` against the document, or nullish when it cannot.\n */\n resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined\n}\n\n/**\n * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the\n * spec-specific schema questions the parser answers.\n */\nexport type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {\n /**\n * Identifies the dialect in logs and diagnostics.\n */\n name: string\n /**\n * The spec-specific schema behavior. See {@link SchemaDialect}.\n */\n schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>\n}\n\n/**\n * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the\n * dialect's type for inference.\n *\n * @example\n * ```ts\n * export const oasDialect = defineDialect({\n * name: 'oas',\n * schema: {\n * isNullable,\n * isReference,\n * isDiscriminator,\n * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',\n * resolveRef,\n * },\n * })\n * ```\n */\nexport function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(\n dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>,\n): Dialect<TSchema, TRef, TDiscriminated, TDocument> {\n return dialect\n}\n","import type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/index.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Run the printer's built-in handler for the node, ignoring any override for its type.\n * Inside an override, `this.base(node)` returns what the printer would have emitted,\n * so the override can wrap it instead of re-implementing the handler. Nested nodes\n * still dispatch through the overrides.\n */\n base: (node: SchemaNode) => TOutput | null\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * User-supplied handler overrides. An override wins over the matching `nodes` handler,\n * and can call `this.base(node)` to reuse the handler it replaced. Pass overrides here\n * instead of spreading them into `nodes`, otherwise `this.base` cannot find the original.\n */\n overrides?: Partial<{\n [K in SchemaType]: PrinterHandler<T['output'], T['options'], K>\n }>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `overrides` (optional), user-supplied handlers that win over `nodes`.\n * An override can call `this.base(node)` to reuse the handler it replaced.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build(options ?? ({} as T['options']))\n const merged = overrides ? { ...nodes, ...overrides } : nodes\n\n const context = {\n options: resolvedOptions,\n transform: (node: SchemaNode): T['output'] | null => {\n const handler = merged[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n base: (node: SchemaNode): T['output'] | null => {\n const handler = nodes[node.type]\n if (!handler) return null\n\n return (handler as (this: typeof context, node: SchemaNode) => T['output'] | null).call(context, node)\n },\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n }\n }\n}\n","import type { Node } from './nodes/index.ts'\n\n// Node constructors, grouped under the `factory` namespace the way the TypeScript compiler exposes\n// `ts.factory.createX`. Aggregating them here lets `export * as factory from './factory.ts'` in the\n// barrel surface every `createX` alongside the `createFile`/`update` helpers from a single module.\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { defineDialect } from './defineDialect.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, transform, walk } from './visitor.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,cACd,SACmD;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC4IA,SAAgB,cAAuE,OAAkE;CACvJ,QAAQ,YAAY;EAClB,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,WAAW,OAAO,kBAAkB,MAAM,WAAY,CAAC,CAAkB;EACxH,MAAM,SAAS,YAAY;GAAE,GAAG;GAAO,GAAG;EAAU,IAAI;EAExD,MAAM,UAAU;GACd,SAAS;GACT,YAAY,SAAyC;IACnD,MAAM,UAAU,OAAO,KAAK;IAC5B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;GACA,OAAO,SAAyC;IAC9C,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,SAAS,OAAO;IAErB,OAAQ,QAA2E,KAAK,SAAS,IAAI;GACvG;EACF;EAEA,OAAO;GACL;GACA,SAAS;GACT,WAAW,QAAQ;GACnB,OAAQ,gBAAgB,cAAc,KAAK,OAAO,IAAI,QAAQ;EAChE;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvMA,SAAgB,OAAuB,MAAS,SAAwB;CACtE,KAAK,MAAM,OAAO,SAChB,IAAI,QAAQ,SAAS,KAAK,MACxB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAQ;CAIjC,OAAO;AACT"} |
+1
-1
| import { c as VisitorContext, n as Macro, o as ParentOf, s as Visitor, t as Enforce } from "./defineMacro-DzsACbFo.js"; | ||
| import { a as Dialect, n as PrinterFactoryOptions, o as SchemaDialect, r as PrinterPartial, t as Printer } from "./types-Ctz5NB1o.js"; | ||
| import { a as Dialect, n as PrinterFactoryOptions, o as SchemaDialect, r as PrinterPartial, t as Printer } from "./types-CWF7DV0f.js"; | ||
| import { $ as ScalarSchemaType, A as SourceNode, B as ContentNode, C as ParameterNode, Ct as TypeNode, D as ExportNode, G as DatetimeSchemaNode, Ht as NodeKind, J as NumberSchemaNode, K as EnumSchemaNode, O as FileNode, Q as ScalarSchemaNode, Rt as DistributiveOmit, S as ParameterLocation, St as TextNode, U as ArraySchemaNode, W as DateSchemaNode, X as PrimitiveSchemaType, Y as ObjectSchemaNode, Z as RefSchemaNode, _t as CodeNode, a as InputMeta, at as UnionSchemaNode, bt as JSDocNode, d as HttpOperationNode, et as SchemaNode, f as OperationNode, g as StatusCode, gt as BreakNode, h as ResponseNode, ht as ArrowFunctionNode, it as TimeSchemaNode, j as UserFileNode, k as ImportNode, l as GenericOperationNode, lt as PropertyNode, mt as ParserOptions, n as OutputNode, nt as SchemaType, o as InputNode, ot as UrlSchemaNode, pt as InferSchemaNode, q as IntersectionSchemaNode, rt as StringSchemaNode, t as Node, tt as SchemaNodeByType, u as HttpMethod, vt as ConstNode, w as ParameterStyle, xt as JsxNode, y as RequestBodyNode, yt as FunctionNode, zt as NodeDef } from "./index-Cu2zmNxv.js"; | ||
| export type { ArraySchemaNode, ArrowFunctionNode, BreakNode, CodeNode, ConstNode, ContentNode, DateSchemaNode, DatetimeSchemaNode, Dialect, DistributiveOmit, Enforce, EnumSchemaNode, ExportNode, FileNode, FunctionNode, GenericOperationNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, IntersectionSchemaNode, JSDocNode, JsxNode, Macro, Node, NodeDef, NodeKind, NumberSchemaNode, ObjectSchemaNode, OperationNode, OutputNode, ParameterLocation, ParameterNode, ParameterStyle, ParentOf, ParserOptions, PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, PropertyNode, RefSchemaNode, RequestBodyNode, ResponseNode, ScalarSchemaNode, ScalarSchemaType, SchemaDialect, SchemaNode, SchemaNodeByType, SchemaType, SourceNode, StatusCode, StringSchemaNode, TextNode, TimeSchemaNode, TypeNode, UnionSchemaNode, UrlSchemaNode, UserFileNode, Visitor, VisitorContext }; |
+1
-1
| { | ||
| "name": "@kubb/ast", | ||
| "version": "5.0.0-beta.79", | ||
| "version": "5.0.0-beta.80", | ||
| "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,0 +5,0 @@ "keywords": [ |
| import { n as __name } from "./rolldown-runtime-CNktS9qV.js"; | ||
| import { et as SchemaNode, nt as SchemaType, tt as SchemaNodeByType } from "./index-Cu2zmNxv.js"; | ||
| //#region src/defineDialect.d.ts | ||
| /** | ||
| * The spec-specific questions a schema parser answers while turning a source document into Kubb | ||
| * AST nodes. The rest of the pipeline is generic, so this is the one seam where source formats | ||
| * differ. | ||
| */ | ||
| type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = { | ||
| /** | ||
| * Whether the schema is nullable. | ||
| */ | ||
| isNullable(schema?: TSchema): boolean; | ||
| /** | ||
| * Whether the value is a `$ref` pointer. | ||
| */ | ||
| isReference(value?: unknown): value is TRef; | ||
| /** | ||
| * Whether the schema carries a discriminator for polymorphism. | ||
| */ | ||
| isDiscriminator(value?: unknown): value is TDiscriminated; | ||
| /** | ||
| * Whether the schema is binary data, converted to a `blob` node. | ||
| */ | ||
| isBinary(schema: TSchema): boolean; | ||
| /** | ||
| * Resolves a local `$ref` against the document, or nullish when it cannot. | ||
| */ | ||
| resolveRef<TResolved>(document: TDocument, ref: string): TResolved | null | undefined; | ||
| }; | ||
| /** | ||
| * A spec adapter's dialect. `name` identifies it in logs and diagnostics, and `schema` holds the | ||
| * spec-specific schema questions the parser answers. | ||
| */ | ||
| type Dialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = { | ||
| /** | ||
| * Identifies the dialect in logs and diagnostics. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * The spec-specific schema behavior. See {@link SchemaDialect}. | ||
| */ | ||
| schema: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>; | ||
| }; | ||
| /** | ||
| * Types a {@link Dialect} for an adapter. Adds no runtime behavior and only pins the | ||
| * dialect's type for inference. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * export const oasDialect = defineDialect({ | ||
| * name: 'oas', | ||
| * schema: { | ||
| * isNullable, | ||
| * isReference, | ||
| * isDiscriminator, | ||
| * isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream', | ||
| * resolveRef, | ||
| * }, | ||
| * }) | ||
| * ``` | ||
| */ | ||
| declare function defineDialect<TSchema, TRef, TDiscriminated, TDocument>(dialect: Dialect<TSchema, TRef, TDiscriminated, TDocument>): Dialect<TSchema, TRef, TDiscriminated, TDocument>; | ||
| //#endregion | ||
| //#region src/createPrinter.d.ts | ||
| /** | ||
| * Runtime context passed as `this` to printer handlers. | ||
| * | ||
| * `this.transform` dispatches to node-level handlers from `nodes`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const context: PrinterHandlerContext<string, {}> = { | ||
| * options: {}, | ||
| * transform: () => 'value', | ||
| * } | ||
| * ``` | ||
| */ | ||
| type PrinterHandlerContext<TOutput, TOptions extends object> = { | ||
| /** | ||
| * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers. | ||
| * Use `this.transform` inside `nodes` handlers and inside the `print` override. | ||
| */ | ||
| transform: (node: SchemaNode) => TOutput | null; | ||
| /** | ||
| * Options for this printer instance. | ||
| */ | ||
| options: TOptions; | ||
| }; | ||
| /** | ||
| * Handler for one schema node type. | ||
| * | ||
| * Use a regular function (not an arrow function) if you need `this`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const handler: PrinterHandler<string, {}, 'string'> = function () { | ||
| * return 'string' | ||
| * } | ||
| * ``` | ||
| */ | ||
| type PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (this: PrinterHandlerContext<TOutput, TOptions>, node: SchemaNodeByType[T]) => TOutput | null; | ||
| /** | ||
| * Partial map of per-node-type handler overrides for a printer. | ||
| * | ||
| * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`). | ||
| * Supply only the handlers you want to replace. The printer's built-in | ||
| * defaults fill in the rest. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * pluginZod({ | ||
| * printer: { | ||
| * nodes: { | ||
| * date(): string { | ||
| * return 'z.string().date()' | ||
| * }, | ||
| * } satisfies PrinterPartial<string, PrinterZodOptions>, | ||
| * }, | ||
| * }) | ||
| * ``` | ||
| */ | ||
| type PrinterPartial<TOutput, TOptions extends object> = Partial<{ [K in SchemaType]: PrinterHandler<TOutput, TOptions, K> }>; | ||
| /** | ||
| * Generic shape used by `definePrinter`. | ||
| * | ||
| * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`) | ||
| * - `TOptions` options passed to and stored on the printer instance | ||
| * - `TOutput` the type emitted by node handlers | ||
| * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string> | ||
| * ``` | ||
| */ | ||
| type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = { | ||
| name: TName; | ||
| options: TOptions; | ||
| output: TOutput; | ||
| printOutput: TPrintOutput; | ||
| }; | ||
| /** | ||
| * Printer instance returned by a printer factory. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({}) | ||
| * ``` | ||
| */ | ||
| type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = { | ||
| /** | ||
| * Unique identifier supplied at creation time. | ||
| */ | ||
| name: T['name']; | ||
| /** | ||
| * Options for this printer instance. | ||
| */ | ||
| options: T['options']; | ||
| /** | ||
| * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers. | ||
| * Always dispatches through the `nodes` map. Never calls the `print` override. | ||
| * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping. | ||
| */ | ||
| transform: (node: SchemaNode) => T['output'] | null; | ||
| /** | ||
| * Public printer. If the builder provides a root-level `print`, this calls that | ||
| * higher-level function (which may produce full declarations). | ||
| * Otherwise, falls back to the node-level dispatcher. | ||
| */ | ||
| print: (node: SchemaNode) => T['printOutput'] | null; | ||
| }; | ||
| /** | ||
| * Builder function passed to `definePrinter`. | ||
| * | ||
| * It receives resolved options and returns: | ||
| * - `name` | ||
| * - `options` | ||
| * - `nodes` handlers | ||
| * - optional top-level `print` override | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} }) | ||
| * ``` | ||
| */ | ||
| type PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => { | ||
| name: T['name']; | ||
| /** | ||
| * Options to store on the printer. | ||
| */ | ||
| options: T['options']; | ||
| nodes: Partial<{ [K in SchemaType]: PrinterHandler<T['output'], T['options'], K> }>; | ||
| /** | ||
| * Optional root-level print override. When provided, becomes the public `printer.print`. | ||
| * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`), | ||
| * not the override itself, so recursion is safe. | ||
| */ | ||
| print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null; | ||
| }; | ||
| /** | ||
| * Creates a schema printer: a function that takes a `SchemaNode` and emits | ||
| * code in your target language. Each plugin that produces code from schemas | ||
| * (TypeScript types, Zod schemas, Faker factories) ships a printer built | ||
| * with this helper. | ||
| * | ||
| * The builder receives resolved options and returns: | ||
| * | ||
| * - `name` unique identifier for the printer. | ||
| * - `options` stored on the returned printer instance. | ||
| * - `nodes` map of `SchemaType` → handler. Handlers return the rendered | ||
| * output (a string, a TypeScript AST node, ...) for that schema type. | ||
| * - `print` (optional), top-level override exposed as `printer.print`. | ||
| * Use `this.transform(node)` inside it to dispatch to `nodes` recursively. | ||
| * | ||
| * Without a `print` override, `printer.print` falls back to `printer.transform` | ||
| * (the node-level dispatcher). | ||
| * | ||
| * @example Tiny Zod printer | ||
| * ```ts | ||
| * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast' | ||
| * | ||
| * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string> | ||
| * | ||
| * export const zodPrinter = createPrinter<PrinterZod>((options) => ({ | ||
| * name: 'zod', | ||
| * options: { strict: options.strict ?? true }, | ||
| * nodes: { | ||
| * string: () => 'z.string()', | ||
| * object(node) { | ||
| * const props = node.properties | ||
| * .map((p) => `${p.name}: ${this.transform(p.schema)}`) | ||
| * .join(', ') | ||
| * return `z.object({ ${props} })` | ||
| * }, | ||
| * }, | ||
| * })) | ||
| * ``` | ||
| */ | ||
| declare function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T>; | ||
| //#endregion | ||
| export { Dialect as a, createPrinter as i, PrinterFactoryOptions as n, SchemaDialect as o, PrinterPartial as r, defineDialect as s, Printer as t }; | ||
| //# sourceMappingURL=types-Ctz5NB1o.d.ts.map |
650674
0.69%8582
0.43%