@kubb/ast 5.0.0-beta.54 → 5.0.0-beta.56

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.
@@ -1567,6 +1567,22 @@ type FunctionParamNode = FunctionParameterNode | ParameterGroupNode | FunctionPa
1567
1567
  */
1568
1568
  type FunctionNodeType = 'functionParameter' | 'parameterGroup' | 'functionParameters' | 'paramsType';
1569
1569
  //#endregion
1570
+ //#region ../../internals/utils/src/promise.d.ts
1571
+ /**
1572
+ * Container that switches between an eager `Array<T>` and a lazy `AsyncIterable<T>`.
1573
+ *
1574
+ * `Array<T>` by default. With `Stream` set to `true` it becomes `AsyncIterable<T>`, so large
1575
+ * collections can be produced lazily without holding every item in memory. Pairs with
1576
+ * {@link arrayToAsyncIterable}, which lifts a plain array into the streaming form.
1577
+ *
1578
+ * @example
1579
+ * ```ts
1580
+ * type Eager = Streamable<number> // Array<number>
1581
+ * type Lazy = Streamable<number, true> // AsyncIterable<number>
1582
+ * ```
1583
+ */
1584
+ type Streamable<T, Stream extends boolean = false> = Stream extends true ? AsyncIterable<T> : Array<T>;
1585
+ //#endregion
1570
1586
  //#region src/nodes/parameter.d.ts
1571
1587
  type ParameterLocation = 'path' | 'query' | 'header' | 'cookie';
1572
1588
  /**
@@ -1606,6 +1622,47 @@ type ParameterNode = BaseNode & {
1606
1622
  required: boolean;
1607
1623
  };
1608
1624
  //#endregion
1625
+ //#region src/nodes/requestBody.d.ts
1626
+ /**
1627
+ * AST node representing an operation request body.
1628
+ *
1629
+ * Body schemas live exclusively inside the `content` array (one entry per content type),
1630
+ * mirroring {@link ResponseNode}.
1631
+ *
1632
+ * @example
1633
+ * ```ts
1634
+ * const requestBody: RequestBodyNode = {
1635
+ * kind: 'RequestBody',
1636
+ * required: true,
1637
+ * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
1638
+ * }
1639
+ * ```
1640
+ */
1641
+ type RequestBodyNode = BaseNode & {
1642
+ /**
1643
+ * Node kind.
1644
+ */
1645
+ kind: 'RequestBody';
1646
+ /**
1647
+ * Human-readable request body description.
1648
+ */
1649
+ description?: string;
1650
+ /**
1651
+ * Whether the request body is required (`requestBody.required: true` in the spec).
1652
+ * When `false` or absent, the generated `data` parameter should be optional.
1653
+ */
1654
+ required?: boolean;
1655
+ /**
1656
+ * All available content type entries for this request body.
1657
+ *
1658
+ * When the adapter `contentType` option is set, this array contains exactly one entry for
1659
+ * that content type. Otherwise it contains one entry per content type declared in the spec,
1660
+ * so that plugins can generate code for every variant (e.g. separate hooks for
1661
+ * `application/json` and `multipart/form-data`).
1662
+ */
1663
+ content?: Array<ContentNode>;
1664
+ };
1665
+ //#endregion
1609
1666
  //#region src/nodes/http.d.ts
1610
1667
  /**
1611
1668
  * All supported HTTP status code literals as strings, as used in API specs
@@ -1679,45 +1736,6 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTION
1679
1736
  * Transport an operation belongs to.
1680
1737
  */
1681
1738
  type OperationProtocol = 'http';
1682
- /**
1683
- * AST node representing an operation request body.
1684
- *
1685
- * Body schemas live exclusively inside the `content` array (one entry per content type),
1686
- * mirroring {@link ResponseNode}.
1687
- *
1688
- * @example
1689
- * ```ts
1690
- * const requestBody: RequestBodyNode = {
1691
- * kind: 'RequestBody',
1692
- * required: true,
1693
- * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
1694
- * }
1695
- * ```
1696
- */
1697
- type RequestBodyNode = BaseNode & {
1698
- /**
1699
- * Node kind.
1700
- */
1701
- kind: 'RequestBody';
1702
- /**
1703
- * Human-readable request body description.
1704
- */
1705
- description?: string;
1706
- /**
1707
- * Whether the request body is required (`requestBody.required: true` in the spec).
1708
- * When `false` or absent, the generated `data` parameter should be optional.
1709
- */
1710
- required?: boolean;
1711
- /**
1712
- * All available content type entries for this request body.
1713
- *
1714
- * When the adapter `contentType` option is set, this array contains exactly one entry for
1715
- * that content type. Otherwise it contains one entry per content type declared in the spec,
1716
- * so that plugins can generate code for every variant (e.g. separate hooks for
1717
- * `application/json` and `multipart/form-data`).
1718
- */
1719
- content?: Array<ContentNode>;
1720
- };
1721
1739
  /**
1722
1740
  * Fields shared by every operation, regardless of transport.
1723
1741
  */
