UNPKG

@hey-api/openapi-ts

Version:

๐ŸŒ€ OpenAPI to TypeScript codegen. Production-ready SDKs, Zod schemas, TanStack Query hooks, and 20+ plugins. Used by Vercel, OpenCode, and PayPal.

1,542 lines (1,502 loc) โ€ข 681 kB
import { createRequire } from "node:module"; import { Project, StructureModel, fromRef, isNode, isRef, isSymbol, log, nodeBrand, ref, refs } from "@hey-api/codegen-core"; import colors from "ansi-colors"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; import ts from "typescript"; import { EOL } from "node:os"; import * as semver from "semver"; import { getResolvedInput, sendRequest } from "@hey-api/json-schema-ref-parser"; //#region rolldown:runtime var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); var __require = /* @__PURE__ */ createRequire(import.meta.url); //#endregion //#region src/generate/tsConfig.ts const __filename$1 = fileURLToPath(import.meta.url); const __dirname$1 = path.dirname(__filename$1); const findPackageJson = () => { let dir = __dirname$1; while (dir !== path.dirname(dir)) { const candidates = fs.readdirSync(dir).filter((file) => file === "package.json"); if (candidates[0]) { const packageJsonPath = path.join(dir, candidates[0]); return JSON.parse(fs.readFileSync(packageJsonPath, { encoding: "utf8" })); } dir = path.dirname(dir); } }; const loadPackageJson = () => { const packageJson = findPackageJson(); const safePackage = { bugs: { url: "" }, name: "", version: "" }; if (packageJson && typeof packageJson === "object") { if ("name" in packageJson && typeof packageJson.name === "string") safePackage.name = packageJson.name; if ("version" in packageJson && typeof packageJson.version === "string") safePackage.version = packageJson.version; if ("bugs" in packageJson && packageJson.bugs && typeof packageJson.bugs === "object") { if ("url" in packageJson.bugs && typeof packageJson.bugs.url === "string") { safePackage.bugs.url = packageJson.bugs.url; if (safePackage.bugs.url && !safePackage.bugs.url.endsWith("/")) safePackage.bugs.url += "/"; } } } return safePackage; }; const findTsConfigPath = (tsConfigPath) => { if (tsConfigPath === null) return null; if (tsConfigPath) { const resolved = path.isAbsolute(tsConfigPath) ? tsConfigPath : path.resolve(__dirname$1, tsConfigPath); return fs.existsSync(resolved) ? resolved : null; } let dir = __dirname$1; while (dir !== path.dirname(dir)) { const candidates = fs.readdirSync(dir).filter((file) => file.startsWith("tsconfig") && file.endsWith(".json")).sort((file) => file === "tsconfig.json" ? -1 : 1); if (candidates[0]) return path.join(dir, candidates[0]); dir = path.dirname(dir); } return null; }; const loadTsConfig = (configPath) => { if (!configPath) return null; const raw = ts.readConfigFile(configPath, ts.sys.readFile); if (raw.error) throw new Error(`Couldn't read tsconfig from path: ${configPath}`); return ts.parseJsonConfigFileContent(raw.config, ts.sys, path.dirname(configPath)); }; //#endregion //#region src/generate/utils.ts const ensureDirSync = (path$4) => { if (!fs.existsSync(path$4)) fs.mkdirSync(path$4, { recursive: true }); }; //#endregion //#region src/error.ts /** * Represents a single configuration error. * * Used for reporting issues with a specific config instance. */ var ConfigError = class extends Error { constructor(message) { super(message); this.name = "ConfigError"; } }; /** * Aggregates multiple config errors with their job indices for reporting. */ var ConfigValidationError = class extends Error { errors; constructor(errors) { super(`Found ${errors.length} configuration ${errors.length === 1 ? "error" : "errors"}.`); this.name = "ConfigValidationError"; this.errors = errors; } }; /** * Represents a runtime error originating from a specific job. * * Used for reporting job-level failures that are not config validation errors. */ var JobError = class extends Error { originalError; constructor(message, error) { super(message); this.name = "JobError"; this.originalError = error; } }; var HeyApiError = class extends Error { args; event; pluginName; constructor({ args, error, event, name, pluginName }) { const message = error instanceof Error ? error.message : "Unknown error"; super(message); this.args = args; this.cause = error.cause; this.event = event; this.name = name || error.name; this.pluginName = pluginName; this.stack = error.stack; } }; const logCrashReport = (error, logsDir) => { if (error instanceof ConfigError || error instanceof ConfigValidationError) return; if (error instanceof JobError) error = error.originalError.error; const logName = `openapi-ts-error-${Date.now()}.log`; const fullDir = path.resolve(process.cwd(), logsDir); ensureDirSync(fullDir); const logPath = path.resolve(fullDir, logName); let logContent = `[${(/* @__PURE__ */ new Date()).toISOString()}] `; if (error instanceof HeyApiError) { logContent += `${error.name} during event "${error.event}"\n`; if (error.pluginName) logContent += `Plugin: ${error.pluginName}\n`; logContent += `Arguments: ${JSON.stringify(error.args, null, 2)}\n\n`; } const message = error instanceof Error ? error.message : String(error); const stack = error instanceof Error ? error.stack : void 0; logContent += `Error: ${message}\n`; if (stack) logContent += `Stack:\n${stack}\n`; fs.writeFileSync(logPath, logContent); return logPath; }; const openGitHubIssueWithCrashReport = async (error) => { const packageJson = loadPackageJson(); if (!packageJson.bugs.url) return; if (error instanceof JobError) error = error.originalError.error; let body = ""; if (error instanceof HeyApiError) { if (error.pluginName) body += `**Plugin**: \`${error.pluginName}\`\n`; body += `**Event**: \`${error.event}\`\n`; body += `**Arguments**:\n\`\`\`ts\n${JSON.stringify(error.args, null, 2)}\n\`\`\`\n\n`; } const message = error instanceof Error ? error.message : String(error); const stack = error instanceof Error ? error.stack : void 0; body += `**Error**: \`${message}\`\n`; if (stack) body += `\n**Stack Trace**:\n\`\`\`\n${stack}\n\`\`\``; const search = new URLSearchParams({ body, labels: "bug ๐Ÿ”ฅ", title: "Crash Report" }); const url = `${packageJson.bugs.url}new?${search.toString()}`; const open = (await import("open")).default; await open(url); }; const printCrashReport = ({ error, logPath }) => { if (error instanceof ConfigValidationError && error.errors.length) { const groupByJob = /* @__PURE__ */ new Map(); for (const { error: err, jobIndex } of error.errors) { if (!groupByJob.has(jobIndex)) groupByJob.set(jobIndex, []); groupByJob.get(jobIndex).push(err); } for (const [jobIndex, errors] of groupByJob.entries()) { const jobPrefix = colors.gray(`[Job ${jobIndex + 1}] `); const count = errors.length; const baseString = colors.red(`Found ${count} configuration ${count === 1 ? "error" : "errors"}:`); console.error(`${jobPrefix}โ—๏ธ ${baseString}`); errors.forEach((err, index) => { const itemPrefixStr = ` [${index + 1}] `; const itemPrefix = colors.red(itemPrefixStr); console.error(`${jobPrefix}${itemPrefix}${colors.white(err.message)}`); }); } } else { let jobPrefix = colors.gray("[root] "); if (error instanceof JobError) { jobPrefix = colors.gray(`[Job ${error.originalError.jobIndex + 1}] `); error = error.originalError.error; } const baseString = colors.red("Failed with the message:"); console.error(`${jobPrefix}โŒ ${baseString}`); const itemPrefix = colors.red(` `); console.error(`${jobPrefix}${itemPrefix}${typeof error === "string" ? error : error instanceof Error ? error.message : "Unknown error"}`); } if (logPath) { const jobPrefix = colors.gray("[root] "); console.error(`${jobPrefix}${colors.cyan("๐Ÿ“„ Crash log saved to:")} ${colors.gray(logPath)}`); } }; const shouldReportCrash = async ({ error, isInteractive }) => { if (!isInteractive || error instanceof ConfigError || error instanceof ConfigValidationError) return false; return new Promise((resolve) => { const jobPrefix = colors.gray("[root] "); console.log(`${jobPrefix}${colors.yellow("๐Ÿ“ข Open a GitHub issue with crash details? (y/N):")}`); process.stdin.setEncoding("utf8"); process.stdin.once("data", (data) => { resolve(data.trim().toLowerCase() === "y"); }); }); }; //#endregion //#region src/utils/input/heyApi.ts const registryRegExp$2 = /^([\w-]+)\/([\w-]+)(?:\?([\w=&.-]*))?$/; const heyApiRegistryBaseUrl = "https://get.heyapi.dev"; /** * Creates a full Hey API Registry URL. * * @param organization - Hey API organization slug * @param project - Hey API project slug * @param queryParams - Optional query parameters * @returns The full Hey API registry URL. */ const getRegistryUrl$2 = (organization, project, queryParams) => `${heyApiRegistryBaseUrl}/${organization}/${project}${queryParams ? `?${queryParams}` : ""}`; /** * Parses a Hey API input string and extracts components. * * @param input - Hey API configuration input * @returns Parsed Hey API input components * @throws Error if the input format is invalid */ const parseShorthand$2 = (input) => { let organization = input.organization; let project = input.project; let queryParams; if (input.path) { const match = input.path.match(registryRegExp$2); if (!match) throw new Error(`Invalid Hey API shorthand format. Expected "organization/project?queryParams" or "organization/project", received: ${input.path}`); organization = match[1]; project = match[2]; queryParams = match[3]; } if (!organization) throw new Error("The Hey API organization cannot be empty."); if (!project) throw new Error("The Hey API project cannot be empty."); return { organization, project, queryParams }; }; /** * Transforms a Hey API shorthand string to the corresponding API URL. * * @param input - Hey API configuration input * @returns The Hey API Registry URL */ const inputToHeyApiPath = (input) => { const parsed = parseShorthand$2(input); return { path: getRegistryUrl$2(parsed.organization, parsed.project, parsed.queryParams), registry: "hey-api" }; }; //#endregion //#region src/utils/input/readme.ts const registryRegExp$1 = /^(@([\w-]+)\/([\w\-.]+)#)?([\w-]+)$/; /** * Creates a full ReadMe API Registry URL. * * @param uuid - ReadMe UUID * @returns The full ReadMe API registry URL. */ const getRegistryUrl$1 = (uuid) => `https://dash.readme.com/api/v1/api-registry/${uuid}`; const namespace$1 = "readme"; /** * Parses a ReadMe input string and extracts components. * * @param shorthand - ReadMe format string (@org/project#uuid or uuid) * @returns Parsed ReadMe input components * @throws Error if the input format is invalid */ const parseShorthand$1 = (shorthand) => { const match = shorthand.match(registryRegExp$1); if (!match) throw new Error(`Invalid ReadMe shorthand format. Expected "${namespace$1}:@organization/project#uuid" or "${namespace$1}:uuid", received: ${namespace$1}:${shorthand}`); const [, , organization, project, uuid] = match; if (!uuid) throw new Error("The ReadMe UUID cannot be empty."); return { organization, project, uuid }; }; /** * Transforms a ReadMe shorthand string to the corresponding API URL. * * @param input - ReadMe format string * @returns The ReadMe API Registry URL */ const inputToReadmePath = (input) => { const parsed = parseShorthand$1(input.slice(`${namespace$1}:`.length)); return { ...parsed, path: getRegistryUrl$1(parsed.uuid), registry: "readme" }; }; //#endregion //#region src/utils/input/scalar.ts const registryRegExp = /^(@[\w-]+)\/([\w.-]+)$/; /** * Creates a full Scalar API Registry URL. * * @param organization - Scalar organization slug * @param project - Scalar project slug * @returns The full Scalar API registry URL. */ const getRegistryUrl = (organization, project) => `https://registry.scalar.com/${organization}/apis/${project}/latest?format=json`; const namespace = "scalar"; /** * Parses a Scalar input string and extracts components. * * @param shorthand - Scalar format string (@org/project) * @returns Parsed Scalar input components * @throws Error if the input format is invalid */ const parseShorthand = (shorthand) => { const match = shorthand.match(registryRegExp); if (!match) throw new Error(`Invalid Scalar shorthand format. Expected "${namespace}:@organization/project", received: ${namespace}:${shorthand}`); const [, organization, project] = match; if (!organization) throw new Error("The Scalar organization cannot be empty."); if (!project) throw new Error("The Scalar project cannot be empty."); return { organization, project }; }; /** * Transforms a Scalar shorthand string to the corresponding API URL. * * @param input - Scalar format string * @returns The Scalar API Registry URL */ const inputToScalarPath = (input) => { const parsed = parseShorthand(input.slice(`${namespace}:`.length)); return { ...parsed, path: getRegistryUrl(parsed.organization, parsed.project), registry: "scalar" }; }; //#endregion //#region src/utils/input/index.ts const inputToApiRegistry = (input) => { if (input.path.startsWith("readme:")) { Object.assign(input, inputToReadmePath(input.path)); return; } if (input.path.startsWith("scalar:")) { Object.assign(input, inputToScalarPath(input.path)); return; } if (input.path.startsWith(".")) return; if (input.path.startsWith(heyApiRegistryBaseUrl)) { input.path = input.path.slice(heyApiRegistryBaseUrl.length + 1); Object.assign(input, inputToHeyApiPath(input)); return; } const parts = input.path.split("/"); if (parts.length === 2 && parts.filter(Boolean).length === 2) { Object.assign(input, inputToHeyApiPath(input)); return; } }; //#endregion //#region src/config/input.ts const defaultWatch = { enabled: false, interval: 1e3, timeout: 6e4 }; const getWatch = (input) => { let watch = { ...defaultWatch }; if (typeof input.path !== "string") return watch; if (typeof input.watch === "boolean") watch.enabled = input.watch; else if (typeof input.watch === "number") { watch.enabled = true; watch.interval = input.watch; } else if (input.watch) watch = { ...watch, ...input.watch }; return watch; }; const getInput = (userConfig) => { const userInputs = userConfig.input instanceof Array ? userConfig.input : [userConfig.input]; const inputs = []; for (const userInput of userInputs) { let input = { path: "", watch: defaultWatch }; if (typeof userInput === "string") input.path = userInput; else if (userInput && (userInput.path !== void 0 || userInput.organization !== void 0)) { input = { ...input, path: heyApiRegistryBaseUrl, ...userInput }; if (input.watch !== void 0) input.watch = getWatch(input); } else input = { ...input, path: userInput }; if (typeof input.path === "string") inputToApiRegistry(input); if (userConfig.watch !== void 0 && input.watch.enabled === defaultWatch.enabled && input.watch.interval === defaultWatch.interval && input.watch.timeout === defaultWatch.timeout) input.watch = getWatch({ path: input.path, watch: userConfig.watch }); if (input.path) inputs.push(input); } return inputs; }; //#endregion //#region src/config/logs.ts const getLogs = (userConfig) => { let logs = { file: true, level: "info", path: process.cwd() }; if (typeof userConfig?.logs === "string") logs.path = userConfig.logs; else logs = { ...logs, ...userConfig?.logs }; return logs; }; //#endregion //#region src/config/merge.ts const mergeObjects = (objA, objB) => { const a = objA || {}; const b = objB || {}; return { ...a, ...b }; }; const mergeConfigs = (configA, configB) => { const a = configA || {}; const b = configB || {}; const merged = { ...a, ...b }; if (typeof merged.logs === "object") merged.logs = mergeObjects(a.logs, b.logs); return merged; }; //#endregion //#region src/config/utils/config.ts const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value !== "function"; const mergeResult = (result, mapped) => { for (const [key, value] of Object.entries(mapped)) if (value !== void 0 && value !== "") result[key] = value; return result; }; const valueToObject = ({ defaultValue, mappers: mappers$1, value }) => { let result = { ...defaultValue }; switch (typeof value) { case "boolean": if (mappers$1 && "boolean" in mappers$1) { const mapper = mappers$1.boolean; result = mergeResult(result, mapper(value)); } break; case "function": if (mappers$1 && "function" in mappers$1) { const mapper = mappers$1.function; result = mergeResult(result, mapper(value)); } break; case "number": if (mappers$1 && "number" in mappers$1) { const mapper = mappers$1.number; result = mergeResult(result, mapper(value)); } break; case "string": if (mappers$1 && "string" in mappers$1) { const mapper = mappers$1.string; result = mergeResult(result, mapper(value)); } break; case "object": if (isPlainObject(value)) if (mappers$1 && "object" in mappers$1 && typeof mappers$1.object === "function") { const mapper = mappers$1.object; result = mergeResult(result, mapper(value, defaultValue)); } else result = mergeResult(result, value); break; } return result; }; //#endregion //#region ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js var require_windows = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = isexe; isexe.sync = sync; var fs$3 = __require("fs"); function checkPathExt(path$4, options) { var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT; if (!pathext) return true; pathext = pathext.split(";"); if (pathext.indexOf("") !== -1) return true; for (var i = 0; i < pathext.length; i++) { var p = pathext[i].toLowerCase(); if (p && path$4.substr(-p.length).toLowerCase() === p) return true; } return false; } function checkStat(stat, path$4, options) { if (!stat.isSymbolicLink() && !stat.isFile()) return false; return checkPathExt(path$4, options); } function isexe(path$4, options, cb) { fs$3.stat(path$4, function(er, stat) { cb(er, er ? false : checkStat(stat, path$4, options)); }); } function sync(path$4, options) { return checkStat(fs$3.statSync(path$4), path$4, options); } })); //#endregion //#region ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js var require_mode = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = isexe; isexe.sync = sync; var fs$2 = __require("fs"); function isexe(path$4, options, cb) { fs$2.stat(path$4, function(er, stat) { cb(er, er ? false : checkStat(stat, options)); }); } function sync(path$4, options) { return checkStat(fs$2.statSync(path$4), options); } function checkStat(stat, options) { return stat.isFile() && checkMode(stat, options); } function checkMode(stat, options) { var mod = stat.mode; var uid = stat.uid; var gid = stat.gid; var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid(); var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid(); var u = parseInt("100", 8); var g = parseInt("010", 8); var o = parseInt("001", 8); var ug = u | g; return mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0; } })); //#endregion //#region ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js var require_isexe = /* @__PURE__ */ __commonJSMin(((exports, module) => { __require("fs"); var core; if (process.platform === "win32" || global.TESTING_WINDOWS) core = require_windows(); else core = require_mode(); module.exports = isexe; isexe.sync = sync; function isexe(path$4, options, cb) { if (typeof options === "function") { cb = options; options = {}; } if (!cb) { if (typeof Promise !== "function") throw new TypeError("callback not provided"); return new Promise(function(resolve, reject) { isexe(path$4, options || {}, function(er, is) { if (er) reject(er); else resolve(is); }); }); } core(path$4, options || {}, function(er, is) { if (er) { if (er.code === "EACCES" || options && options.ignoreErrors) { er = null; is = false; } } cb(er, is); }); } function sync(path$4, options) { try { return core.sync(path$4, options || {}); } catch (er) { if (options && options.ignoreErrors || er.code === "EACCES") return false; else throw er; } } })); //#endregion //#region ../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => { const isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys"; const path$3 = __require("path"); const COLON = isWindows ? ";" : ":"; const isexe = require_isexe(); const getNotFoundError = (cmd) => Object.assign(/* @__PURE__ */ new Error(`not found: ${cmd}`), { code: "ENOENT" }); const getPathInfo = (cmd, opt) => { const colon = opt.colon || COLON; const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [...isWindows ? [process.cwd()] : [], ...(opt.path || process.env.PATH || "").split(colon)]; const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : ""; const pathExt = isWindows ? pathExtExe.split(colon) : [""]; if (isWindows) { if (cmd.indexOf(".") !== -1 && pathExt[0] !== "") pathExt.unshift(""); } return { pathEnv, pathExt, pathExtExe }; }; const which = (cmd, opt, cb) => { if (typeof opt === "function") { cb = opt; opt = {}; } if (!opt) opt = {}; const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); const found = []; const step = (i) => new Promise((resolve, reject) => { if (i === pathEnv.length) return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd)); const ppRaw = pathEnv[i]; const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; const pCmd = path$3.join(pathPart, cmd); resolve(subStep(!pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd, i, 0)); }); const subStep = (p, i, ii) => new Promise((resolve, reject) => { if (ii === pathExt.length) return resolve(step(i + 1)); const ext = pathExt[ii]; isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { if (!er && is) if (opt.all) found.push(p + ext); else return resolve(p + ext); return resolve(subStep(p, i, ii + 1)); }); }); return cb ? step(0).then((res) => cb(null, res), cb) : step(0); }; const whichSync = (cmd, opt) => { opt = opt || {}; const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); const found = []; for (let i = 0; i < pathEnv.length; i++) { const ppRaw = pathEnv[i]; const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; const pCmd = path$3.join(pathPart, cmd); const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd; for (let j = 0; j < pathExt.length; j++) { const cur = p + pathExt[j]; try { if (isexe.sync(cur, { pathExt: pathExtExe })) if (opt.all) found.push(cur); else return cur; } catch (ex) {} } } if (opt.all && found.length) return found; if (opt.nothrow) return null; throw getNotFoundError(cmd); }; module.exports = which; which.sync = whichSync; })); //#endregion //#region ../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js var require_path_key = /* @__PURE__ */ __commonJSMin(((exports, module) => { const pathKey = (options = {}) => { const environment = options.env || process.env; if ((options.platform || process.platform) !== "win32") return "PATH"; return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path"; }; module.exports = pathKey; module.exports.default = pathKey; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js var require_resolveCommand = /* @__PURE__ */ __commonJSMin(((exports, module) => { const path$2 = __require("path"); const which = require_which(); const getPathKey = require_path_key(); function resolveCommandAttempt(parsed, withoutPathExt) { const env = parsed.options.env || process.env; const cwd = process.cwd(); const hasCustomCwd = parsed.options.cwd != null; const shouldSwitchCwd = hasCustomCwd && process.chdir !== void 0 && !process.chdir.disabled; if (shouldSwitchCwd) try { process.chdir(parsed.options.cwd); } catch (err) {} let resolved; try { resolved = which.sync(parsed.command, { path: env[getPathKey({ env })], pathExt: withoutPathExt ? path$2.delimiter : void 0 }); } catch (e) {} finally { if (shouldSwitchCwd) process.chdir(cwd); } if (resolved) resolved = path$2.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved); return resolved; } function resolveCommand(parsed) { return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); } module.exports = resolveCommand; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js var require_escape = /* @__PURE__ */ __commonJSMin(((exports, module) => { const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; function escapeCommand(arg) { arg = arg.replace(metaCharsRegExp, "^$1"); return arg; } function escapeArgument(arg, doubleEscapeMetaChars) { arg = `${arg}`; arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\""); arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1"); arg = `"${arg}"`; arg = arg.replace(metaCharsRegExp, "^$1"); if (doubleEscapeMetaChars) arg = arg.replace(metaCharsRegExp, "^$1"); return arg; } module.exports.command = escapeCommand; module.exports.argument = escapeArgument; })); //#endregion //#region ../../node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.js var require_shebang_regex = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = /^#!(.*)/; })); //#endregion //#region ../../node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.js var require_shebang_command = /* @__PURE__ */ __commonJSMin(((exports, module) => { const shebangRegex = require_shebang_regex(); module.exports = (string = "") => { const match = string.match(shebangRegex); if (!match) return null; const [path$4, argument] = match[0].replace(/#! ?/, "").split(" "); const binary = path$4.split("/").pop(); if (binary === "env") return argument; return argument ? `${binary} ${argument}` : binary; }; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js var require_readShebang = /* @__PURE__ */ __commonJSMin(((exports, module) => { const fs$1 = __require("fs"); const shebangCommand = require_shebang_command(); function readShebang(command) { const size = 150; const buffer = Buffer.alloc(size); let fd; try { fd = fs$1.openSync(command, "r"); fs$1.readSync(fd, buffer, 0, size, 0); fs$1.closeSync(fd); } catch (e) {} return shebangCommand(buffer.toString()); } module.exports = readShebang; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => { const path$1 = __require("path"); const resolveCommand = require_resolveCommand(); const escape = require_escape(); const readShebang = require_readShebang(); const isWin = process.platform === "win32"; const isExecutableRegExp = /\.(?:com|exe)$/i; const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; function detectShebang(parsed) { parsed.file = resolveCommand(parsed); const shebang = parsed.file && readShebang(parsed.file); if (shebang) { parsed.args.unshift(parsed.file); parsed.command = shebang; return resolveCommand(parsed); } return parsed.file; } function parseNonShell(parsed) { if (!isWin) return parsed; const commandFile = detectShebang(parsed); const needsShell = !isExecutableRegExp.test(commandFile); if (parsed.options.forceShell || needsShell) { const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); parsed.command = path$1.normalize(parsed.command); parsed.command = escape.command(parsed.command); parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); parsed.args = [ "/d", "/s", "/c", `"${[parsed.command].concat(parsed.args).join(" ")}"` ]; parsed.command = process.env.comspec || "cmd.exe"; parsed.options.windowsVerbatimArguments = true; } return parsed; } function parse(command, args, options) { if (args && !Array.isArray(args)) { options = args; args = null; } args = args ? args.slice(0) : []; options = Object.assign({}, options); const parsed = { command, args, options, file: void 0, original: { command, args } }; return options.shell ? parsed : parseNonShell(parsed); } module.exports = parse; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js var require_enoent = /* @__PURE__ */ __commonJSMin(((exports, module) => { const isWin = process.platform === "win32"; function notFoundError(original, syscall) { return Object.assign(/* @__PURE__ */ new Error(`${syscall} ${original.command} ENOENT`), { code: "ENOENT", errno: "ENOENT", syscall: `${syscall} ${original.command}`, path: original.command, spawnargs: original.args }); } function hookChildProcess(cp$1, parsed) { if (!isWin) return; const originalEmit = cp$1.emit; cp$1.emit = function(name, arg1) { if (name === "exit") { const err = verifyENOENT(arg1, parsed); if (err) return originalEmit.call(cp$1, "error", err); } return originalEmit.apply(cp$1, arguments); }; } function verifyENOENT(status, parsed) { if (isWin && status === 1 && !parsed.file) return notFoundError(parsed.original, "spawn"); return null; } function verifyENOENTSync(status, parsed) { if (isWin && status === 1 && !parsed.file) return notFoundError(parsed.original, "spawnSync"); return null; } module.exports = { hookChildProcess, verifyENOENT, verifyENOENTSync, notFoundError }; })); //#endregion //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.js var require_cross_spawn = /* @__PURE__ */ __commonJSMin(((exports, module) => { const cp = __require("child_process"); const parse = require_parse(); const enoent = require_enoent(); function spawn(command, args, options) { const parsed = parse(command, args, options); const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); enoent.hookChildProcess(spawned, parsed); return spawned; } function spawnSync(command, args, options) { const parsed = parse(command, args, options); const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); return result; } module.exports = spawn; module.exports.spawn = spawn; module.exports.sync = spawnSync; module.exports._parse = parse; module.exports._enoent = enoent; })); //#endregion //#region src/config/output/postprocess.ts var import_cross_spawn = require_cross_spawn(); const postProcessors = { "biome:format": { args: [ "format", "--write", "{{path}}" ], command: "biome", name: "Biome (Format)" }, "biome:lint": { args: [ "lint", "--apply", "{{path}}" ], command: "biome", name: "Biome (Lint)" }, eslint: { args: ["{{path}}", "--fix"], command: "eslint", name: "ESLint" }, oxfmt: { args: ["{{path}}"], command: "oxfmt", name: "Oxfmt" }, oxlint: { args: ["--fix", "{{path}}"], command: "oxlint", name: "Oxlint" }, prettier: { args: [ "--ignore-unknown", "{{path}}", "--write", "--ignore-path", "./.prettierignore" ], command: "prettier", name: "Prettier" } }; const postprocessOutput = (config, jobPrefix) => { for (const processor of config.postProcess) { const resolved = typeof processor === "string" ? postProcessors[processor] : processor; const name = resolved.name ?? resolved.command; const args = resolved.args.map((arg) => arg.replace("{{path}}", config.path)); console.log(`${jobPrefix}๐Ÿงน Running ${colors.cyanBright(name)}`); (0, import_cross_spawn.sync)(resolved.command, args); } }; //#endregion //#region src/config/output/source/config.ts function resolveSource(config) { const source$2 = valueToObject({ defaultValue: { enabled: Boolean(config.source), extension: "json", fileName: "source", serialize: (input) => JSON.stringify(input, null, 2) }, mappers: { boolean: (enabled) => ({ enabled }) }, value: config.source }); if (source$2.path === void 0 || source$2.path === true) source$2.path = ""; else if (source$2.path === false) source$2.path = null; return source$2; } //#endregion //#region src/config/output/config.ts function getOutput(userConfig) { if (userConfig.output instanceof Array) throw new Error("Unexpected array of outputs in user configuration. This should have been expanded already."); const userOutput = typeof userConfig.output === "string" ? { path: userConfig.output } : userConfig.output ?? {}; const legacyPostProcess = resolveLegacyPostProcess(userOutput); const output = valueToObject({ defaultValue: { clean: true, fileName: { case: "preserve", name: "{{name}}", suffix: ".gen" }, format: null, header: "// This file is auto-generated by @hey-api/openapi-ts", indexFile: true, lint: null, path: "", postProcess: [], preferExportAll: false }, mappers: { object: (fields, defaultValue) => ({ ...fields, fileName: valueToObject({ defaultValue: { ...defaultValue.fileName }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: fields.fileName }) }) }, value: userOutput }); output.tsConfig = loadTsConfig(findTsConfigPath(output.tsConfigPath)); if (output.importFileExtension === void 0 && (output.tsConfig?.options.moduleResolution === ts.ModuleResolutionKind.NodeNext || output.tsConfig?.options.moduleResolution === ts.ModuleResolutionKind.Node16)) output.importFileExtension = ".js"; if (output.importFileExtension && !output.importFileExtension.startsWith(".")) output.importFileExtension = `.${output.importFileExtension}`; output.postProcess = normalizePostProcess(userOutput.postProcess ?? legacyPostProcess); output.source = resolveSource(output); return output; } function resolveLegacyPostProcess(config) { const result = []; if (config.lint !== void 0) { let processor; let preset; if (config.lint) { preset = config.lint === "biome" ? "biome:lint" : config.lint; processor = postProcessors[preset]; if (processor) result.push(processor); } log.warnDeprecated({ context: "output", field: "lint", replacement: `postProcess: [${processor && preset ? `'${preset}'` : ""}]` }); } if (config.format !== void 0) { let processor; let preset; if (config.format) { preset = config.format === "biome" ? "biome:format" : config.format; processor = postProcessors[preset]; if (processor) result.push(processor); } log.warnDeprecated({ context: "output", field: "format", replacement: `postProcess: [${processor && preset ? `'${preset}'` : ""}]` }); } return result; } function normalizePostProcess(input) { if (!input) return []; return input.map((item) => { if (typeof item === "string") { const preset = postProcessors[item]; if (!preset) throw new Error(`Unknown post-processor preset: "${item}"`); return preset; } return { name: item.name ?? item.command, ...item }; }); } //#endregion //#region src/config/packages.ts /** * Finds and reads the project's package.json file by searching upwards from the config file location, * or from process.cwd() if no config file is provided. * This ensures we get the correct dependencies even in monorepo setups. * * @param configFilePath - The path to the configuration file (e.g., openapi-ts.config.ts) * @returns An object containing all project dependencies (dependencies, devDependencies, peerDependencies, optionalDependencies) */ const getProjectDependencies = (configFilePath) => { let currentDir = configFilePath ? path.dirname(configFilePath) : process.cwd(); while (currentDir !== path.dirname(currentDir)) { const packageJsonPath = path.join(currentDir, "package.json"); if (fs.existsSync(packageJsonPath)) try { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); return { ...packageJson.dependencies, ...packageJson.devDependencies, ...packageJson.peerDependencies, ...packageJson.optionalDependencies }; } catch {} const parentDir = path.dirname(currentDir); if (parentDir === currentDir) break; currentDir = parentDir; } return {}; }; //#endregion //#region src/config/parser.ts const defaultPaginationKeywords = [ "after", "before", "cursor", "offset", "page", "start" ]; const getParser = (userConfig) => { return valueToObject({ defaultValue: { hooks: {}, pagination: { keywords: defaultPaginationKeywords }, transforms: { enums: { case: "PascalCase", enabled: false, mode: "root", name: "{{name}}Enum" }, propertiesRequiredByDefault: false, readWrite: { enabled: true, requests: { case: "preserve", name: "{{name}}Writable" }, responses: { case: "preserve", name: "{{name}}" } } }, validate_EXPERIMENTAL: false }, mappers: { object: (fields, defaultValue) => ({ ...fields, pagination: valueToObject({ defaultValue: { ...defaultValue.pagination }, value: fields.pagination }), transforms: valueToObject({ defaultValue: { ...defaultValue.transforms }, mappers: { object: (fields$1, defaultValue$1) => ({ ...fields$1, enums: valueToObject({ defaultValue: { ...defaultValue$1.enums, enabled: fields$1.enums !== void 0 ? Boolean(fields$1.enums) : defaultValue$1.enums.enabled }, mappers: { boolean: (enabled) => ({ enabled }), string: (mode) => ({ mode }) }, value: fields$1.enums }), propertiesRequiredByDefault: fields$1.propertiesRequiredByDefault !== void 0 ? fields$1.propertiesRequiredByDefault : defaultValue$1.propertiesRequiredByDefault, readWrite: valueToObject({ defaultValue: { ...defaultValue$1.readWrite, enabled: fields$1.readWrite !== void 0 ? Boolean(fields$1.readWrite) : defaultValue$1.readWrite.enabled }, mappers: { boolean: (enabled) => ({ enabled }), object: (fields$2, defaultValue$2) => ({ ...fields$2, requests: valueToObject({ defaultValue: { ...defaultValue$2.requests }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: fields$2.requests }), responses: valueToObject({ defaultValue: { ...defaultValue$2.responses }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: fields$2.responses }) }) }, value: fields$1.readWrite }) }) }, value: fields.transforms }), validate_EXPERIMENTAL: fields.validate_EXPERIMENTAL === true ? "warn" : fields.validate_EXPERIMENTAL }) }, value: userConfig.parser }); }; //#endregion //#region src/plugins/shared/utils/config.ts const definePluginConfig = (defaultConfig$24) => (userConfig) => ({ ...defaultConfig$24, config: { ...defaultConfig$24.config, ...userConfig } }); /** * Reusable mappers for `enabled` and `name` fields. */ const mappers = { boolean: (enabled) => ({ enabled }), function: (name) => ({ name }), string: (name) => ({ name }) }; //#endregion //#region src/plugins/@angular/common/httpRequests/config.ts function resolveHttpRequests(config, context) { let input = config.httpRequests; if (typeof input === "string" || typeof input === "function") input = { strategy: input }; else if (typeof input === "boolean" || !input) input = { enabled: Boolean(input) }; const strategy = input.strategy ?? "flat"; return context.valueToObject({ defaultValue: { container: "class", enabled: true, methods: "instance", nesting: "operationId", nestingDelimiters: /[./]/, strategy, strategyDefaultTag: "default" }, mappers: { object(value) { value.containerName = context.valueToObject({ defaultValue: strategy === "single" ? { casing: "PascalCase", name: "HttpRequests" } : { casing: "PascalCase" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.containerName }); value.methodName = context.valueToObject({ defaultValue: strategy === "flat" ? { casing: "camelCase", name: "{{name}}Request" } : { casing: "camelCase" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.methodName }); value.segmentName = context.valueToObject({ defaultValue: { casing: "PascalCase", name: "{{name}}Requests" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.segmentName }); return value; } }, value: input }); } //#endregion //#region src/openApi/shared/locations/operation.ts /** * Built-in strategies for operations. */ const OperationStrategy = { byTags: (config) => (operation) => { const tags = operation.tags && operation.tags.length > 0 ? operation.tags : [config.fallback]; const pathSegments = (config.path ?? OperationPath.id())(operation); return tags.map((tag) => [tag, ...pathSegments]); }, flat: (config) => (operation) => { const pathSegments = (config?.path ?? OperationPath.id())(operation); return [[pathSegments[pathSegments.length - 1]]]; }, single: (config) => (operation) => { const pathSegments = (config.path ?? OperationPath.id())(operation); return [[config.root, ...pathSegments]]; } }; /** * Built-in path derivation helpers for operations. */ const OperationPath = { fromOperationId: (config) => (operation) => { const fallback = config?.fallback ?? OperationPath.id(); if (!operation.operationId) return fallback(operation); const delimiters = config?.delimiters ?? /[./]/; const segments = operation.operationId.split(delimiters).filter(Boolean); return segments.length === 0 ? fallback(operation) : segments; }, fromPath: (config) => (operation) => { const delimiters = config?.delimiters ?? /[./]/; const segments = operation.path.split(delimiters).filter(Boolean); switch (config?.methodPosition) { case "prefix": segments.unshift(operation.method.toLowerCase()); break; case "suffix": segments.push(operation.method.toLowerCase()); break; default: break; } return segments; }, id: () => (operation) => [operation.id] }; //#endregion //#region src/plugins/@angular/common/httpRequests/resolve.ts function resolvePath$2(plugin) { if (plugin.config.httpRequests.nesting === "id") return OperationPath.id(); if (plugin.config.httpRequests.nesting === "operationId") return OperationPath.fromOperationId({ delimiters: plugin.config.httpRequests.nestingDelimiters, fallback: OperationPath.id() }); return plugin.config.httpRequests.nesting; } function resolveHttpRequestsStrategy(plugin) { if (plugin.config.httpRequests.strategy === "flat") return OperationStrategy.flat({ path: (operation) => [resolvePath$2(plugin)(operation).join(".")] }); if (plugin.config.httpRequests.strategy === "single") { const root = plugin.config.httpRequests.containerName; return OperationStrategy.single({ path: resolvePath$2(plugin), root: typeof root.name === "string" ? root.name : root.name?.("") ?? "" }); } if (plugin.config.httpRequests.strategy === "byTags") return OperationStrategy.byTags({ fallback: plugin.config.httpRequests.strategyDefaultTag, path: resolvePath$2(plugin) }); return plugin.config.httpRequests.strategy; } //#endregion //#region src/plugins/@angular/common/httpResources/config.ts function resolveHttpResources(config, context) { let input = config.httpResources; if (typeof input === "string" || typeof input === "function") input = { strategy: input }; else if (typeof input === "boolean" || !input) input = { enabled: Boolean(input) }; const strategy = input.strategy ?? "flat"; return context.valueToObject({ defaultValue: { container: "class", enabled: true, methods: "instance", nesting: "operationId", nestingDelimiters: /[./]/, strategy, strategyDefaultTag: "default" }, mappers: { object(value) { value.containerName = context.valueToObject({ defaultValue: strategy === "single" ? { casing: "PascalCase", name: "HttpResources" } : { casing: "PascalCase" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.containerName }); value.methodName = context.valueToObject({ defaultValue: strategy === "flat" ? { casing: "camelCase", name: "{{name}}Resource" } : { casing: "camelCase" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.methodName }); value.segmentName = context.valueToObject({ defaultValue: { casing: "PascalCase", name: "{{name}}Resources" }, mappers: { function: (name) => ({ name }), string: (name) => ({ name }) }, value: value.segmentName }); return value; } }, value: input }); } //#endregion //#region src/plugins/@angular/common/httpResources/resolve.ts function resolvePath$1(plugin) { if (plugin.config.httpResources.nesting === "id") return OperationPath.id(); if (plugin.config.httpResources.nesting === "operationId") return OperationPath.fromOperationId({ delimiters: plugin.config.httpResources.nestingDelimiters, fallback: OperationPath.id() }); return plugin.config.httpResources.nesting; } function resolveHttpResourcesStrategy(plugin) { if (plugin.config.httpResources.strategy === "flat") return OperationStrategy.flat({ path: (operation) => [resolvePath$1(plugin)(operation).join(".")] }); if (plugin.config.httpResources.strategy === "single") { const root = plugin.config.httpResources.containerName; return OperationStrategy.single({ path: resolvePath$1(plugin), root: typeof root.name === "string" ? root.name : root.name?.("") ?? "" }); } if (plugin.config.httpResources.strategy === "byTags") return OperationStrategy.byTags({ fallback: plugin.config.httpResources.strategyDefaultTag, path: resolvePath$1(plugin) }); return plugin.config.httpResources.strategy; } //#endregion //#region src/plugins/@hey-api/client-core/utils.ts const getClientBaseUrlKey = (config) => { const client = getClientPlugin(config); if (client.name === "@hey-api/client-axios" || client.name === "@hey-api/client-nuxt") return "baseURL"; return "baseUrl"; }; const getClientPlugin = (config) => { for (const name of config.pluginOrder) { const plugin = config.plugins[name]; if (plugin?.tags?.includes("client")) return plugin; } return { config: { name: "" }, name: "" }; }; //#endregion //#region src/ir/parameter.ts const getPaginationSchema = ({ context, parameter }) => { if (!parameter.pagination) return; if (parameter.pagination === true) return parameter.schema; let schema = parameter.schema; if (schema.$ref) schema = context.resolveIrRef(schema.$ref); return schema.properties[parameter.pagination]; }; const hasParameterGroupObjectRequired = (parameterGroup) => { for (const name in parameterGroup) if (parameterGroup[name].required) return true; return false; }; const hasParametersObjectRequired = (parameters) => { if (!parameters) return false; if (hasParameterGroupObjectRequired(parameters.cookie)) return true; if (hasParameterGroupObjectRequired(parameters.header)) return true; if (hasParameterGroupObjectRequired(parameters.path)) return true; if (hasParameterGroupObjectRequired(parameters.query)) return true; return false; }; const parameterWithPagination = ({ context, parameters }) => { if (!parameters) return; for (const name in parameters.cookie) { const parameter = parameters.cookie[name]; if (parameter.pagination) return { in: parameter.location, name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`, schema: getPaginationSchema({ context, parameter }) }; } for (const name in parameters.header) { const parameter = parameters.header[name]; if (parameter.pagination) return { in: parameter.location, name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`, schema: getPaginationSchema({ context, parameter }) }; } for (const name in parameters.path) { const parameter = parameters.path[name]; if (parameter.pagination) return { in: parameter.location, name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`, schema: getPaginationSchema({ context, parameter }) }; } for (const name in parameters.query) { const parameter = parameters.query[name]; if (parameter.pagination) return { in: parameter.location, name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`, schema: getPaginationSchema({ context, parameter }) }; } }; //#endregion //#region src/ir/schema.ts /** * Ensure we don't produce redundant types, e.g. string | string. */ const dedupl