@kubb/ast 5.0.0-beta.53 → 5.0.0-beta.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +75 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -26
- package/dist/index.js +74 -106
- package/dist/index.js.map +1 -1
- package/dist/{types-IHUK_alM.d.ts → types-BL7RpQAE.d.ts} +141 -172
- package/dist/types.d.ts +2 -2
- package/dist/{utils-BIcKgbbc.js → utils-0p8ZO287.js} +15 -71
- package/dist/utils-0p8ZO287.js.map +1 -0
- package/dist/{utils-CMRZrT-w.cjs → utils-cdQ6Pzyi.cjs} +14 -82
- package/dist/utils-cdQ6Pzyi.cjs.map +1 -0
- package/dist/utils.cjs +1 -2
- package/dist/utils.d.ts +1 -14
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/src/dedupe.ts +47 -16
- package/src/dialect.ts +23 -28
- package/src/factory.ts +2 -3
- package/src/index.ts +1 -3
- package/src/mocks.ts +1 -1
- package/src/nodes/index.ts +6 -4
- package/src/nodes/{root.ts → input.ts} +16 -39
- package/src/nodes/operation.ts +1 -41
- package/src/nodes/requestBody.ts +42 -0
- package/src/signature.ts +23 -48
- package/src/types.ts +1 -3
- package/src/utils/index.ts +3 -1
- package/dist/utils-BIcKgbbc.js.map +0 -1
- package/dist/utils-CMRZrT-w.cjs.map +0 -1
- package/src/dispatch.ts +0 -53
- package/src/resolvers.ts +0 -31
|
@@ -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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"}
|
|
@@ -193,56 +193,31 @@ const INDENT = Array.from({ length: 2 }, () => " ").join("");
|
|
|
193
193
|
function toCamelOrPascal(text, pascal) {
|
|
194
194
|
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) => {
|
|
195
195
|
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
196
|
-
|
|
197
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
196
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
198
197
|
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
199
198
|
}
|
|
200
199
|
/**
|
|
201
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
202
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
203
|
-
* Segments are joined with `/` to form a file path.
|
|
204
|
-
*
|
|
205
|
-
* Only splits on dots followed by a letter so that version numbers
|
|
206
|
-
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
207
|
-
*
|
|
208
|
-
* Empty segments are filtered before joining. They arise when the text starts with
|
|
209
|
-
* a dot followed immediately by a letter (e.g. `..Schema` splits into `['..', 'Schema']`
|
|
210
|
-
* and `'..'` transforms to an empty string). Without this filter the join would produce
|
|
211
|
-
* a leading `/`, which `path.resolve` would interpret as an absolute path, allowing
|
|
212
|
-
* generated files to escape the configured output directory.
|
|
213
|
-
*/
|
|
214
|
-
function applyToFileParts(text, transformPart) {
|
|
215
|
-
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
216
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).filter(Boolean).join("/");
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
200
|
* Converts `text` to camelCase.
|
|
220
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
221
201
|
*
|
|
222
|
-
* @example
|
|
223
|
-
* camelCase('hello-world')
|
|
224
|
-
*
|
|
202
|
+
* @example Word boundaries
|
|
203
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
204
|
+
*
|
|
205
|
+
* @example With a prefix
|
|
206
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
225
207
|
*/
|
|
226
|
-
function camelCase(text, {
|
|
227
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
228
|
-
prefix,
|
|
229
|
-
suffix
|
|
230
|
-
} : {}));
|
|
208
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
231
209
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
232
210
|
}
|
|
233
211
|
/**
|
|
234
212
|
* Converts `text` to PascalCase.
|
|
235
|
-
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
236
213
|
*
|
|
237
|
-
* @example
|
|
238
|
-
* pascalCase('hello-world')
|
|
239
|
-
*
|
|
214
|
+
* @example Word boundaries
|
|
215
|
+
* `pascalCase('hello-world') // 'HelloWorld'`
|
|
216
|
+
*
|
|
217
|
+
* @example With a suffix
|
|
218
|
+
* `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
|
|
240
219
|
*/
|
|
241
|
-
function pascalCase(text, {
|
|
242
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
243
|
-
prefix,
|
|
244
|
-
suffix
|
|
245
|
-
}) : camelCase(part));
|
|
220
|
+
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
246
221
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
247
222
|
}
|
|
248
223
|
//#endregion
|
|
@@ -349,22 +324,6 @@ function isValidVarName(name) {
|
|
|
349
324
|
return isIdentifier(name);
|
|
350
325
|
}
|
|
351
326
|
/**
|
|
352
|
-
* Returns `name` when it is already a valid JavaScript variable name, otherwise prefixes it with `_`
|
|
353
|
-
* so the result can be used as an identifier. Useful for sanitizing schema names or operation IDs
|
|
354
|
-
* that start with a digit (`409`, `504AccountCancel`) or collide with a reserved word.
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```ts
|
|
358
|
-
* ensureValidVarName('409') // '_409'
|
|
359
|
-
* ensureValidVarName('Pet') // 'Pet'
|
|
360
|
-
* ensureValidVarName('class') // '_class'
|
|
361
|
-
* ```
|
|
362
|
-
*/
|
|
363
|
-
function ensureValidVarName(name) {
|
|
364
|
-
if (!name || isValidVarName(name)) return name;
|
|
365
|
-
return `_${name}`;
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
327
|
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
369
328
|
*
|
|
370
329
|
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
@@ -396,21 +355,6 @@ function singleQuote(value) {
|
|
|
396
355
|
if (value === void 0 || value === null) return "''";
|
|
397
356
|
return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
398
357
|
}
|
|
399
|
-
/**
|
|
400
|
-
* Strips the file extension from a path or file name.
|
|
401
|
-
* Only removes the last `.ext` segment when the dot is not part of a directory name.
|
|
402
|
-
*
|
|
403
|
-
* @example
|
|
404
|
-
* trimExtName('petStore.ts') // 'petStore'
|
|
405
|
-
* trimExtName('/src/models/pet.ts') // '/src/models/pet'
|
|
406
|
-
* trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
|
|
407
|
-
* trimExtName('noExtension') // 'noExtension'
|
|
408
|
-
*/
|
|
409
|
-
function trimExtName(text) {
|
|
410
|
-
const dotIndex = text.lastIndexOf(".");
|
|
411
|
-
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
412
|
-
return text;
|
|
413
|
-
}
|
|
414
358
|
//#endregion
|
|
415
359
|
//#region src/utils/index.ts
|
|
416
360
|
/**
|
|
@@ -688,12 +632,6 @@ Object.defineProperty(exports, "childName", {
|
|
|
688
632
|
return childName;
|
|
689
633
|
}
|
|
690
634
|
});
|
|
691
|
-
Object.defineProperty(exports, "ensureValidVarName", {
|
|
692
|
-
enumerable: true,
|
|
693
|
-
get: function() {
|
|
694
|
-
return ensureValidVarName;
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
635
|
Object.defineProperty(exports, "enumPropName", {
|
|
698
636
|
enumerable: true,
|
|
699
637
|
get: function() {
|
|
@@ -772,12 +710,6 @@ Object.defineProperty(exports, "toRegExpString", {
|
|
|
772
710
|
return toRegExpString;
|
|
773
711
|
}
|
|
774
712
|
});
|
|
775
|
-
Object.defineProperty(exports, "trimExtName", {
|
|
776
|
-
enumerable: true,
|
|
777
|
-
get: function() {
|
|
778
|
-
return trimExtName;
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
713
|
Object.defineProperty(exports, "trimQuotes", {
|
|
782
714
|
enumerable: true,
|
|
783
715
|
get: function() {
|
|
@@ -791,4 +723,4 @@ Object.defineProperty(exports, "visitorDepths", {
|
|
|
791
723
|
}
|
|
792
724
|
});
|
|
793
725
|
|
|
794
|
-
//# sourceMappingURL=utils-
|
|
726
|
+
//# sourceMappingURL=utils-cdQ6Pzyi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-cdQ6Pzyi.cjs","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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"}
|
package/dist/utils.cjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_utils = require("./utils-
|
|
2
|
+
const require_utils = require("./utils-cdQ6Pzyi.cjs");
|
|
3
3
|
exports.buildJSDoc = require_utils.buildJSDoc;
|
|
4
4
|
exports.buildList = require_utils.buildList;
|
|
5
5
|
exports.buildObject = require_utils.buildObject;
|
|
6
6
|
exports.childName = require_utils.childName;
|
|
7
|
-
exports.ensureValidVarName = require_utils.ensureValidVarName;
|
|
8
7
|
exports.enumPropName = require_utils.enumPropName;
|
|
9
8
|
exports.extractRefName = require_utils.extractRefName;
|
|
10
9
|
exports.findDiscriminator = require_utils.findDiscriminator;
|
package/dist/utils.d.ts
CHANGED
|
@@ -12,19 +12,6 @@ import { t as __name } from "./chunk-C0LytTxp.js";
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
declare function isValidVarName(name: string): boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Returns `name` when it is already a valid JavaScript variable name, otherwise prefixes it with `_`
|
|
17
|
-
* so the result can be used as an identifier. Useful for sanitizing schema names or operation IDs
|
|
18
|
-
* that start with a digit (`409`, `504AccountCancel`) or collide with a reserved word.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```ts
|
|
22
|
-
* ensureValidVarName('409') // '_409'
|
|
23
|
-
* ensureValidVarName('Pet') // 'Pet'
|
|
24
|
-
* ensureValidVarName('class') // '_class'
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
declare function ensureValidVarName(name: string): string;
|
|
28
15
|
//#endregion
|
|
29
16
|
//#region src/utils/index.d.ts
|
|
30
17
|
/**
|
|
@@ -201,5 +188,5 @@ declare function enumPropName(parentName: string | null | undefined, propName: s
|
|
|
201
188
|
*/
|
|
202
189
|
declare function findDiscriminator(mapping: Record<string, string> | undefined, ref: string | undefined): string | null;
|
|
203
190
|
//#endregion
|
|
204
|
-
export { buildJSDoc, buildList, buildObject, childName,
|
|
191
|
+
export { buildJSDoc, buildList, buildObject, childName, enumPropName, extractRefName, findDiscriminator, getNestedAccessor, isValidVarName, jsStringEscape, objectKey, stringify, stringifyObject, toRegExpString, trimQuotes };
|
|
205
192
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { buildJSDoc, buildList, buildObject, childName,
|
|
1
|
+
import { a as enumPropName, c as getNestedAccessor, d as stringify, f as stringifyObject, h as isValidVarName, i as childName, l as jsStringEscape, m as trimQuotes, n as buildList, o as extractRefName, p as toRegExpString, r as buildObject, s as findDiscriminator, t as buildJSDoc, u as objectKey } from "./utils-0p8ZO287.js";
|
|
2
|
+
export { buildJSDoc, buildList, buildObject, childName, enumPropName, extractRefName, findDiscriminator, getNestedAccessor, isValidVarName, jsStringEscape, objectKey, stringify, stringifyObject, toRegExpString, trimQuotes };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/ast",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.55",
|
|
4
4
|
"description": "Spec-agnostic AST layer for Kubb. Defines the node tree, visitor pattern, factory functions, and type guards used across all code generation plugins.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ast",
|
package/src/dedupe.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSchema } from './factory.ts'
|
|
2
2
|
import type { Node, OperationNode, SchemaNode } from './nodes/index.ts'
|
|
3
3
|
import { signatureOf } from './signature.ts'
|
|
4
|
+
import { extractRefName } from './utils/index.ts'
|
|
4
5
|
import { collectLazy, transform } from './visitor.ts'
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -28,6 +29,11 @@ export type DedupePlan = {
|
|
|
28
29
|
* Maps a structural signature to the canonical schema that represents it.
|
|
29
30
|
*/
|
|
30
31
|
canonicalBySignature: Map<string, DedupeCanonical>
|
|
32
|
+
/**
|
|
33
|
+
* Maps the name of a top-level schema that duplicates a canonical one to that canonical, so
|
|
34
|
+
* references to the duplicate can be repointed at the first schema with the same content.
|
|
35
|
+
*/
|
|
36
|
+
aliasNames: Map<string, DedupeCanonical>
|
|
31
37
|
/**
|
|
32
38
|
* New top-level schema definitions created for inline shapes that had no existing
|
|
33
39
|
* named component. Nested duplicates inside each definition are already collapsed.
|
|
@@ -35,6 +41,11 @@ export type DedupePlan = {
|
|
|
35
41
|
hoisted: Array<SchemaNode>
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The lookups {@link applyDedupe} needs from a {@link DedupePlan}.
|
|
46
|
+
*/
|
|
47
|
+
export type DedupeLookups = Pick<DedupePlan, 'canonicalBySignature' | 'aliasNames'>
|
|
48
|
+
|
|
38
49
|
/**
|
|
39
50
|
* Options that inject the naming and candidate policy into {@link buildDedupePlan}.
|
|
40
51
|
* The mechanics (grouping, counting, rewriting) live here. The policy lives in the caller.
|
|
@@ -86,25 +97,35 @@ function createRefNode(node: SchemaNode, canonical: DedupeCanonical): SchemaNode
|
|
|
86
97
|
/**
|
|
87
98
|
* Rewrites a node, replacing every candidate sub-schema whose signature has a canonical
|
|
88
99
|
* target with a `ref` to that target. Replacing a node with a `ref` prunes its subtree,
|
|
89
|
-
* so nested duplicates inside a replaced shape are not visited again.
|
|
100
|
+
* so nested duplicates inside a replaced shape are not visited again. A `ref` that points
|
|
101
|
+
* at a duplicate top-level schema (see `aliasNames`) is repointed at the first schema with
|
|
102
|
+
* the same content.
|
|
90
103
|
*
|
|
91
104
|
* Pass `skipRootMatch` when rewriting a canonical definition so its own root is not
|
|
92
105
|
* turned into a reference to itself. Nested duplicates are still collapsed.
|
|
93
106
|
*
|
|
94
107
|
* @example
|
|
95
108
|
* ```ts
|
|
96
|
-
* const next = applyDedupe(operationNode, plan
|
|
109
|
+
* const next = applyDedupe(operationNode, plan)
|
|
97
110
|
* ```
|
|
98
111
|
*/
|
|
99
|
-
export function applyDedupe(node: SchemaNode,
|
|
100
|
-
export function applyDedupe(node: OperationNode,
|
|
101
|
-
export function applyDedupe(node: Node,
|
|
102
|
-
|
|
112
|
+
export function applyDedupe(node: SchemaNode, plan: DedupeLookups, skipRootMatch?: boolean): SchemaNode
|
|
113
|
+
export function applyDedupe(node: OperationNode, plan: DedupeLookups, skipRootMatch?: boolean): OperationNode
|
|
114
|
+
export function applyDedupe(node: Node, plan: DedupeLookups, skipRootMatch = false): Node {
|
|
115
|
+
const { canonicalBySignature, aliasNames } = plan
|
|
116
|
+
if (canonicalBySignature.size === 0 && aliasNames.size === 0) return node
|
|
103
117
|
|
|
104
118
|
const root = node
|
|
105
119
|
|
|
106
120
|
return transform(node, {
|
|
107
121
|
schema(schemaNode) {
|
|
122
|
+
if (schemaNode.type === 'ref') {
|
|
123
|
+
const target = schemaNode.ref ? extractRefName(schemaNode.ref) : schemaNode.name
|
|
124
|
+
const canonical = target ? aliasNames.get(target) : undefined
|
|
125
|
+
|
|
126
|
+
return canonical ? { ...schemaNode, name: canonical.name, ref: canonical.ref } : undefined
|
|
127
|
+
}
|
|
128
|
+
|
|
108
129
|
const signature = signatureOf(schemaNode)
|
|
109
130
|
if (skipRootMatch && schemaNode === root) return undefined
|
|
110
131
|
|
|
@@ -128,9 +149,11 @@ function cleanDefinition(node: SchemaNode, name: string): SchemaNode {
|
|
|
128
149
|
* Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
|
|
129
150
|
*
|
|
130
151
|
* A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
|
|
131
|
-
* is a named top-level schema,
|
|
132
|
-
* and inline copies turn into references to it).
|
|
133
|
-
*
|
|
152
|
+
* is a named top-level schema, the first one becomes the canonical (so other top-level
|
|
153
|
+
* duplicates and inline copies turn into references to it). Every other top-level name with
|
|
154
|
+
* the same content is recorded in `aliasNames`, so refs to it can be repointed at the
|
|
155
|
+
* canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
|
|
156
|
+
* per node with {@link applyDedupe}.
|
|
134
157
|
*
|
|
135
158
|
* @example
|
|
136
159
|
* ```ts
|
|
@@ -149,7 +172,7 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
149
172
|
type Group = {
|
|
150
173
|
count: number
|
|
151
174
|
representative: SchemaNode
|
|
152
|
-
|
|
175
|
+
topLevelNames: Array<string>
|
|
153
176
|
}
|
|
154
177
|
const groups = new Map<string, Group>()
|
|
155
178
|
|
|
@@ -161,9 +184,9 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
161
184
|
const group = groups.get(signature)
|
|
162
185
|
if (group) {
|
|
163
186
|
group.count++
|
|
164
|
-
if (isTopLevel
|
|
187
|
+
if (isTopLevel) group.topLevelNames.push(schemaNode.name!)
|
|
165
188
|
} else {
|
|
166
|
-
groups.set(signature, { count: 1, representative: schemaNode,
|
|
189
|
+
groups.set(signature, { count: 1, representative: schemaNode, topLevelNames: isTopLevel ? [schemaNode.name!] : [] })
|
|
167
190
|
}
|
|
168
191
|
}
|
|
169
192
|
|
|
@@ -175,13 +198,19 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
175
198
|
}
|
|
176
199
|
|
|
177
200
|
const canonicalBySignature = new Map<string, DedupeCanonical>()
|
|
201
|
+
const aliasNames = new Map<string, DedupeCanonical>()
|
|
178
202
|
const pendingHoists: Array<{ name: string; representative: SchemaNode }> = []
|
|
179
203
|
|
|
180
204
|
for (const [signature, group] of groups) {
|
|
181
205
|
if (group.count < minOccurrences) continue
|
|
182
206
|
|
|
183
|
-
|
|
184
|
-
|
|
207
|
+
const [firstName, ...duplicateNames] = group.topLevelNames
|
|
208
|
+
if (firstName) {
|
|
209
|
+
const canonical: DedupeCanonical = { name: firstName, ref: refFor(firstName) }
|
|
210
|
+
canonicalBySignature.set(signature, canonical)
|
|
211
|
+
for (const duplicate of duplicateNames) {
|
|
212
|
+
aliasNames.set(duplicate, canonical)
|
|
213
|
+
}
|
|
185
214
|
continue
|
|
186
215
|
}
|
|
187
216
|
|
|
@@ -194,7 +223,9 @@ export function buildDedupePlan(roots: ReadonlyArray<Node>, options: BuildDedupe
|
|
|
194
223
|
|
|
195
224
|
// Build hoisted definitions only after every canonical name is known, so nested
|
|
196
225
|
// duplicates inside a definition also resolve to refs.
|
|
197
|
-
const hoisted = pendingHoists.map(({ name, representative }) =>
|
|
226
|
+
const hoisted = pendingHoists.map(({ name, representative }) =>
|
|
227
|
+
cleanDefinition(applyDedupe(representative, { canonicalBySignature, aliasNames }, true), name),
|
|
228
|
+
)
|
|
198
229
|
|
|
199
|
-
return { canonicalBySignature, hoisted }
|
|
230
|
+
return { canonicalBySignature, aliasNames, hoisted }
|
|
200
231
|
}
|
package/src/dialect.ts
CHANGED
|
@@ -1,43 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The spec-specific
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* targeting Postgres vs MySQL. Pair it with {@link dispatch}: the rule table picks which converter
|
|
6
|
-
* runs, the dialect answers the spec-specific questions inside it.
|
|
7
|
-
*
|
|
8
|
-
* The guards (`isReference`, `isDiscriminator`) are type predicates, so converters narrow the
|
|
9
|
-
* schema after a check and the type parameters carry the narrowed types through.
|
|
10
|
-
*
|
|
11
|
-
* This is the seam for the JSON Schema family: OpenAPI, AsyncAPI, and plain JSON Schema share
|
|
12
|
-
* `$ref`, `allOf`/`oneOf`, `enum`, and `format` and differ only in these few decisions. A spec on
|
|
13
|
-
* a different type system (GraphQL, with non-null wrappers and named-type references instead of
|
|
14
|
-
* `$ref`) skips `SchemaDialect` and reuses the universal layer directly: the `Adapter` port, the
|
|
15
|
-
* AST factories, and {@link dispatch} with its own rule table.
|
|
16
|
-
*
|
|
17
|
-
* @typeParam TSchema - The adapter's schema object type (e.g. an OpenAPI `SchemaObject`).
|
|
18
|
-
* @typeParam TRef - The narrowed `$ref` pointer type `isReference` proves.
|
|
19
|
-
* @typeParam TDiscriminated - The narrowed discriminated-schema type `isDiscriminator` proves.
|
|
20
|
-
* @typeParam TDocument - The source document `resolveRef` resolves against.
|
|
2
|
+
* The spec-specific questions a schema parser answers while turning a source document into Kubb
|
|
3
|
+
* AST nodes. The rest of the pipeline is generic JSON Schema, so this is the one seam where
|
|
4
|
+
* OpenAPI, AsyncAPI, and plain JSON Schema differ.
|
|
21
5
|
*/
|
|
22
6
|
export type SchemaDialect<TSchema = unknown, TRef = TSchema, TDiscriminated = TSchema, TDocument = unknown> = {
|
|
23
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Identifies the dialect in logs and diagnostics.
|
|
9
|
+
*/
|
|
24
10
|
name: string
|
|
25
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Whether the schema is nullable.
|
|
13
|
+
*/
|
|
26
14
|
isNullable: (schema?: TSchema) => boolean
|
|
27
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Whether the value is a `$ref` pointer.
|
|
17
|
+
*/
|
|
28
18
|
isReference: (value?: unknown) => value is TRef
|
|
29
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Whether the schema carries a discriminator for polymorphism.
|
|
21
|
+
*/
|
|
30
22
|
isDiscriminator: (value?: unknown) => value is TDiscriminated
|
|
31
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Whether the schema is binary data, converted to a `blob` node.
|
|
25
|
+
*/
|
|
32
26
|
isBinary: (schema: TSchema) => boolean
|
|
33
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Resolves a local `$ref` against the document, or nullish when it cannot.
|
|
29
|
+
*/
|
|
34
30
|
resolveRef: <TResolved>(document: TDocument, ref: string) => TResolved | null | undefined
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* inference and gives adapter authors a discoverable anchor.
|
|
34
|
+
* Types a {@link SchemaDialect} for an adapter. Adds no runtime behavior and only pins the
|
|
35
|
+
* dialect's type for inference.
|
|
41
36
|
*
|
|
42
37
|
* @example
|
|
43
38
|
* ```ts
|
package/src/factory.ts
CHANGED
|
@@ -17,7 +17,6 @@ import type {
|
|
|
17
17
|
ImportNode,
|
|
18
18
|
InputMeta,
|
|
19
19
|
InputNode,
|
|
20
|
-
InputStreamNode,
|
|
21
20
|
JsxNode,
|
|
22
21
|
Node,
|
|
23
22
|
ObjectSchemaNode,
|
|
@@ -127,14 +126,14 @@ export function createInput(overrides: Partial<Omit<InputNode, 'kind'>> = {}): I
|
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
/**
|
|
130
|
-
* Creates
|
|
129
|
+
* Creates a streaming `InputNode<true>` from pre-built `AsyncIterable` sources.
|
|
131
130
|
*
|
|
132
131
|
* @example
|
|
133
132
|
* ```ts
|
|
134
133
|
* const node = createStreamInput(schemasIterable, operationsIterable, { title: 'My API' })
|
|
135
134
|
* ```
|
|
136
135
|
*/
|
|
137
|
-
export function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta):
|
|
136
|
+
export function createStreamInput(schemas: AsyncIterable<SchemaNode>, operations: AsyncIterable<OperationNode>, meta?: InputMeta): InputNode<true> {
|
|
138
137
|
return { kind: 'Input', schemas, operations, meta }
|
|
139
138
|
}
|
|
140
139
|
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { httpMethods, schemaTypes } from './constants.ts'
|
|
2
2
|
export { applyDedupe, buildDedupePlan } from './dedupe.ts'
|
|
3
3
|
export { defineSchemaDialect } from './dialect.ts'
|
|
4
|
-
export { dispatch } from './dispatch.ts'
|
|
5
4
|
export {
|
|
6
5
|
createArrowFunction,
|
|
7
6
|
createBreak,
|
|
@@ -31,8 +30,7 @@ export {
|
|
|
31
30
|
} from './factory.ts'
|
|
32
31
|
export { isHttpOperationNode, isInputNode, isOperationNode, isOutputNode, isSchemaNode, narrowSchema } from './guards.ts'
|
|
33
32
|
export { createPrinterFactory, definePrinter } from './printer.ts'
|
|
34
|
-
export {
|
|
35
|
-
export { schemaSignature } from './signature.ts'
|
|
33
|
+
export { signatureOf } from './signature.ts'
|
|
36
34
|
export { mergeAdjacentObjectsLazy, setDiscriminatorEnum, setEnumName, simplifyUnion } from './transformers.ts'
|
|
37
35
|
export type * from './types.ts'
|
|
38
36
|
export {
|
package/src/mocks.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createInput, createOperation, createParameter, createProperty, createResponse, createSchema } from './factory.ts'
|
|
2
|
-
import type { InputNode } from './nodes/
|
|
2
|
+
import type { InputNode } from './nodes/input.ts'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Builds a minimal sample AST with one `Pet` schema and one `getPetById` operation.
|
package/src/nodes/index.ts
CHANGED
|
@@ -2,12 +2,13 @@ import type { ArrowFunctionNode, ConstNode, FunctionNode, TypeNode } from './cod
|
|
|
2
2
|
import type { ContentNode } from './content.ts'
|
|
3
3
|
import type { ExportNode, FileNode, ImportNode, SourceNode } from './file.ts'
|
|
4
4
|
import type { FunctionParamNode, ParamsTypeNode } from './function.ts'
|
|
5
|
-
import type {
|
|
5
|
+
import type { InputNode } from './input.ts'
|
|
6
|
+
import type { OperationNode } from './operation.ts'
|
|
6
7
|
import type { OutputNode } from './output.ts'
|
|
7
8
|
import type { ParameterNode } from './parameter.ts'
|
|
8
9
|
import type { PropertyNode } from './property.ts'
|
|
10
|
+
import type { RequestBodyNode } from './requestBody.ts'
|
|
9
11
|
import type { ResponseNode } from './response.ts'
|
|
10
|
-
import type { InputNode } from './root.ts'
|
|
11
12
|
import type { SchemaNode } from './schema.ts'
|
|
12
13
|
|
|
13
14
|
export type { NodeKind } from './base.ts'
|
|
@@ -16,12 +17,13 @@ export type { ContentNode } from './content.ts'
|
|
|
16
17
|
export type { ExportNode, FileNode, ImportNode, SourceNode } from './file.ts'
|
|
17
18
|
export type { FunctionNodeType, FunctionParameterNode, FunctionParametersNode, FunctionParamNode, ParameterGroupNode, ParamsTypeNode } from './function.ts'
|
|
18
19
|
export type { StatusCode } from './http.ts'
|
|
19
|
-
export type {
|
|
20
|
+
export type { InputMeta, InputNode } from './input.ts'
|
|
21
|
+
export type { GenericOperationNode, HttpMethod, HttpOperationNode, OperationNode } from './operation.ts'
|
|
20
22
|
export type { OutputNode } from './output.ts'
|
|
21
23
|
export type { ParameterLocation, ParameterNode } from './parameter.ts'
|
|
22
24
|
export type { PropertyNode } from './property.ts'
|
|
25
|
+
export type { RequestBodyNode } from './requestBody.ts'
|
|
23
26
|
export type { ResponseNode } from './response.ts'
|
|
24
|
-
export type { InputMeta, InputNode, InputStreamNode } from './root.ts'
|
|
25
27
|
export type {
|
|
26
28
|
ArraySchemaNode,
|
|
27
29
|
DateSchemaNode,
|