UNPKG

@kubb/plugin-ts

Version:

TypeScript code generation plugin for Kubb, transforming OpenAPI schemas into TypeScript interfaces, types, and utility functions.

850 lines (849 loc) 37 kB
//#region \0rolldown/runtime.js var __create = Object.create; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let _kubb_plugin_oas = require("@kubb/plugin-oas"); let _kubb_fabric_core_parsers_typescript = require("@kubb/fabric-core/parsers/typescript"); let _kubb_react_fabric = require("@kubb/react-fabric"); let typescript = require("typescript"); typescript = __toESM(typescript); let remeda = require("remeda"); let _kubb_react_fabric_jsx_runtime = require("@kubb/react-fabric/jsx-runtime"); //#region ../../internals/utils/src/casing.ts /** * Shared implementation for camelCase and PascalCase conversion. * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons) * and capitalizes each word according to `pascal`. * * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are. */ function toCamelOrPascal(text, pascal) { 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) => { if (word.length > 1 && word === word.toUpperCase()) return word; if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1); return word.charAt(0).toUpperCase() + word.slice(1); }).join("").replace(/[^a-zA-Z0-9]/g, ""); } /** * Splits `text` on `.` and applies `transformPart` to each segment. * The last segment receives `isLast = true`, all earlier segments receive `false`. * Segments are joined with `/` to form a file path. */ function applyToFileParts(text, transformPart) { const parts = text.split("."); return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/"); } /** * Converts `text` to camelCase. * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`. * * @example * camelCase('hello-world') // 'helloWorld' * camelCase('pet.petId', { isFile: true }) // 'pet/petId' */ function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) { if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? { prefix, suffix } : {})); return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false); } /** * Converts `text` to PascalCase. * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased. * * @example * pascalCase('hello-world') // 'HelloWorld' * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId' */ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) { if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, { prefix, suffix }) : camelCase(part)); return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true); } /** * Converts `text` to snake_case. * * @example * snakeCase('helloWorld') // 'hello_world' * snakeCase('Hello-World') // 'hello_world' */ function snakeCase(text, { prefix = "", suffix = "" } = {}) { return `${prefix} ${text} ${suffix}`.trim().replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s\-.]+/g, "_").replace(/[^a-zA-Z0-9_]/g, "").toLowerCase().split("_").filter(Boolean).join("_"); } /** * Converts `text` to SCREAMING_SNAKE_CASE. * * @example * screamingSnakeCase('helloWorld') // 'HELLO_WORLD' */ function screamingSnakeCase(text, { prefix = "", suffix = "" } = {}) { return snakeCase(text, { prefix, suffix }).toUpperCase(); } //#endregion //#region ../../internals/utils/src/string.ts /** * Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`. * Returns the string unchanged when no balanced quote pair is found. * * @example * trimQuotes('"hello"') // 'hello' * trimQuotes('hello') // 'hello' */ function trimQuotes(text) { if (text.length >= 2) { const first = text[0]; const last = text[text.length - 1]; if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1); } return text; } /** * Escapes characters that are not allowed inside JS string literals. * Handles quotes, backslashes, and Unicode line terminators (U+2028 / U+2029). * * @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4 */ function jsStringEscape(input) { return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => { switch (character) { case "\"": case "'": case "\\": return `\\${character}`; case "\n": return "\\n"; case "\r": return "\\r"; case "\u2028": return "\\u2028"; case "\u2029": return "\\u2029"; default: return ""; } }); } //#endregion //#region src/factory.ts const { SyntaxKind, factory } = typescript.default; const modifiers = { async: factory.createModifier(typescript.default.SyntaxKind.AsyncKeyword), export: factory.createModifier(typescript.default.SyntaxKind.ExportKeyword), const: factory.createModifier(typescript.default.SyntaxKind.ConstKeyword), static: factory.createModifier(typescript.default.SyntaxKind.StaticKeyword) }; const syntaxKind = { union: SyntaxKind.UnionType }; function getUnknownType(unknownType) { if (unknownType === "any") return keywordTypeNodes.any; if (unknownType === "void") return keywordTypeNodes.void; return keywordTypeNodes.unknown; } function isValidIdentifier(str) { if (!str.length || str.trim() !== str) return false; const node = typescript.default.parseIsolatedEntityName(str, typescript.default.ScriptTarget.Latest); return !!node && node.kind === typescript.default.SyntaxKind.Identifier && typescript.default.identifierToKeywordKind(node.kind) === void 0; } function propertyName(name) { if (typeof name === "string") return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name); return name; } const questionToken = factory.createToken(typescript.default.SyntaxKind.QuestionToken); function createQuestionToken(token) { if (!token) return; if (token === true) return questionToken; return token; } function createIntersectionDeclaration({ nodes, withParentheses }) { if (!nodes.length) return null; if (nodes.length === 1) return nodes[0] || null; const node = factory.createIntersectionTypeNode(nodes); if (withParentheses) return factory.createParenthesizedType(node); return node; } function createArrayDeclaration({ nodes, arrayType = "array" }) { if (!nodes.length) return factory.createTupleTypeNode([]); if (nodes.length === 1) { const node = nodes[0]; if (!node) return null; if (arrayType === "generic") return factory.createTypeReferenceNode(factory.createIdentifier("Array"), [node]); return factory.createArrayTypeNode(node); } const unionType = factory.createUnionTypeNode(nodes); if (arrayType === "generic") return factory.createTypeReferenceNode(factory.createIdentifier("Array"), [unionType]); return factory.createArrayTypeNode(factory.createParenthesizedType(unionType)); } /** * Minimum nodes length of 2 * @example `string | number` */ function createUnionDeclaration({ nodes, withParentheses }) { if (!nodes.length) return keywordTypeNodes.any; if (nodes.length === 1) return nodes[0]; const node = factory.createUnionTypeNode(nodes); if (withParentheses) return factory.createParenthesizedType(node); return node; } function createPropertySignature({ readOnly, modifiers = [], name, questionToken, type }) { return factory.createPropertySignature([...modifiers, readOnly ? factory.createToken(typescript.default.SyntaxKind.ReadonlyKeyword) : void 0].filter(Boolean), propertyName(name), createQuestionToken(questionToken), type); } function createParameterSignature(name, { modifiers, dotDotDotToken, questionToken, type, initializer }) { return factory.createParameterDeclaration(modifiers, dotDotDotToken, name, createQuestionToken(questionToken), type, initializer); } /** * @link https://github.com/microsoft/TypeScript/issues/44151 */ function appendJSDocToNode({ node, comments }) { const filteredComments = comments.filter(Boolean); if (!filteredComments.length) return node; const text = filteredComments.reduce((acc = "", comment = "") => { return `${acc}\n * ${comment.replaceAll("*/", "*\\/")}`; }, "*"); return typescript.default.addSyntheticLeadingComment(node, typescript.default.SyntaxKind.MultiLineCommentTrivia, `${text || "*"}\n`, true); } function createIndexSignature(type, { modifiers, indexName = "key", indexType = factory.createKeywordTypeNode(typescript.default.SyntaxKind.StringKeyword) } = {}) { return factory.createIndexSignature(modifiers, [createParameterSignature(indexName, { type: indexType })], type); } function createTypeAliasDeclaration({ modifiers, name, typeParameters, type }) { return factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type); } function createInterfaceDeclaration({ modifiers, name, typeParameters, members }) { return factory.createInterfaceDeclaration(modifiers, name, typeParameters, void 0, members); } function createTypeDeclaration({ syntax, isExportable, comments, name, type }) { if (syntax === "interface" && "members" in type) return appendJSDocToNode({ node: createInterfaceDeclaration({ members: type.members, modifiers: isExportable ? [modifiers.export] : [], name, typeParameters: void 0 }), comments }); return appendJSDocToNode({ node: createTypeAliasDeclaration({ type, modifiers: isExportable ? [modifiers.export] : [], name, typeParameters: void 0 }), comments }); } /** * Apply casing transformation to enum keys */ function applyEnumKeyCasing(key, casing = "none") { if (casing === "none") return key; if (casing === "screamingSnakeCase") return screamingSnakeCase(key); if (casing === "snakeCase") return snakeCase(key); if (casing === "pascalCase") return pascalCase(key); if (casing === "camelCase") return camelCase(key); return key; } function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCasing = "none" }) { if (type === "literal" || type === "inlineLiteral") return [void 0, factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createUnionTypeNode(enums.map(([_key, value]) => { if ((0, remeda.isNumber)(value)) { if (value < 0) return factory.createLiteralTypeNode(factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)))); return factory.createLiteralTypeNode(factory.createNumericLiteral(value?.toString())); } if (typeof value === "boolean") return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse()); if (value) return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString())); }).filter(Boolean)))]; if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(typescript.default.SyntaxKind.ConstKeyword) : void 0].filter(Boolean), factory.createIdentifier(typeName), enums.map(([key, value]) => { let initializer = factory.createStringLiteral(value?.toString()); if (Number.parseInt(value.toString(), 10) === value && (0, remeda.isNumber)(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))); else initializer = factory.createNumericLiteral(value); if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse(); if ((0, remeda.isNumber)(Number.parseInt(key.toString(), 10))) { const casingKey = applyEnumKeyCasing(`${typeName}_${key}`, enumKeyCasing); return factory.createEnumMember(propertyName(casingKey), initializer); } if (key) { const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing); return factory.createEnumMember(propertyName(casingKey), initializer); } }).filter(Boolean))]; const identifierName = name; if (enums.length === 0) return [void 0, factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createKeywordTypeNode(typescript.default.SyntaxKind.NeverKeyword))]; return [factory.createVariableStatement([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier(identifierName), void 0, void 0, factory.createAsExpression(factory.createObjectLiteralExpression(enums.map(([key, value]) => { let initializer = factory.createStringLiteral(value?.toString()); if ((0, remeda.isNumber)(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))); else initializer = factory.createNumericLiteral(value); if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse(); if (key) { const casingKey = applyEnumKeyCasing(key.toString(), enumKeyCasing); return factory.createPropertyAssignment(propertyName(casingKey), initializer); } }).filter(Boolean), true), factory.createTypeReferenceNode(factory.createIdentifier("const"), void 0)))], typescript.default.NodeFlags.Const)), factory.createTypeAliasDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword)], factory.createIdentifier(typeName), void 0, factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0)), factory.createTypeOperatorNode(typescript.default.SyntaxKind.KeyOfKeyword, factory.createTypeQueryNode(factory.createIdentifier(identifierName), void 0))))]; } function createOmitDeclaration({ keys, type, nonNullable }) { const node = nonNullable ? factory.createTypeReferenceNode(factory.createIdentifier("NonNullable"), [type]) : type; if (Array.isArray(keys)) return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createUnionTypeNode(keys.map((key) => { return factory.createLiteralTypeNode(factory.createStringLiteral(key)); }))]); return factory.createTypeReferenceNode(factory.createIdentifier("Omit"), [node, factory.createLiteralTypeNode(factory.createStringLiteral(keys))]); } const keywordTypeNodes = { any: factory.createKeywordTypeNode(typescript.default.SyntaxKind.AnyKeyword), unknown: factory.createKeywordTypeNode(typescript.default.SyntaxKind.UnknownKeyword), void: factory.createKeywordTypeNode(typescript.default.SyntaxKind.VoidKeyword), number: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NumberKeyword), integer: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NumberKeyword), bigint: factory.createKeywordTypeNode(typescript.default.SyntaxKind.BigIntKeyword), object: factory.createKeywordTypeNode(typescript.default.SyntaxKind.ObjectKeyword), string: factory.createKeywordTypeNode(typescript.default.SyntaxKind.StringKeyword), boolean: factory.createKeywordTypeNode(typescript.default.SyntaxKind.BooleanKeyword), undefined: factory.createKeywordTypeNode(typescript.default.SyntaxKind.UndefinedKeyword), null: factory.createLiteralTypeNode(factory.createToken(typescript.default.SyntaxKind.NullKeyword)), never: factory.createKeywordTypeNode(typescript.default.SyntaxKind.NeverKeyword) }; /** * Converts a path like '/pet/{petId}/uploadImage' to a template literal type * like `/pet/${string}/uploadImage` */ function createUrlTemplateType(path) { if (!path.includes("{")) return factory.createLiteralTypeNode(factory.createStringLiteral(path)); const segments = path.split(/(\{[^}]+\})/); const parts = []; const parameterIndices = []; segments.forEach((segment) => { if (segment.startsWith("{") && segment.endsWith("}")) { parameterIndices.push(parts.length); parts.push(segment); } else if (segment) parts.push(segment); }); const head = typescript.default.factory.createTemplateHead(parts[0] || ""); const templateSpans = []; parameterIndices.forEach((paramIndex, i) => { const isLast = i === parameterIndices.length - 1; const nextPart = parts[paramIndex + 1] || ""; const literal = isLast ? typescript.default.factory.createTemplateTail(nextPart) : typescript.default.factory.createTemplateMiddle(nextPart); templateSpans.push(typescript.default.factory.createTemplateLiteralTypeSpan(keywordTypeNodes.string, literal)); }); return typescript.default.factory.createTemplateLiteralType(head, templateSpans); } const createTypeLiteralNode = factory.createTypeLiteralNode; const createTypeReferenceNode = factory.createTypeReferenceNode; const createNumericLiteral = factory.createNumericLiteral; const createStringLiteral = factory.createStringLiteral; const createArrayTypeNode = factory.createArrayTypeNode; factory.createParenthesizedType; const createLiteralTypeNode = factory.createLiteralTypeNode; factory.createNull; const createIdentifier = factory.createIdentifier; const createOptionalTypeNode = factory.createOptionalTypeNode; const createTupleTypeNode = factory.createTupleTypeNode; const createRestTypeNode = factory.createRestTypeNode; const createTrue = factory.createTrue; const createFalse = factory.createFalse; const createIndexedAccessTypeNode = factory.createIndexedAccessTypeNode; const createTypeOperatorNode = factory.createTypeOperatorNode; factory.createPrefixUnaryExpression; //#endregion //#region src/parser.ts const typeKeywordMapper = { any: () => keywordTypeNodes.any, unknown: () => keywordTypeNodes.unknown, void: () => keywordTypeNodes.void, number: () => keywordTypeNodes.number, integer: () => keywordTypeNodes.number, bigint: () => keywordTypeNodes.bigint, object: (nodes) => { if (!nodes || !nodes.length) return keywordTypeNodes.object; return createTypeLiteralNode(nodes); }, string: () => keywordTypeNodes.string, boolean: () => keywordTypeNodes.boolean, undefined: () => keywordTypeNodes.undefined, nullable: void 0, null: () => keywordTypeNodes.null, nullish: void 0, array: (nodes, arrayType) => { if (!nodes) return; return createArrayDeclaration({ nodes, arrayType }); }, tuple: (nodes, rest, min, max) => { if (!nodes) return; if (max) { nodes = nodes.slice(0, max); if (nodes.length < max && rest) nodes = [...nodes, ...Array(max - nodes.length).fill(rest)]; } if (min) nodes = nodes.map((node, index) => index >= min ? createOptionalTypeNode(node) : node); if (typeof max === "undefined" && rest) nodes.push(createRestTypeNode(createArrayTypeNode(rest))); return createTupleTypeNode(nodes); }, enum: (name) => { if (!name) return; return createTypeReferenceNode(name, void 0); }, union: (nodes) => { if (!nodes) return; return createUnionDeclaration({ withParentheses: true, nodes }); }, const: (name, format) => { if (name === null || name === void 0 || name === "") return; if (format === "boolean") { if (name === true) return createLiteralTypeNode(createTrue()); return createLiteralTypeNode(createFalse()); } if (format === "number" && typeof name === "number") return createLiteralTypeNode(createNumericLiteral(name)); return createLiteralTypeNode(createStringLiteral(name.toString())); }, datetime: () => keywordTypeNodes.string, date: (type = "string") => type === "string" ? keywordTypeNodes.string : createTypeReferenceNode(createIdentifier("Date")), time: (type = "string") => type === "string" ? keywordTypeNodes.string : createTypeReferenceNode(createIdentifier("Date")), uuid: () => keywordTypeNodes.string, url: () => keywordTypeNodes.string, default: void 0, and: (nodes) => { if (!nodes) return; return createIntersectionDeclaration({ withParentheses: true, nodes }); }, describe: void 0, min: void 0, max: void 0, optional: void 0, matches: () => keywordTypeNodes.string, email: () => keywordTypeNodes.string, firstName: void 0, lastName: void 0, password: void 0, phone: void 0, readOnly: void 0, writeOnly: void 0, ref: (propertyName) => { if (!propertyName) return; return createTypeReferenceNode(propertyName, void 0); }, blob: () => createTypeReferenceNode("Blob", []), deprecated: void 0, example: void 0, schema: void 0, catchall: void 0, name: void 0, interface: void 0, exclusiveMaximum: void 0, exclusiveMinimum: void 0 }; /** * Recursively parses a schema tree node into a corresponding TypeScript AST node. * * Maps OpenAPI schema keywords to TypeScript AST nodes using the `typeKeywordMapper`, handling complex types such as unions, intersections, arrays, tuples (with optional/rest elements and length constraints), enums, constants, references, and objects with property modifiers and documentation annotations. * * @param current - The schema node to parse. * @param siblings - Sibling schema nodes, used for context in certain mappings. * @param name - The name of the schema or property being parsed. * @param options - Parsing options controlling output style, property handling, and custom mappers. * @returns The generated TypeScript AST node, or `undefined` if the schema keyword is not mapped. */ const parse = (0, _kubb_plugin_oas.createParser)({ mapper: typeKeywordMapper, handlers: { union(tree, options) { const { current, schema, name } = tree; return typeKeywordMapper.union(current.args.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean)); }, and(tree, options) { const { current, schema, name } = tree; return typeKeywordMapper.and(current.args.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean)); }, array(tree, options) { const { current, schema, name } = tree; return typeKeywordMapper.array(current.args.items.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean), options.arrayType); }, enum(tree, options) { const { current } = tree; if (options.enumType === "inlineLiteral") { const enumValues = current.args.items.map((item) => item.value).filter((value) => value !== void 0 && value !== null).map((value) => { const format = typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string"; return typeKeywordMapper.const(value, format); }).filter(Boolean); return typeKeywordMapper.union(enumValues); } const enumTypeSuffix = options.enumTypeSuffix ?? "Key"; return typeKeywordMapper.enum(["asConst", "asPascalConst"].includes(options.enumType) ? `${current.args.typeName}${enumTypeSuffix}` : current.args.typeName); }, ref(tree, _options) { const { current } = tree; return typeKeywordMapper.ref(current.args.name); }, blob() { return typeKeywordMapper.blob(); }, tuple(tree, options) { const { current, schema, name } = tree; return typeKeywordMapper.tuple(current.args.items.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean), current.args.rest && (this.parse({ schema, parent: current, name, current: current.args.rest, siblings: [] }, options) ?? void 0), current.args.min, current.args.max); }, const(tree, _options) { const { current } = tree; return typeKeywordMapper.const(current.args.name, current.args.format); }, object(tree, options) { const { current, schema, name } = tree; const properties = Object.entries(current.args?.properties || {}).filter((item) => { const schemas = item[1]; return schemas && typeof schemas.map === "function"; }).map(([name, schemas]) => { const mappedName = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.name)?.args || name; if (options.mapper && Object.hasOwn(options.mapper, mappedName)) return options.mapper[mappedName]; const isNullish = schemas.some((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.nullish); const isNullable = schemas.some((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.nullable); const isOptional = schemas.some((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.optional); const isReadonly = schemas.some((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.readOnly); const describeSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.describe); const deprecatedSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.deprecated); const defaultSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.default); const exampleSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.example); const schemaSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.schema); const minSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.min); const maxSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.max); const matchesSchema = schemas.find((schema) => schema.keyword === _kubb_plugin_oas.schemaKeywords.matches); let type = schemas.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: schemas }, options)).filter(Boolean)[0]; if (isNullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] }); if (isNullish && ["undefined", "questionTokenAndUndefined"].includes(options.optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] }); if (isOptional && ["undefined", "questionTokenAndUndefined"].includes(options.optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] }); return appendJSDocToNode({ node: createPropertySignature({ questionToken: isOptional || isNullish ? ["questionToken", "questionTokenAndUndefined"].includes(options.optionalType) : false, name: mappedName, type, readOnly: isReadonly }), comments: [ describeSchema ? `@description ${jsStringEscape(describeSchema.args)}` : void 0, deprecatedSchema ? "@deprecated" : void 0, minSchema ? `@minLength ${minSchema.args}` : void 0, maxSchema ? `@maxLength ${maxSchema.args}` : void 0, matchesSchema ? `@pattern ${matchesSchema.args}` : void 0, defaultSchema ? `@default ${defaultSchema.args}` : void 0, exampleSchema ? `@example ${exampleSchema.args}` : void 0, schemaSchema?.args?.type || schemaSchema?.args?.format ? [`@type ${schemaSchema?.args?.type || "unknown"}${!isOptional ? "" : " | undefined"}`, schemaSchema?.args?.format].filter(Boolean).join(", ") : void 0 ].filter(Boolean) }); }); let additionalProperties; if (current.args?.additionalProperties?.length) { let additionalPropertiesType = current.args.additionalProperties.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean).at(0); if (current.args?.additionalProperties.some((schema) => (0, _kubb_plugin_oas.isKeyword)(schema, _kubb_plugin_oas.schemaKeywords.nullable))) additionalPropertiesType = createUnionDeclaration({ nodes: [additionalPropertiesType, keywordTypeNodes.null] }); additionalProperties = createIndexSignature(properties.length > 0 ? keywordTypeNodes.unknown : additionalPropertiesType); } let patternProperties; if (current.args?.patternProperties) { const allPatternSchemas = Object.values(current.args.patternProperties).flat(); if (allPatternSchemas.length > 0) { patternProperties = allPatternSchemas.map((it) => this.parse({ schema, parent: current, name, current: it, siblings: [] }, options)).filter(Boolean).at(0); if (allPatternSchemas.some((schema) => (0, _kubb_plugin_oas.isKeyword)(schema, _kubb_plugin_oas.schemaKeywords.nullable))) patternProperties = createUnionDeclaration({ nodes: [patternProperties, keywordTypeNodes.null] }); patternProperties = createIndexSignature(patternProperties); } } return typeKeywordMapper.object([ ...properties, additionalProperties, patternProperties ].filter(Boolean)); }, datetime() { return typeKeywordMapper.datetime(); }, date(tree) { const { current } = tree; return typeKeywordMapper.date(current.args.type); }, time(tree) { const { current } = tree; return typeKeywordMapper.time(current.args.type); } } }); //#endregion //#region src/components/Type.tsx function Type({ name, typedName, tree, keysToOmit, schema, optionalType, arrayType, syntaxType, enumType, enumTypeSuffix, enumKeyCasing, mapper, description }) { const typeNodes = []; if (!tree.length) return ""; const schemaFromTree = tree.find((item) => item.keyword === _kubb_plugin_oas.schemaKeywords.schema); const enumSchemas = _kubb_plugin_oas.SchemaGenerator.deepSearch(tree, _kubb_plugin_oas.schemaKeywords.enum); let type = tree.map((current, _index, siblings) => parse({ name, schema, parent: void 0, current, siblings }, { optionalType, arrayType, enumType, enumTypeSuffix, mapper })).filter(Boolean).at(0) || typeKeywordMapper.undefined(); if (["asConst", "asPascalConst"].includes(enumType) && enumSchemas.length > 0) { const isDirectEnum = schema.type === "array" && schema.items !== void 0; const isEnumOnly = "enum" in schema && schema.enum; if (isDirectEnum || isEnumOnly) { type = createTypeReferenceNode(`${enumSchemas[0].args.typeName}${enumTypeSuffix}`); if (schema.type === "array") if (arrayType === "generic") type = createTypeReferenceNode(createIdentifier("Array"), [type]); else type = createArrayTypeNode(type); } } if (schemaFromTree && (0, _kubb_plugin_oas.isKeyword)(schemaFromTree, _kubb_plugin_oas.schemaKeywords.schema)) { const isNullish = tree.some((item) => item.keyword === _kubb_plugin_oas.schemaKeywords.nullish); const isNullable = tree.some((item) => item.keyword === _kubb_plugin_oas.schemaKeywords.nullable); const isOptional = tree.some((item) => item.keyword === _kubb_plugin_oas.schemaKeywords.optional); if (isNullable) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.null] }); if (isNullish && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] }); if (isOptional && ["undefined", "questionTokenAndUndefined"].includes(optionalType)) type = createUnionDeclaration({ nodes: [type, keywordTypeNodes.undefined] }); } const useTypeGeneration = syntaxType === "type" || [syntaxKind.union].includes(type.kind) || !!keysToOmit?.length; typeNodes.push(createTypeDeclaration({ name, isExportable: true, type: keysToOmit?.length ? createOmitDeclaration({ keys: keysToOmit, type, nonNullable: true }) : type, syntax: useTypeGeneration ? "type" : "interface", comments: [ schema.title ? `${jsStringEscape(schema.title)}` : void 0, description ? `@description ${jsStringEscape(description)}` : void 0, schema.deprecated ? "@deprecated" : void 0, schema.minLength ? `@minLength ${schema.minLength}` : void 0, schema.maxLength ? `@maxLength ${schema.maxLength}` : void 0, schema.pattern ? `@pattern ${schema.pattern}` : void 0, schema.default ? `@default ${schema.default}` : void 0, schema.example ? `@example ${schema.example}` : void 0 ] })); const enums = [...new Set(enumSchemas)].map((enumSchema) => { const name = enumType === "asPascalConst" ? pascalCase(enumSchema.args.name) : camelCase(enumSchema.args.name); const typeName = ["asConst", "asPascalConst"].includes(enumType) ? `${enumSchema.args.typeName}${enumTypeSuffix}` : enumSchema.args.typeName; const [nameNode, typeNode] = createEnumDeclaration({ name, typeName, enums: enumSchema.args.items.map((item) => item.value === void 0 ? void 0 : [trimQuotes(item.name?.toString()), item.value]).filter(Boolean), type: enumType, enumKeyCasing }); return { nameNode, typeNode, name, typeName }; }); const shouldExportEnums = enumType !== "inlineLiteral"; const shouldExportType = enumType === "inlineLiteral" || enums.every((item) => item.typeName !== name); return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [shouldExportEnums && enums.map(({ name, nameNode, typeName, typeNode }) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [nameNode && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, { name, isExportable: true, isIndexable: true, isTypeOnly: false, children: (0, _kubb_fabric_core_parsers_typescript.safePrint)(nameNode) }), /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, { name: typeName, isIndexable: true, isExportable: [ "enum", "asConst", "asPascalConst", "constEnum", "literal", void 0 ].includes(enumType), isTypeOnly: [ "asConst", "asPascalConst", "literal", void 0 ].includes(enumType), children: (0, _kubb_fabric_core_parsers_typescript.safePrint)(typeNode) })] })), shouldExportType && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, { name: typedName, isTypeOnly: true, isExportable: true, isIndexable: true, children: (0, _kubb_fabric_core_parsers_typescript.safePrint)(...typeNodes) })] }); } //#endregion Object.defineProperty(exports, "Type", { enumerable: true, get: function() { return Type; } }); Object.defineProperty(exports, "__name", { enumerable: true, get: function() { return __name; } }); Object.defineProperty(exports, "__toESM", { enumerable: true, get: function() { return __toESM; } }); Object.defineProperty(exports, "camelCase", { enumerable: true, get: function() { return camelCase; } }); Object.defineProperty(exports, "createIdentifier", { enumerable: true, get: function() { return createIdentifier; } }); Object.defineProperty(exports, "createIndexedAccessTypeNode", { enumerable: true, get: function() { return createIndexedAccessTypeNode; } }); Object.defineProperty(exports, "createPropertySignature", { enumerable: true, get: function() { return createPropertySignature; } }); Object.defineProperty(exports, "createTypeAliasDeclaration", { enumerable: true, get: function() { return createTypeAliasDeclaration; } }); Object.defineProperty(exports, "createTypeLiteralNode", { enumerable: true, get: function() { return createTypeLiteralNode; } }); Object.defineProperty(exports, "createTypeOperatorNode", { enumerable: true, get: function() { return createTypeOperatorNode; } }); Object.defineProperty(exports, "createTypeReferenceNode", { enumerable: true, get: function() { return createTypeReferenceNode; } }); Object.defineProperty(exports, "createUnionDeclaration", { enumerable: true, get: function() { return createUnionDeclaration; } }); Object.defineProperty(exports, "createUrlTemplateType", { enumerable: true, get: function() { return createUrlTemplateType; } }); Object.defineProperty(exports, "getUnknownType", { enumerable: true, get: function() { return getUnknownType; } }); Object.defineProperty(exports, "keywordTypeNodes", { enumerable: true, get: function() { return keywordTypeNodes; } }); Object.defineProperty(exports, "modifiers", { enumerable: true, get: function() { return modifiers; } }); Object.defineProperty(exports, "pascalCase", { enumerable: true, get: function() { return pascalCase; } }); //# sourceMappingURL=components-DXaWdjXj.cjs.map