@@ -1811,32 +1829,7 @@ type GenericOperationNode = OperationNodeBase & {
1811
1829
  */
1812
1830
  type OperationNode = HttpOperationNode | GenericOperationNode;
1813
1831
  //#endregion
1814
- //#region src/nodes/output.d.ts
1815
- /**
1816
- * Output AST node that groups all generated file output for one API document.
1817
- *
1818
- * Produced by generators and consumed by the build pipeline to write files.
1819
- *
1820
- * @example
1821
- * ```ts
1822
- * const output: OutputNode = {
1823
- * kind: 'Output',
1824
- * files: [],
1825
- * }
1826
- * ```
1827
- */
1828
- type OutputNode = BaseNode & {
1829
- /**
1830
- * Node kind.
1831
- */
1832
- kind: 'Output';
1833
- /**
1834
- * Generated file nodes.
1835
- */
1836
- files: Array<FileNode>;
1837
- };
1838
- //#endregion
1839
- //#region src/nodes/root.d.ts
1832
+ //#region src/nodes/input.d.ts
1840
1833
  /**
1841
1834
  * Metadata for an API document, populated by the adapter and available to every generator.
1842
1835
  *
@@ -1899,16 +1892,28 @@ type InputMeta = {
1899
1892
  * Input AST node that contains all schemas and operations for one API document.
1900
1893
  * Produced by the adapter and consumed by all Kubb plugins.
1901
1894
  *
1895
+ * `Stream` switches `schemas` and `operations` between eager `Array`s (the default) and lazy
1896
+ * `AsyncIterable`s. The streaming variant `InputNode<true>` yields nodes one at a time and makes
1897
+ * `meta` optional, since the adapter can emit metadata before the first node is parsed.
1898
+ *
1902
1899
  * @example
1903
1900
  * ```ts
1904
1901
  * const input: InputNode = {
1905
1902
  * kind: 'Input',
1906
1903
  * schemas: [],
1907
1904
  * operations: [],
1905
+ * meta: { circularNames: [], enumNames: [] },
1906
+ * }
1907
+ * ```
1908
+ *
1909
+ * @example Streaming variant for large specs
1910
+ * ```ts
1911
+ * for await (const schema of inputNode.schemas) {
1912
+ * // only this one SchemaNode is live here. Previous ones are GC-eligible
1908
1913
  * }
1909
1914
  * ```
1910
1915
  */
1911
- type InputNode = BaseNode & {
1916
+ type InputNode<Stream extends boolean = false> = BaseNode & {
1912
1917
  /**
1913
1918
  * Node kind.
1914
1919
  */
@@ -1916,46 +1921,40 @@ type InputNode = BaseNode & {
1916
1921
  /**
1917
1922
  * All schema nodes in the document.
1918
1923
  */
1919
- schemas: Array<SchemaNode>;
1924
+ schemas: Streamable<SchemaNode, Stream>;
1920
1925
  /**
1921
1926
  * All operation nodes in the document.
1922
1927
  */
1923
- operations: Array<OperationNode>;
1924
- /**
1925
- * Document metadata populated by the adapter.
1926
- */
1928
+ operations: Streamable<OperationNode, Stream>;
1929
+ } & (Stream extends true ? {
1930
+ meta?: InputMeta;
1931
+ } : {
1927
1932
  meta: InputMeta;
1928
- };
1933
+ });
1934
+ //#endregion
1935
+ //#region src/nodes/output.d.ts
1929
1936
  /**
1930
- * Streaming variant of `InputNode` for memory-efficient processing of large API specs.
1937
+ * Output AST node that groups all generated file output for one API document.
1931
1938
  *
1932
- * `schemas` and `operations` are `AsyncIterable` rather than arrays, each `for await`
1933
- * loop creates a fresh parse pass from the cached in-memory document, so multiple
1934
- * consumers (plugins) can iterate independently without keeping all nodes in memory.
1939
+ * Produced by generators and consumed by the build pipeline to write files.
1935
1940
  *
1936
1941
  * @example
1937
1942
  * ```ts
1938
- * for await (const schema of inputStreamNode.schemas) {
1939
- * // only this one SchemaNode is live here. Previous ones are GC-eligible
1943
+ * const output: OutputNode = {
1944
+ * kind: 'Output',
1945
+ * files: [],
1940
1946
  * }
1941
1947
  * ```
1942
1948
  */
1943
- type InputStreamNode = {
1944
- kind: 'Input';
1945
- /**
1946
- * Lazily parsed schema nodes. Each `for await` creates a fresh parse pass, so
1947
- * multiple plugins can iterate independently without sharing state.
1948
- */
1949
- schemas: AsyncIterable<SchemaNode>;
1949
+ type OutputNode = BaseNode & {
1950
1950
  /**
1951
- * Lazily parsed operation nodes. Each `for await` creates a fresh parse pass, so
1952
- * multiple plugins can iterate independently without sharing state.
1951
+ * Node kind.
1953
1952
  */
1954
- operations: AsyncIterable<OperationNode>;
1953
+ kind: 'Output';
1955
1954
  /**
1956
- * Document metadata available immediately, before the first yielded node.
1955
+ * Generated file nodes.
1957
1956
  */
1958
- meta?: InputMeta;
1957
+ files: Array<FileNode>;
1959
1958
  };
1960
1959
  //#endregion
1961
1960
  //#region src/nodes/index.d.ts
@@ -2087,38 +2086,39 @@ declare function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedup
2087
2086
  //#endregion
2088
2087
  //#region src/dialect.d.ts
2089
2088
  /**
2090
- * The spec-specific decisions a schema parser makes when converting a source document's schemas
2091
- * into Kubb AST nodes. Everything else in an adapter's schema pipeline is generic JSON Schema,
2092
- * shared across specs, so the dialect is the one seam where specs differ, like a database driver
2093
- * targeting Postgres vs MySQL. Pair it with {@link dispatch}: the rule table picks which converter
2094
- * runs, the dialect answers the spec-specific questions inside it.
2095
- *
2096
- * The guards (`isReference`, `isDiscriminator`) are type predicates, so converters narrow the
2097
- * schema after a check and the type parameters carry the narrowed types through.
2098
- *
2099
- * This is the seam for the JSON Schema family: OpenAPI, AsyncAPI, and plain JSON Schema share
2100
- * `$ref`, `allOf`/`oneOf`, `enum`, and `format` and differ only in these few decisions. A spec on
2101
- * a different type system (GraphQL, with non-null wrappers and named-type references instead of
2102
- * `$ref`) skips `SchemaDialect` and reuses the universal layer directly: the `Adapter` port, the
2103
- * AST factories, and {@link dispatch} with its own rule table.
2104
- *
2105
- * @typeParam TSchema - The adapter's schema object type (e.g. an OpenAPI `SchemaObject`).
2106
- * @typeParam TRef - The narrowed `$ref` pointer type `isReference` proves.
2107
- * @typeParam TDiscriminated - The narrowed discriminated-schema type `isDiscriminator` proves.
2108
- * @typeParam TDocument - The source document `resolveRef` resolves against.
2089
+ * The spec-specific questions a schema parser answers while turning a source document into Kubb
2090
+ * AST nodes. The rest of the pipeline is generic JSON Schema, so this is the one seam where
2091
+ * OpenAPI, AsyncAPI, and plain JSON Schema differ.
2109
2092
  */
2110
2093
  type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {
2111
- /** Identifies the dialect in logs and while debugging dispatch. */name: string; /** Whether a schema should be treated as nullable. */
2112
- isNullable: (schema?: TSchema) => boolean; /** Whether a value is a `$ref` pointer object. */
2113
- isReference: (value?: unknown) => value is TRef; /** Whether a schema carries a structured discriminator (polymorphism). */
2114
- isDiscriminator: (value?: unknown) => value is TDiscriminated; /** Whether a schema represents binary data (converted to a `blob` node). */
2115
- isBinary: (schema: TSchema) => boolean; /** Resolves a local `$ref` pointer against the document, or nullish when it cannot. */
2094
+ /**
2095
+ * Identifies the dialect in logs and diagnostics.
2096
+ */
2097
+ name: string;
2098
+ /**
2099
+ * Whether the schema is nullable.
2100
+ */
2101
+ isNullable: (schema?: TSchema) => boolean;
2102
+ /**
2103
+ * Whether the value is a `$ref` pointer.
2104
+ */
2105
+ isReference: (value?: unknown) => value is TRef;
2106
+ /**
2107
+ * Whether the schema carries a discriminator for polymorphism.
2108
+ */
2109
+ isDiscriminator: (value?: unknown) => value is TDiscriminated;
2110
+ /**
2111
+ * Whether the schema is binary data, converted to a `blob` node.
2112
+ */
2113
+ isBinary: (schema: TSchema) => boolean;
2114
+ /**
2115
+ * Resolves a local `$ref` against the document, or nullish when it cannot.
2116
+ */
2116
2117
  resolveRef: <TResolved>(document: TDocument, ref: string) => TResolved | null | undefined;
2117
2118
  };
2118
2119
  /**
2119
- * Identity helper that types a {@link SchemaDialect} for an adapter. Like
2120
- * `defineParser`, it adds no runtime behavior, it pins the dialect's type for
2121
- * inference and gives adapter authors a discoverable anchor.
2120
+ * Types a {@link SchemaDialect} for an adapter. Adds no runtime behavior and only pins the
2121
+ * dialect's type for inference.
2122
2122
  *
2123
2123
  * @example
2124
2124
  * ```ts
@@ -2134,50 +2134,6 @@ type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema,
2134
2134
  */
2135
2135
  declare function defineSchemaDialect<TSchema, TRef, TDiscriminated, TDocument>(dialect: SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>): SchemaDialect<TSchema, TRef, TDiscriminated, TDocument>;
2136
2136
  //#endregion
2137
- //#region src/dispatch.d.ts
2138
- /**
2139
- * One entry in an ordered dispatch table: a predicate paired with a converter.
2140
- *
2141
- * @typeParam TContext - Per-input context handed to every rule. A spec adapter typically
2142
- * pre-computes this once per node (the source spec node plus derived fields like a
2143
- * normalized type or resolved options) so individual rules stay cheap predicates.
2144
- * @typeParam TNode - The node a rule produces, e.g. a Kubb AST `SchemaNode`.
2145
- */
2146
- type DispatchRule<TContext, TNode> = {
2147
- /** Identifies the rule when reading the table or debugging which branch ran. */name: string; /** Returns `true` when this rule is responsible for the given context. */
2148
- match: (context: TContext) => boolean;
2149
- /**
2150
- * Produces a node for the context, or `null` to fall through to the next rule.
2151
- *
2152
- * Returning `null` lets a broad `match` defer: e.g. "has a `format`" matches many schemas,
2153
- * but only some formats are convertible, the rest fall through to plain `type` handling.
2154
- */
2155
- convert: (context: TContext) => TNode | null;
2156
- };
2157
- /**
2158
- * Walks an ordered list of {@link DispatchRule}s and returns the first node produced.
2159
- *
2160
- * This is the shared backbone for spec adapters (OpenAPI today, AsyncAPI and others later).
2161
- * The contract an adapter follows is intentionally minimal:
2162
- *
2163
- * context → [rule.match → rule.convert] → node
2164
- *
2165
- * An adapter derives a context from a source spec node, then declares an ordered table of
2166
- * rules mapping spec shapes onto Kubb AST nodes. To add support for a new spec, write a new
2167
- * context type and a new rules table, the traversal here is reused unchanged.
2168
- *
2169
- * Order is significant: earlier rules win, so list higher-precedence or more specific shapes
2170
- * first (e.g. composition keywords before plain `type`). A rule whose `match` returns `true`
2171
- * may still `convert` to `null` to defer to later rules. When no rule produces a node this
2172
- * returns `null`, leaving the caller to apply its own fallback.
2173
- *
2174
- * @example
2175
- * ```ts
2176
- * const node = dispatch(schemaRules, schemaContext) ?? createSchema({ type: fallbackType })
2177
- * ```
2178
- */
2179
- declare function dispatch<TContext, TNode>(rules: ReadonlyArray<DispatchRule<TContext, TNode>>, context: TContext): TNode | null;
2180
- //#endregion
2181
2137
  //#region src/infer.d.ts
2182
2138
  /**
2183
2139
  * Shared parser options used by OAS-to-AST inference and parser flows.
@@ -2391,14 +2347,14 @@ type CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & {
2391
2347
  */
2392
2348
  declare function createInput(overrides?: Partial<Omit<InputNode, 'kind'>>): InputNode;
2393
2349
  /**
2394
- * Creates an `InputStreamNode` from pre-built `AsyncIterable` sources.
2350
+ * Creates a streaming `InputNode<true>` from pre-built `AsyncIterable` sources.
2395
2351
  *
2396
2352
  * @example
2397
2353
  * ```ts
2398
2354
  * const node = createStreamInput(schemasIterable, operationsIterable, { title: 'My API' })
2399
2355
  * ```
2400
2356
  */
2401
- declare function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta): InputStreamNode;
2357
+ declare function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta): InputNode<true>;
2402
2358
  /**
2403
2359
  * Creates an `OutputNode` with a stable default for `files`.
2404
2360
  *
@@ -3584,5 +3540,5 @@ declare function containsCircularRef(node: SchemaNode | undefined, {
3584
3540
  excludeName?: string;
3585
3541
  }): boolean;
3586
3542
  //#endregion
3587
- export { SchemaDialect as $, TypeNode as $t, createFunctionParameter as A, DatetimeSchemaNode as At, createProperty as B, SchemaType as Bt, UserFileNode as C, ParamsTypeNode as Ct, createExport as D, SourceNode as Dt, createConst as E, ImportNode as Et, createOperation as F, PrimitiveSchemaType as Ft, createText as G, PropertyNode as Gt, createSchema as H, TimeSchemaNode as Ht, createOutput as I, RefSchemaNode as It, update as J, ConstNode as Jt, createType as K, ArrowFunctionNode as Kt, createParameter as L, ScalarSchemaType as Lt, createImport as M, IntersectionSchemaNode as Mt, createInput as N, NumberSchemaNode as Nt, createFile as O, ArraySchemaNode as Ot, createJsx as P, ObjectSchemaNode as Pt, dispatch as Q, TextNode as Qt, createParameterGroup as R, SchemaNode as Rt, DistributiveOmit as S, ParameterGroupNode as St, createBreak as T, FileNode as Tt, createSource as U, UnionSchemaNode as Ut, createResponse as V, StringSchemaNode as Vt, createStreamInput as W, UrlSchemaNode as Wt, ParserOptions as X, JSDocNode as Xt, InferSchemaNode as Y, FunctionNode as Yt, DispatchRule as Z, JsxNode as Zt, Printer as _, ParameterNode as _t, createDiscriminantNode as a, buildDedupePlan as at, createPrinterFactory as b, FunctionParameterNode as bt, findCircularSchemas as c, InputNode as ct, ParentOf as d, HttpMethod as dt, NodeKind as en, defineSchemaDialect as et, Visitor as f, HttpOperationNode as ft, walk as g, ParameterLocation as gt, transform as h, StatusCode as ht, containsCircularRef as i, applyDedupe as it, createFunctionParameters as j, EnumSchemaNode as jt, createFunction as k, DateSchemaNode as kt, isStringType as l, InputStreamNode as lt, collect as m, ResponseNode as mt, caseParams as n, schemaTypes as nn, DedupeLookups as nt, createOperationParams as o, Node as ot, VisitorContext as p, OperationNode as pt, syncOptionality as q, CodeNode as qt, collectUsedSchemaNames as r, DedupePlan as rt, extractStringsFromNodes as s, InputMeta as st, OperationParamsResolver as t, httpMethods as tn, DedupeCanonical as tt, syncSchemaRef as u, OutputNode as ut, PrinterFactoryOptions as v, FunctionNodeType as vt, createArrowFunction as w, ExportNode as wt, definePrinter as x, FunctionParametersNode as xt, PrinterPartial as y, FunctionParamNode as yt, createParamsType as z, SchemaNodeByType as zt };
3588
- //# sourceMappingURL=types-BYujEIxF.d.ts.map
3543
+ export { DedupeCanonical as $, schemaTypes as $t, createFunctionParameter as A, NumberSchemaNode as At, createProperty as B, UnionSchemaNode as Bt, UserFileNode as C, ImportNode as Ct, createExport as D, DatetimeSchemaNode as Dt, createConst as E, DateSchemaNode as Et, createOperation as F, SchemaNode as Ft, createText as G, ConstNode as Gt, createSchema as H, PropertyNode as Ht, createOutput as I, SchemaNodeByType as It, update as J, JsxNode as Jt, createType as K, FunctionNode as Kt, createParameter as L, SchemaType as Lt, createImport as M, PrimitiveSchemaType as Mt, createInput as N, RefSchemaNode as Nt, createFile as O, EnumSchemaNode as Ot, createJsx as P, ScalarSchemaType as Pt, defineSchemaDialect as Q, httpMethods as Qt, createParameterGroup as R, StringSchemaNode as Rt, DistributiveOmit as S, FileNode as St, createBreak as T, ArraySchemaNode as Tt, createSource as U, ArrowFunctionNode as Ut, createResponse as V, UrlSchemaNode as Vt, createStreamInput as W, CodeNode as Wt, ParserOptions as X, TypeNode as Xt, InferSchemaNode as Y, TextNode as Yt, SchemaDialect as Z, NodeKind as Zt, Printer as _, FunctionParameterNode as _t, createDiscriminantNode as a, OutputNode as at, createPrinterFactory as b, ParamsTypeNode as bt, findCircularSchemas as c, HttpMethod as ct, ParentOf as d, ResponseNode as dt, DedupeLookups as et, Visitor as f, StatusCode as ft, walk as g, FunctionParamNode as gt, transform as h, FunctionNodeType as ht, containsCircularRef as i, Node as it, createFunctionParameters as j, ObjectSchemaNode as jt, createFunction as k, IntersectionSchemaNode as kt, isStringType as l, HttpOperationNode as lt, collect as m, ParameterNode as mt, caseParams as n, applyDedupe as nt, createOperationParams as o, InputMeta as ot, VisitorContext as p, ParameterLocation as pt, syncOptionality as q, JSDocNode as qt, collectUsedSchemaNames as r, buildDedupePlan as rt, extractStringsFromNodes as s, InputNode as st, OperationParamsResolver as t, DedupePlan as tt, syncSchemaRef as u, OperationNode as ut, PrinterFactoryOptions as v, FunctionParametersNode as vt, createArrowFunction as w, SourceNode as wt, definePrinter as x, ExportNode as xt, PrinterPartial as y, ParameterGroupNode as yt, createParamsType as z, TimeSchemaNode as zt };
3544
+ //# sourceMappingURL=types-BL7RpQAE.d.ts.map
package/dist/types.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as SchemaDialect, $t as TypeNode, At as DatetimeSchemaNode, Bt as SchemaType, C as UserFileNode, Ct as ParamsTypeNode, Dt as SourceNode, Et as ImportNode, Ft as PrimitiveSchemaType, Gt as PropertyNode, Ht as TimeSchemaNode, It as RefSchemaNode, Jt as ConstNode, Kt as ArrowFunctionNode, Lt as ScalarSchemaType, Mt as IntersectionSchemaNode, Nt as NumberSchemaNode, Ot as ArraySchemaNode, Pt as ObjectSchemaNode, Qt as TextNode, Rt as SchemaNode, S as DistributiveOmit, St as ParameterGroupNode, Tt as FileNode, Ut as UnionSchemaNode, Vt as StringSchemaNode, Wt as UrlSchemaNode, X as ParserOptions, Xt as JSDocNode, Y as InferSchemaNode, Yt as FunctionNode, Z as DispatchRule, Zt as JsxNode, _ as Printer, _t as ParameterNode, bt as FunctionParameterNode, ct as InputNode, d as ParentOf, dt as HttpMethod, en as NodeKind, f as Visitor, ft as HttpOperationNode, gt as ParameterLocation, ht as StatusCode, jt as EnumSchemaNode, kt as DateSchemaNode, lt as InputStreamNode, mt as ResponseNode, nt as DedupeLookups, ot as Node, p as VisitorContext, pt as OperationNode, qt as CodeNode, rt as DedupePlan, st as InputMeta, t as OperationParamsResolver, tt as DedupeCanonical, ut as OutputNode, v as PrinterFactoryOptions, vt as FunctionNodeType, wt as ExportNode, xt as FunctionParametersNode, y as PrinterPartial, yt as FunctionParamNode, zt as SchemaNodeByType } from "./types-BYujEIxF.js";
2
- export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode, DedupeCanonical, DedupeLookups, DedupePlan, DispatchRule, DistributiveOmit, EnumSchemaNode, ExportNode, FileNode, FunctionNode, FunctionNodeType, FunctionParamNode, FunctionParameterNode, FunctionParametersNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, InputStreamNode, IntersectionSchemaNode, JSDocNode, JsxNode, Node, NodeKind, NumberSchemaNode, ObjectSchemaNode, OperationNode, OperationParamsResolver, OutputNode, ParameterGroupNode, ParameterLocation, ParameterNode, ParamsTypeNode, ParentOf, ParserOptions, PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, PropertyNode, RefSchemaNode, ResponseNode, ScalarSchemaType, SchemaDialect, SchemaNode, SchemaNodeByType, SchemaType, SourceNode, StatusCode, StringSchemaNode, TextNode, TimeSchemaNode, TypeNode, UnionSchemaNode, UrlSchemaNode, UserFileNode, Visitor, VisitorContext };
1
+ import { $ as DedupeCanonical, At as NumberSchemaNode, Bt as UnionSchemaNode, C as UserFileNode, Ct as ImportNode, Dt as DatetimeSchemaNode, Et as DateSchemaNode, Ft as SchemaNode, Gt as ConstNode, Ht as PropertyNode, It as SchemaNodeByType, Jt as JsxNode, Kt as FunctionNode, Lt as SchemaType, Mt as PrimitiveSchemaType, Nt as RefSchemaNode, Ot as EnumSchemaNode, Pt as ScalarSchemaType, Rt as StringSchemaNode, S as DistributiveOmit, St as FileNode, Tt as ArraySchemaNode, Ut as ArrowFunctionNode, Vt as UrlSchemaNode, Wt as CodeNode, X as ParserOptions, Xt as TypeNode, Y as InferSchemaNode, Yt as TextNode, Z as SchemaDialect, Zt as NodeKind, _ as Printer, _t as FunctionParameterNode, at as OutputNode, bt as ParamsTypeNode, ct as HttpMethod, d as ParentOf, dt as ResponseNode, et as DedupeLookups, f as Visitor, ft as StatusCode, gt as FunctionParamNode, ht as FunctionNodeType, it as Node, jt as ObjectSchemaNode, kt as IntersectionSchemaNode, lt as HttpOperationNode, mt as ParameterNode, ot as InputMeta, p as VisitorContext, pt as ParameterLocation, qt as JSDocNode, st as InputNode, t as OperationParamsResolver, tt as DedupePlan, ut as OperationNode, v as PrinterFactoryOptions, vt as FunctionParametersNode, wt as SourceNode, xt as ExportNode, y as PrinterPartial, yt as ParameterGroupNode, zt as TimeSchemaNode } from "./types-BL7RpQAE.js";
2
+ export type { ArraySchemaNode, ArrowFunctionNode, CodeNode, ConstNode, DateSchemaNode, DatetimeSchemaNode, DedupeCanonical, DedupeLookups, DedupePlan, DistributiveOmit, EnumSchemaNode, ExportNode, FileNode, FunctionNode, FunctionNodeType, FunctionParamNode, FunctionParameterNode, FunctionParametersNode, HttpMethod, HttpOperationNode, ImportNode, InferSchemaNode, InputMeta, InputNode, IntersectionSchemaNode, JSDocNode, JsxNode, Node, NodeKind, NumberSchemaNode, ObjectSchemaNode, OperationNode, OperationParamsResolver, OutputNode, ParameterGroupNode, ParameterLocation, ParameterNode, ParamsTypeNode, ParentOf, ParserOptions, PrimitiveSchemaType, Printer, PrinterFactoryOptions, PrinterPartial, PropertyNode, RefSchemaNode, ResponseNode, ScalarSchemaType, SchemaDialect, SchemaNode, SchemaNodeByType, SchemaType, SourceNode, StatusCode, StringSchemaNode, TextNode, TimeSchemaNode, TypeNode, UnionSchemaNode, UrlSchemaNode, UserFileNode, Visitor, VisitorContext };
@@ -168,56 +168,31 @@ const INDENT = Array.from({ length: 2 }, () => " ").join("");
168
168
  function toCamelOrPascal(text, pascal) {
169
169
  return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
170
170
  if (word.length > 1 && word === word.toUpperCase()) return word;
171
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
172
- return word.charAt(0).toUpperCase() + word.slice(1);
171
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
173
172
  }).join("").replace(/[^a-zA-Z0-9]/g, "");
174
173
  }
175
174
  /**
176
- * Splits `text` on `.` and applies `transformPart` to each segment.
177
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
178
- * Segments are joined with `/` to form a file path.
179
- *
180
- * Only splits on dots followed by a letter so that version numbers
181
- * embedded in operationIds (e.g. `v2025.0`) are kept intact.
182
- *
183
- * Empty segments are filtered before joining. They arise when the text starts with
184
- * a dot followed immediately by a letter (e.g. `..Schema` splits into `['..', 'Schema']`
185
- * and `'..'` transforms to an empty string). Without this filter the join would produce
186
- * a leading `/`, which `path.resolve` would interpret as an absolute path, allowing
187
- * generated files to escape the configured output directory.
188
- */
189
- function applyToFileParts(text, transformPart) {
190
- const parts = text.split(/\.(?=[a-zA-Z])/);
191
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).filter(Boolean).join("/");
192
- }
193
- /**
194
175
  * Converts `text` to camelCase.
195
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
196
176
  *
197
- * @example
198
- * camelCase('hello-world') // 'helloWorld'
199
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
177
+ * @example Word boundaries
178
+ * `camelCase('hello-world') // 'helloWorld'`
179
+ *
180
+ * @example With a prefix
181
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
200
182
  */
201
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
202
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
203
- prefix,
204
- suffix
205
- } : {}));
183
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
206
184
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
207
185
  }
208
186
  /**
209
187
  * Converts `text` to PascalCase.
210
- * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
211
188
  *
212
- * @example
213
- * pascalCase('hello-world') // 'HelloWorld'
214
- * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
189
+ * @example Word boundaries
190
+ * `pascalCase('hello-world') // 'HelloWorld'`
191
+ *
192
+ * @example With a suffix
193
+ * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
215
194
  */
216
- function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
217
- if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
218
- prefix,
219
- suffix
220
- }) : camelCase(part));
195
+ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
221
196
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
222
197
  }
223
198
  //#endregion
@@ -324,22 +299,6 @@ function isValidVarName(name) {
324
299
  return isIdentifier(name);
325
300
  }
326
301
  /**
327
- * Returns `name` when it is already a valid JavaScript variable name, otherwise prefixes it with `_`
328
- * so the result can be used as an identifier. Useful for sanitizing schema names or operation IDs
329
- * that start with a digit (`409`, `504AccountCancel`) or collide with a reserved word.
330
- *
331
- * @example
332
- * ```ts
333
- * ensureValidVarName('409') // '_409'
334
- * ensureValidVarName('Pet') // 'Pet'
335
- * ensureValidVarName('class') // '_class'
336
- * ```
337
- */
338
- function ensureValidVarName(name) {
339
- if (!name || isValidVarName(name)) return name;
340
- return `_${name}`;
341
- }
342
- /**
343
302
  * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
344
303
  *
345
304
  * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
@@ -371,21 +330,6 @@ function singleQuote(value) {
371
330
  if (value === void 0 || value === null) return "''";
372
331
  return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
373
332
  }
374
- /**
375
- * Strips the file extension from a path or file name.
376
- * Only removes the last `.ext` segment when the dot is not part of a directory name.
377
- *
378
- * @example
379
- * trimExtName('petStore.ts') // 'petStore'
380
- * trimExtName('/src/models/pet.ts') // '/src/models/pet'
381
- * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
382
- * trimExtName('noExtension') // 'noExtension'
383
- */
384
- function trimExtName(text) {
385
- const dotIndex = text.lastIndexOf(".");
386
- if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
387
- return text;
388
- }
389
333
  //#endregion
390
334
  //#region src/utils/index.ts
391
335
  /**
@@ -621,6 +565,6 @@ function findDiscriminator(mapping, ref) {
621
565
  return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
622
566
  }
623
567
  //#endregion
624
- export { visitorDepths as S, isValidVarName as _, enumPropName as a, isScalarPrimitive as b, getNestedAccessor as c, stringify as d, stringifyObject as f, ensureValidVarName as g, trimExtName as h, childName as i, jsStringEscape as l, trimQuotes as m, buildList as n, extractRefName as o, toRegExpString as p, buildObject as r, findDiscriminator as s, buildJSDoc as t, objectKey as u, camelCase as v, schemaTypes as x, httpMethods as y };
568
+ export { httpMethods as _, enumPropName as a, visitorDepths as b, getNestedAccessor as c, stringify as d, stringifyObject as f, camelCase as g, isValidVarName as h, childName as i, jsStringEscape as l, trimQuotes as m, buildList as n, extractRefName as o, toRegExpString as p, buildObject as r, findDiscriminator as s, buildJSDoc as t, objectKey as u, isScalarPrimitive as v, schemaTypes as y };
625
569
 
626
- //# sourceMappingURL=utils-BIcKgbbc.js.map
570
+ //# sourceMappingURL=utils-0p8ZO287.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-0p8ZO287.js","names":[],"sources":["../src/constants.ts","../../../internals/utils/src/casing.ts","../../../internals/utils/src/reserved.ts","../../../internals/utils/src/string.ts","../src/utils/index.ts"],"sourcesContent":["import type { HttpMethod } from './nodes/operation.ts'\nimport type { SchemaType } from './nodes/schema.ts'\n\n/**\n * Traversal depth for AST visitor utilities.\n *\n * - `'shallow'` visits only the immediate node, skipping children.\n * - `'deep'` recursively visits all descendant nodes.\n */\nexport type VisitorDepth = 'shallow' | 'deep'\n\nexport const visitorDepths = {\n shallow: 'shallow',\n deep: 'deep',\n} as const satisfies Record<VisitorDepth, VisitorDepth>\n\n/**\n * Schema type discriminators used by all AST schema nodes.\n *\n * These values serve as stable discriminators across the AST (e.g., `schema.type === schemaTypes.object`).\n * Grouped by category: primitives (`string`, `number`, `boolean`), structural types (`object`, `array`, `union`),\n * and format-specific types (`date`, `uuid`, `email`). Use `isScalarPrimitive()` to check for scalar types.\n */\nexport const schemaTypes = {\n /**\n * Text value.\n */\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 /**\n * Boolean value\n */\n boolean: 'boolean',\n /**\n * Explicit null value.\n */\n null: 'null',\n /**\n * Any value (no type restriction).\n */\n any: 'any',\n /**\n * Unknown value (must be narrowed before usage).\n */\n unknown: 'unknown',\n /**\n * No return value (`void`).\n */\n void: 'void',\n /**\n * Object with named properties.\n */\n object: 'object',\n /**\n * Sequential list of items.\n */\n array: 'array',\n /**\n * Fixed-length list with position-specific items.\n */\n tuple: 'tuple',\n /**\n * \"One of\" multiple schema members.\n */\n union: 'union',\n /**\n * \"All of\" multiple schema members.\n */\n intersection: 'intersection',\n /**\n * Enum schema.\n */\n enum: 'enum',\n /**\n * Reference to another schema.\n */\n ref: 'ref',\n /**\n * Calendar date (for example `2026-03-24`).\n */\n date: 'date',\n /**\n * Date-time value (for example `2026-03-24T09:00:00Z`).\n */\n datetime: 'datetime',\n /**\n * Time-only value (for example `09:00:00`).\n */\n time: 'time',\n /**\n * UUID value.\n */\n uuid: 'uuid',\n /**\n * Email address value.\n */\n email: 'email',\n /**\n * URL value.\n */\n url: 'url',\n /**\n * IPv4 address value.\n */\n ipv4: 'ipv4',\n /**\n * IPv6 address value.\n */\n ipv6: 'ipv6',\n /**\n * Binary/blob value.\n */\n blob: 'blob',\n /**\n * Impossible value (`never`).\n */\n never: 'never',\n} as const satisfies Record<SchemaType, SchemaType>\n\nexport type ScalarPrimitive = 'string' | 'number' | 'integer' | 'bigint' | 'boolean'\n\n/**\n * Scalar primitive schema types used for union simplification and type narrowing.\n *\n * Use `isScalarPrimitive()` to safely check whether a type is a scalar primitive.\n */\nconst SCALAR_PRIMITIVE_TYPES = new Set<ScalarPrimitive>(['string', 'number', 'integer', 'bigint', 'boolean'])\n\n/**\n * Type guard that returns `true` when `type` is a scalar primitive schema type.\n *\n * Use this to check if a schema type can be directly assigned without wrapping (e.g., `string | number | boolean`).\n */\nexport function isScalarPrimitive(type: string): type is ScalarPrimitive {\n return SCALAR_PRIMITIVE_TYPES.has(type as ScalarPrimitive)\n}\n\n/**\n * HTTP method identifiers used by operation nodes.\n *\n * Includes all standard HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE).\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\n/**\n * Default concurrency limit for `walk()` traversal utility.\n *\n * Set to 30 to balance I/O-bound resolver parallelism against event loop pressure and memory usage during large spec traversals.\n * Use `WALK_CONCURRENCY` when calling `walk()` or override for different hardware constraints.\n *\n * @example\n * ```ts\n * import { walk, WALK_CONCURRENCY } from '@kubb/ast'\n *\n * walk(root, { concurrency: WALK_CONCURRENCY, root: () => {} })\n * ```\n */\nexport const WALK_CONCURRENCY = 30\n\n/**\n * Number of spaces in one indentation level when assembling multi-line code as strings.\n * Set to 2, 3, … to change the indent width used by `buildObject`/`buildList`.\n */\nconst INDENT_SIZE = 2\n\n/**\n * One indentation level, derived from {@link INDENT_SIZE}.\n */\nexport const INDENT = Array.from({ length: INDENT_SIZE }, () => ' ').join('')\n","type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes `word` with `_` when it is a reserved JavaScript/Java identifier or starts with a digit.\n *\n * @example\n * ```ts\n * transformReservedWord('class') // '_class'\n * transformReservedWord('42foo') // '_42foo'\n * transformReservedWord('status') // 'status'\n * ```\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return isIdentifier(name)\n}\n\n/**\n * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.\n *\n * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys\n * even though they are not valid variable names, so use this (not {@link isValidVarName}) when\n * deciding whether an object key needs quoting.\n *\n * @example\n * ```ts\n * isIdentifier('name') // true\n * isIdentifier('x-total')// false\n * ```\n */\nexport function isIdentifier(name: string): boolean {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n","/**\n * Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping\n * any backslash or single quote in the content.\n *\n * @example\n * ```ts\n * singleQuote('foo') // \"'foo'\"\n * singleQuote(\"o'clock\") // \"'o\\\\'clock'\"\n * ```\n */\nexport function singleQuote(value: string | number | boolean | undefined | null): string {\n if (value === undefined || value === null) return \"''\"\n const escaped = String(value).replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")\n\n return `'${escaped}'`\n}\n","import { isIdentifier, pascalCase, singleQuote } from '@internals/utils'\nimport { INDENT } from '../constants.ts'\n\nexport { isValidVarName } from '@internals/utils'\n\n/**\n * Strips a single matching pair of `\"...\"`, `'...'`, or `` `...` `` from both ends of `text`.\n * Returns the string unchanged when no balanced quote pair is found.\n *\n * @example\n * ```ts\n * trimQuotes('\"hello\"') // 'hello'\n * trimQuotes('hello') // 'hello'\n * ```\n */\nexport function trimQuotes(text: string): string {\n if (text.length >= 2) {\n const first = text[0]\n const last = text[text.length - 1]\n if ((first === '\"' && last === '\"') || (first === \"'\" && last === \"'\") || (first === '`' && last === '`')) {\n return text.slice(1, -1)\n }\n }\n return text\n}\n\n/**\n * Serializes a primitive value to a single-quoted string literal, stripping any surrounding quote\n * characters first. Escaping comes from `JSON.stringify`, then the quote style switches to single\n * quotes so generated code matches the repo style without a formatter.\n *\n * @example\n * ```ts\n * stringify('hello') // \"'hello'\"\n * stringify('\"hello\"') // \"'hello'\"\n * ```\n */\nexport function stringify(value: string | number | boolean | undefined): string {\n if (value === undefined || value === null) return \"''\"\n const json = JSON.stringify(trimQuotes(value.toString()))\n const inner = json.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/'/g, \"\\\\'\")\n return `'${inner}'`\n}\n\n/**\n * Escapes characters that are not allowed inside JS string literals, covering quotes, backslashes,\n * and the Unicode line terminators U+2028 and U+2029.\n *\n * @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4\n *\n * @example\n * ```ts\n * jsStringEscape('say \"hi\"\\nbye') // 'say \\\\\"hi\\\\\"\\\\nbye'\n * ```\n */\nexport function jsStringEscape(input: unknown): string {\n return `${input}`.replace(/[\"'\\\\\\n\\r\\u2028\\u2029]/g, (character) => {\n switch (character) {\n case '\"':\n case \"'\":\n case '\\\\':\n return `\\\\${character}`\n case '\\n':\n return '\\\\n'\n case '\\r':\n return '\\\\r'\n case '\\u2028':\n return '\\\\u2028'\n case '\\u2029':\n return '\\\\u2029'\n default:\n return ''\n }\n })\n}\n\n/**\n * Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.\n * Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.\n * Pass `null` as the second argument to emit a `/pattern/flags` literal instead.\n *\n * @example\n * ```ts\n * toRegExpString('^(?im)foo') // 'new RegExp(\"^foo\", \"im\")'\n * toRegExpString('^(?im)foo', null) // '/^foo/im'\n * ```\n */\nexport function toRegExpString(text: string, func: string | null = 'RegExp'): string {\n const raw = trimQuotes(text)\n\n const match = raw.match(/^\\^(\\(\\?([igmsuy]+)\\))/i)\n const replacementTarget = match?.[1] ?? ''\n const matchedFlags = match?.[2]\n const cleaned = raw\n .replace(/^\\\\?\\//, '')\n .replace(/\\\\?\\/$/, '')\n .replace(replacementTarget, '')\n\n const { source, flags } = new RegExp(cleaned, matchedFlags)\n\n if (func === null) return `/${source}/${flags}`\n\n return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ''})`\n}\n\n/**\n * Renders a plain object as multi-line `key: value` source for embedding in generated code. Nested\n * objects recurse with fixed indentation, so the result drops straight into an object literal\n * without re-parsing.\n *\n * @example\n * ```ts\n * stringifyObject({ foo: 'bar', nested: { a: 1 } })\n * // 'foo: bar,\\nnested: {\\n a: 1\\n }'\n * ```\n */\nexport function stringifyObject(value: Record<string, unknown>): string {\n const items = Object.entries(value)\n .map(([key, val]) => {\n if (val !== null && typeof val === 'object') {\n return `${key}: {\\n ${stringifyObject(val as Record<string, unknown>)}\\n }`\n }\n return `${key}: ${val}`\n })\n .filter(Boolean)\n return items.join(',\\n')\n}\n\n/**\n * Renders a dotted path or string array as an optional-chaining accessor expression rooted at\n * `accessor`. Returns `null` for an empty path.\n *\n * @example\n * ```ts\n * getNestedAccessor('pagination.next.id', 'lastPage')\n * // \"lastPage?.['pagination']?.['next']?.['id']\"\n * ```\n */\nexport function getNestedAccessor(param: string | Array<string>, accessor: string): string | null {\n const parts = Array.isArray(param) ? param : param.split('.')\n if (parts.length === 0 || (parts.length === 1 && parts[0] === '')) return null\n return `${accessor}?.['${`${parts.join(\"']?.['\")}']`}`\n}\n\n/**\n * Builds a JSDoc comment block from an array of lines, returning `fallback` when there are no\n * comments so callers always get a usable string.\n *\n * @example\n * ```ts\n * buildJSDoc(['@type string', '@example hello'])\n * // '/**\\n * @type string\\n * @example hello\\n *\\/\\n '\n * ```\n */\nexport function buildJSDoc(\n comments: Array<string>,\n options: {\n /**\n * String used to indent each comment line.\n * @default ' * '\n */\n indent?: string\n /**\n * String appended after the closing tag.\n * @default '\\n '\n */\n suffix?: string\n /**\n * Returned as-is when `comments` is empty.\n * @default ' '\n */\n fallback?: string\n } = {},\n): string {\n const { indent = ' * ', suffix = '\\n ', fallback = ' ' } = options\n\n if (comments.length === 0) return fallback\n\n return `/**\\n${comments.map((c) => `${indent}${c}`).join('\\n')}\\n */${suffix}`\n}\n\n/**\n * Indents every non-empty line of `text` by one indent level, leaving blank lines empty.\n */\nfunction indentLines(text: string): string {\n if (!text) return ''\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${INDENT}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Renders an object key, quoting it with single quotes only when it is not a valid identifier.\n * Reserved words and globals (`name`, `class`, …) are valid bare keys and stay unquoted.\n *\n * @example\n * ```ts\n * objectKey('name') // 'name'\n * objectKey('x-total') // \"'x-total'\"\n * ```\n */\nexport function objectKey(name: string): string {\n return isIdentifier(name) ? name : singleQuote(name)\n}\n\n/**\n * Assembles a multi-line object literal from already-rendered `entries`, indenting each entry one\n * level and closing the brace at column zero. Nested objects built the same way indent cumulatively,\n * so callers never re-parse the generated code. A trailing comma is added per entry to match the\n * formatter's multi-line style.\n *\n * @example\n * ```ts\n * buildObject(['id: z.number()', 'name: z.string()'])\n * // '{\\n id: z.number(),\\n name: z.string(),\\n}'\n * ```\n */\nexport function buildObject(entries: Array<string>): string {\n if (entries.length === 0) return '{}'\n const body = entries.map((entry) => `${indentLines(entry)},`).join('\\n')\n\n return `{\\n${body}\\n}`\n}\n\n/**\n * Assembles a bracketed list (array by default) from already-rendered `items`. Keeps everything on\n * one line when no item spans multiple lines, and otherwise puts each item on its own line, indented\n * one level with a trailing comma and the closing bracket at column zero. Use it for `z.union([…])`,\n * `z.array([…])`, and similar member lists so objects inside them nest correctly.\n *\n * @example\n * ```ts\n * buildList(['z.string()', 'z.number()'])\n * // '[z.string(), z.number()]'\n * ```\n */\nexport function buildList(items: Array<string>, brackets: [open: string, close: string] = ['[', ']']): string {\n const [open, close] = brackets\n if (items.length === 0) return `${open}${close}`\n if (!items.some((item) => item.includes('\\n'))) return `${open}${items.join(', ')}${close}`\n const body = items.map((item) => `${indentLines(item)},`).join('\\n')\n\n return `${open}\\n${body}\\n${close}`\n}\n\n/**\n * Returns the last path segment of a reference string.\n *\n * @example\n * ```ts\n * extractRefName('#/components/schemas/Pet') // 'Pet'\n * ```\n */\nexport function extractRefName(ref: string): string {\n return ref.split('/').at(-1) ?? ref\n}\n\n/**\n * Builds a PascalCase child schema name by joining a parent name and property name.\n * Returns `null` when there is no parent to nest under.\n *\n * @example\n * ```ts\n * childName('Order', 'shipping_address') // 'OrderShippingAddress'\n * childName(undefined, 'params') // null\n * ```\n */\nexport function childName(parentName: string | null | undefined, propName: string): string | null {\n return parentName ? pascalCase([parentName, propName].join(' ')) : null\n}\n\n/**\n * Builds a PascalCase enum name from the parent name, property name, and a suffix, skipping any\n * empty parts.\n *\n * @example\n * ```ts\n * enumPropName('Order', 'status', 'enum') // 'OrderStatusEnum'\n * ```\n */\nexport function enumPropName(parentName: string | null | undefined, propName: string, enumSuffix: string): string {\n return pascalCase([parentName, propName, enumSuffix].filter(Boolean).join(' '))\n}\n\n/**\n * Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.\n *\n * @example\n * ```ts\n * findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'\n * ```\n */\nexport function findDiscriminator(mapping: Record<string, string> | undefined, ref: string | undefined): string | null {\n if (!mapping || !ref) return null\n return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null\n}\n"],"mappings":"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"}