UNPKG

@inox-tools/content-utils

Version:

Utilities to work with content collections on an Astro project from an integration or library.

1,504 lines (1,483 loc) 141 kB
import { AstroUserError } from './chunk-BSNWH4X2.js'; import { getDebug, debug, setProjectRoot, collectGitInfoForContentFiles } from './chunk-JOKBL6FV.js'; import { __export } from './chunk-PZ5AY32C.js'; import { withApi, onHook, registerGlobalHooks } from '@inox-tools/modular-station'; import { defineIntegration, addVitePlugin, defineUtility, createResolver } from 'astro-integration-kit'; import { mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, lstatSync, cpSync } from 'fs'; import { fileURLToPath } from 'url'; import { walk } from 'estree-walker'; import * as assert from 'assert'; import MagicString from 'magic-string'; import { dirname, resolve, join } from 'path'; import * as devalue from 'devalue'; // src/integration/state.ts function emptyState() { return { injectedCollectionsEntrypoints: [], staticOnlyCollections: [], cleanups: [] }; } var possibleConfigs = [ "content.config.ts", "content.config.mjs", "content.config.js", "content.config.mts", "content/config.ts", "content/config.mjs", "content/config.js", "content/config.mts" ]; function resolveContentPaths(config) { const baseResolver = createResolver(fileURLToPath(config.srcDir)); const contentPath = baseResolver.resolve("content"); const resolver = createResolver(contentPath); const validConfigPaths = possibleConfigs.map( (configPath) => baseResolver.resolve(`${configPath}`) ); const existingConfig = validConfigPaths.find((configPath) => existsSync(configPath)); const configFile = existingConfig ?? validConfigPaths[0]; return { projectRoot: fileURLToPath(config.root), contentPath, configPath: configFile, configExists: existingConfig !== void 0, resolve: resolver.resolve }; } var debug2 = getDebug("injector-plugin"); var thisFile = fileURLToPath(import.meta.url); var thisDir = dirname(thisFile); debug2("Resolution base:", { thisFile, thisDir }); var INJECTOR_VIRTUAL_MODULE = "@it-astro:content/injector"; var RESOLVED_INJECTOR_VIRTUAL_MODULE = `\0${INJECTOR_VIRTUAL_MODULE}`; var CONTENT_VIRTUAL_MODULE = "@it-astro:content"; var RESOLVED_CONTENT_VIRTUAL_MODULE = `\0${CONTENT_VIRTUAL_MODULE}`; var injectorPlugin = (state) => { const { logger, injectedCollectionsEntrypoints: entrypoints, contentPaths: { configPath: configFile } } = state; return { name: "@inox-tools/content-utils/injector", resolveId(id) { switch (id) { case INJECTOR_VIRTUAL_MODULE: return RESOLVED_INJECTOR_VIRTUAL_MODULE; case CONTENT_VIRTUAL_MODULE: return RESOLVED_CONTENT_VIRTUAL_MODULE; } }, load(id) { switch (id) { case RESOLVED_INJECTOR_VIRTUAL_MODULE: debug2("Generating injected collection modole from:", entrypoints); return [ ...entrypoints.map( (entrypoint, index) => `import {collections as __collections${index}} from '${entrypoint}';` ), "export const injectedCollections = {", ...entrypoints.map((_, index) => `...__collections${index},`), "};" ].join("\n"); case RESOLVED_CONTENT_VIRTUAL_MODULE: debug2("Generating fancy content module"); return [ `export {defineCollection} from ${JSON.stringify(resolve(thisDir, "runtime/fancyContent.js"))};`, 'export {z, reference} from "astro:content";' ].join("\n"); } }, transform(code, id) { if (id !== configFile) return; debug2("Transforming config file"); const ast = this.parse(code); const s = new MagicString(code); function update(node, updater) { assert.ok(isBryceNode(node), "Ping Bryce, he lied!"); const { start, end } = node; const oldCode = s.slice(start, end); const newCode = updater(oldCode); if (oldCode === newCode) { debug2("Code is unnafected by transformation."); return; } s.update(start, end, newCode); } debug2("Adding import for collection injection runtime"); s.prepend( `import {injectCollections as $$inox_tools__injectCollection} from ${JSON.stringify(resolve(thisDir, "runtime/injector.js"))};` ); walk(ast, { enter(node, parent) { if (parent?.type !== "ExportNamedDeclaration" || node.type !== "VariableDeclaration") return; const collectionDeclaration = node.declarations.find((value) => { return value.id.type === "Identifier" && value.id.name === "collections"; }); if (collectionDeclaration?.init == null) { throw new AstroUserError( "Exported collections is not initialized.", `Change your ${configFile} to initialize the value of "collections".` ); } if (node.kind !== "const") { logger.warn( `Exporting collections config using "let" may have unintended consequences. Prefer "export const collections" in your "${configFile}".` ); } const sourceInit = collectionDeclaration.init; debug2("Wrapping collection definition with collection injection"); update(sourceInit, (code2) => `$$inox_tools__injectCollection(${code2})`); } }); return { code: s.toString(), map: s.generateMap() }; }, writeBundle(info, bundle) { if (!info.dir) return; for (const chunk of Object.values(bundle)) { if (chunk.type !== "chunk") continue; if (chunk.moduleIds.length === 1 && chunk.moduleIds[0] === "\0astro:data-layer-content") { state.contentDataEntrypoint = join(info.dir, chunk.fileName); break; } } } }; }; function isBryceNode(node) { return typeof node.start === "number" && typeof node.end === "number"; } var debug3 = getDebug("seeding"); function seedCollections(state, options) { debug3("Collecting collection templates from:", options.templateDirectory); const collectionTemplates = readdirSync(options.templateDirectory).map((entry) => [entry, resolve(options.templateDirectory, entry)]).filter(([, path]) => lstatSync(path).isDirectory()); for (const [collectionName, templatePath] of collectionTemplates) { const collectionPath = state.contentPaths.resolve(collectionName); if (existsSync(collectionPath)) { debug3(`Collection ${collectionName} already present, not seeding.`); continue; } debug3(`Seeding collection ${collectionName} from ${templatePath}`); cpSync(templatePath, collectionPath, { recursive: true, dereference: true, preserveTimestamps: false }); } } var MODULE_ID = "@it-astro:content/git"; var RESOLVED_MODULE_ID = "\0@it-astro:content/git"; var INNER_MODULE_ID = "@it-astro:content/git/internal"; var RESOLVED_INNER_MODULE_ID = "\0@it-astro:content/git/internal"; var debug4 = getDebug("git-time-plugin"); var thisFile2 = fileURLToPath(import.meta.url); var thisDir2 = dirname(thisFile2); debug4("Resolution base:", { thisFile: thisFile2, thisDir: thisDir2 }); var gitDevPlugin = ({ contentPaths: { projectRoot } }) => ({ name: "@inox-tools/content-utils/gitTimes", resolveId(id) { if (id === MODULE_ID) return RESOLVED_MODULE_ID; }, load(id, { ssr } = {}) { if (id !== RESOLVED_MODULE_ID || !ssr) return; debug4(`Generated dev mode git time plugin for ${projectRoot}`); return ` import {setProjectRoot} from ${JSON.stringify(resolve(thisDir2, "runtime/git.js"))}; export { getLatestCommitDate, getOldestCommitDate, getEntryGitInfo, } from ${JSON.stringify(resolve(thisDir2, "runtime/liveGit.js"))}; setProjectRoot(${JSON.stringify(projectRoot)}); `; } }); var gitBuildPlugin = (state) => { const { contentPaths: { projectRoot } } = state; return { name: "@inox-tools/content-utils/gitTimes", resolveId(id) { if (id === MODULE_ID) return RESOLVED_MODULE_ID; if (id === INNER_MODULE_ID) return RESOLVED_INNER_MODULE_ID; }, writeBundle(info, bundle) { if (!info.dir) return; let contentDataEntrypoint; let gitStateEntrypoint; for (const chunk of Object.values(bundle)) { if (chunk.type !== "chunk") continue; if (chunk.moduleIds.length !== 1) continue; switch (chunk.moduleIds[0]) { case RESOLVED_INNER_MODULE_ID: gitStateEntrypoint = join(info.dir, chunk.fileName); break; case "\0astro:data-layer-content": contentDataEntrypoint = join(info.dir, chunk.fileName); break; } } if (contentDataEntrypoint && gitStateEntrypoint) { state.cleanups.push(() => cleanupState(contentDataEntrypoint, gitStateEntrypoint)); } }, async load(id, { ssr } = {}) { if (!ssr) return; if (id === RESOLVED_MODULE_ID) return buildFacade; if (id === RESOLVED_INNER_MODULE_ID) { debug4("Registering project root:", projectRoot); setProjectRoot(projectRoot); const trackedFiles = await collectGitInfoForContentFiles(); debug4("Git tracked file dates:", trackedFiles); return `const trackedFiles = ${devalue.stringify(new Map(trackedFiles))}; export { trackedFiles as default };`; } } }; }; async function cleanupState(contentData, gitState) { if (!existsSync(contentData) || !existsSync(gitState)) return; const originalContent = readFileSync(gitState, "utf-8"); if (!originalContent.includes("export")) return; const { default: contentValue } = await import( /*@vite-ignore*/ contentData ); const { default: gitValue } = await import( /*@vite-ignore*/ gitState ); const contentMap = devalue.unflatten(contentValue); const gitInformation = devalue.unflatten(gitValue); const usedFiles = /* @__PURE__ */ new Set(); for (const collection of contentMap.values()) { for (const entry of collection.values()) { if (typeof entry === "object" && entry && "filePath" in entry && entry.filePath) { usedFiles.add(entry.filePath); } } } const cleanedMap = new Map( Array.from(gitInformation.entries()).filter(([path]) => usedFiles.has(path)) ); const newContent = [ `const trackedFiles = ${devalue.stringify(cleanedMap)}`, "\nexport { trackedFiles as default }" ].join("\n"); writeFileSync(gitState, newContent, "utf-8"); } var buildFacade = ` import {getEntry} from 'astro:content'; import {unflatten} from ${JSON.stringify(import.meta.resolve("devalue"))}; const trackedFiles = unflatten((await import(${JSON.stringify(INNER_MODULE_ID)})).default); export async function getEntryGitInfo(...args) { const params = args.length > 1 ? args : [args[0].collection, args[0].slug ?? args[0].id]; const entry = await getEntry(...params); const rawInfo = trackedFiles.get(entry.filePath); if (!rawInfo) return; return { earliest: new Date(rawInfo.earliest), latest: new Date(rawInfo.latest), authors: Array.from(rawInfo.authors), coAuthors: Array.from(rawInfo.coAuthors), }; } const latestCommits = new Map( Array.from(trackedFiles.entries()) .map(([file, fileInfo]) => [file, new Date(fileInfo.latest)]) ); export async function getLatestCommitDate(...args) { const params = args.length > 1 ? args : [args[0].collection, args[0].slug ?? args[0].id]; const entry = await getEntry(...params); const cached = latestCommits.get(entry.filePath); if (cached !== undefined) return cached; const now = new Date(); latestCommits.set(entry.filePath, now); return now; } const oldestCommits = new Map( Array.from(trackedFiles.entries()) .map(([file, fileInfo]) => [file, new Date(fileInfo.earliest)]) ); export async function getOldestCommitDate(...args) { const params = args.length > 1 ? args : [args[0].collection, args[0].slug ?? args[0].id]; const entry = await getEntry(...params); const cached = oldestCommits.get(entry.filePath); if (cached !== undefined) return cached; const now = new Date(); oldestCommits.set(entry.filePath, now); return now; } `; // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js var zod_exports = {}; __export(zod_exports, { BRAND: () => BRAND, DIRTY: () => DIRTY, EMPTY_PATH: () => EMPTY_PATH, INVALID: () => INVALID, NEVER: () => NEVER, OK: () => OK, ParseStatus: () => ParseStatus, Schema: () => ZodType, ZodAny: () => ZodAny, ZodArray: () => ZodArray, ZodBigInt: () => ZodBigInt, ZodBoolean: () => ZodBoolean, ZodBranded: () => ZodBranded, ZodCatch: () => ZodCatch, ZodDate: () => ZodDate, ZodDefault: () => ZodDefault, ZodDiscriminatedUnion: () => ZodDiscriminatedUnion, ZodEffects: () => ZodEffects, ZodEnum: () => ZodEnum, ZodError: () => ZodError, ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind, ZodFunction: () => ZodFunction, ZodIntersection: () => ZodIntersection, ZodIssueCode: () => ZodIssueCode, ZodLazy: () => ZodLazy, ZodLiteral: () => ZodLiteral, ZodMap: () => ZodMap, ZodNaN: () => ZodNaN, ZodNativeEnum: () => ZodNativeEnum, ZodNever: () => ZodNever, ZodNull: () => ZodNull, ZodNullable: () => ZodNullable, ZodNumber: () => ZodNumber, ZodObject: () => ZodObject, ZodOptional: () => ZodOptional, ZodParsedType: () => ZodParsedType, ZodPipeline: () => ZodPipeline, ZodPromise: () => ZodPromise, ZodReadonly: () => ZodReadonly, ZodRecord: () => ZodRecord, ZodSchema: () => ZodType, ZodSet: () => ZodSet, ZodString: () => ZodString, ZodSymbol: () => ZodSymbol, ZodTransformer: () => ZodEffects, ZodTuple: () => ZodTuple, ZodType: () => ZodType, ZodUndefined: () => ZodUndefined, ZodUnion: () => ZodUnion, ZodUnknown: () => ZodUnknown, ZodVoid: () => ZodVoid, addIssueToContext: () => addIssueToContext, any: () => anyType, array: () => arrayType, bigint: () => bigIntType, boolean: () => booleanType, coerce: () => coerce, custom: () => custom, date: () => dateType, datetimeRegex: () => datetimeRegex, default: () => zod_default, defaultErrorMap: () => en_default, discriminatedUnion: () => discriminatedUnionType, effect: () => effectsType, enum: () => enumType, function: () => functionType, getErrorMap: () => getErrorMap, getParsedType: () => getParsedType, instanceof: () => instanceOfType, intersection: () => intersectionType, isAborted: () => isAborted, isAsync: () => isAsync, isDirty: () => isDirty, isValid: () => isValid, late: () => late, lazy: () => lazyType, literal: () => literalType, makeIssue: () => makeIssue, map: () => mapType, nan: () => nanType, nativeEnum: () => nativeEnumType, never: () => neverType, null: () => nullType, nullable: () => nullableType, number: () => numberType, object: () => objectType, objectUtil: () => objectUtil, oboolean: () => oboolean, onumber: () => onumber, optional: () => optionalType, ostring: () => ostring, pipeline: () => pipelineType, preprocess: () => preprocessType, promise: () => promiseType, quotelessJson: () => quotelessJson, record: () => recordType, set: () => setType, setErrorMap: () => setErrorMap, strictObject: () => strictObjectType, string: () => stringType, symbol: () => symbolType, transformer: () => effectsType, tuple: () => tupleType, undefined: () => undefinedType, union: () => unionType, unknown: () => unknownType, util: () => util, void: () => voidType, z: () => external_exports }); // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js var external_exports = {}; __export(external_exports, { BRAND: () => BRAND, DIRTY: () => DIRTY, EMPTY_PATH: () => EMPTY_PATH, INVALID: () => INVALID, NEVER: () => NEVER, OK: () => OK, ParseStatus: () => ParseStatus, Schema: () => ZodType, ZodAny: () => ZodAny, ZodArray: () => ZodArray, ZodBigInt: () => ZodBigInt, ZodBoolean: () => ZodBoolean, ZodBranded: () => ZodBranded, ZodCatch: () => ZodCatch, ZodDate: () => ZodDate, ZodDefault: () => ZodDefault, ZodDiscriminatedUnion: () => ZodDiscriminatedUnion, ZodEffects: () => ZodEffects, ZodEnum: () => ZodEnum, ZodError: () => ZodError, ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind, ZodFunction: () => ZodFunction, ZodIntersection: () => ZodIntersection, ZodIssueCode: () => ZodIssueCode, ZodLazy: () => ZodLazy, ZodLiteral: () => ZodLiteral, ZodMap: () => ZodMap, ZodNaN: () => ZodNaN, ZodNativeEnum: () => ZodNativeEnum, ZodNever: () => ZodNever, ZodNull: () => ZodNull, ZodNullable: () => ZodNullable, ZodNumber: () => ZodNumber, ZodObject: () => ZodObject, ZodOptional: () => ZodOptional, ZodParsedType: () => ZodParsedType, ZodPipeline: () => ZodPipeline, ZodPromise: () => ZodPromise, ZodReadonly: () => ZodReadonly, ZodRecord: () => ZodRecord, ZodSchema: () => ZodType, ZodSet: () => ZodSet, ZodString: () => ZodString, ZodSymbol: () => ZodSymbol, ZodTransformer: () => ZodEffects, ZodTuple: () => ZodTuple, ZodType: () => ZodType, ZodUndefined: () => ZodUndefined, ZodUnion: () => ZodUnion, ZodUnknown: () => ZodUnknown, ZodVoid: () => ZodVoid, addIssueToContext: () => addIssueToContext, any: () => anyType, array: () => arrayType, bigint: () => bigIntType, boolean: () => booleanType, coerce: () => coerce, custom: () => custom, date: () => dateType, datetimeRegex: () => datetimeRegex, defaultErrorMap: () => en_default, discriminatedUnion: () => discriminatedUnionType, effect: () => effectsType, enum: () => enumType, function: () => functionType, getErrorMap: () => getErrorMap, getParsedType: () => getParsedType, instanceof: () => instanceOfType, intersection: () => intersectionType, isAborted: () => isAborted, isAsync: () => isAsync, isDirty: () => isDirty, isValid: () => isValid, late: () => late, lazy: () => lazyType, literal: () => literalType, makeIssue: () => makeIssue, map: () => mapType, nan: () => nanType, nativeEnum: () => nativeEnumType, never: () => neverType, null: () => nullType, nullable: () => nullableType, number: () => numberType, object: () => objectType, objectUtil: () => objectUtil, oboolean: () => oboolean, onumber: () => onumber, optional: () => optionalType, ostring: () => ostring, pipeline: () => pipelineType, preprocess: () => preprocessType, promise: () => promiseType, quotelessJson: () => quotelessJson, record: () => recordType, set: () => setType, setErrorMap: () => setErrorMap, strictObject: () => strictObjectType, string: () => stringType, symbol: () => symbolType, transformer: () => effectsType, tuple: () => tupleType, undefined: () => undefinedType, union: () => unionType, unknown: () => unknownType, util: () => util, void: () => voidType }); // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js var util; (function(util2) { util2.assertEqual = (_) => { }; function assertIs(_arg) { } util2.assertIs = assertIs; function assertNever(_x) { throw new Error(); } util2.assertNever = assertNever; util2.arrayToEnum = (items) => { const obj = {}; for (const item of items) { obj[item] = item; } return obj; }; util2.getValidEnumValues = (obj) => { const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number"); const filtered = {}; for (const k of validKeys) { filtered[k] = obj[k]; } return util2.objectValues(filtered); }; util2.objectValues = (obj) => { return util2.objectKeys(obj).map(function(e) { return obj[e]; }); }; util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => { const keys = []; for (const key in object) { if (Object.prototype.hasOwnProperty.call(object, key)) { keys.push(key); } } return keys; }; util2.find = (arr, checker) => { for (const item of arr) { if (checker(item)) return item; } return void 0; }; util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val; function joinValues(array, separator = " | ") { return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator); } util2.joinValues = joinValues; util2.jsonStringifyReplacer = (_, value) => { if (typeof value === "bigint") { return value.toString(); } return value; }; })(util || (util = {})); var objectUtil; (function(objectUtil2) { objectUtil2.mergeShapes = (first, second) => { return { ...first, ...second // second overwrites first }; }; })(objectUtil || (objectUtil = {})); var ZodParsedType = util.arrayToEnum([ "string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set" ]); var getParsedType = (data) => { const t = typeof data; switch (t) { case "undefined": return ZodParsedType.undefined; case "string": return ZodParsedType.string; case "number": return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number; case "boolean": return ZodParsedType.boolean; case "function": return ZodParsedType.function; case "bigint": return ZodParsedType.bigint; case "symbol": return ZodParsedType.symbol; case "object": if (Array.isArray(data)) { return ZodParsedType.array; } if (data === null) { return ZodParsedType.null; } if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { return ZodParsedType.promise; } if (typeof Map !== "undefined" && data instanceof Map) { return ZodParsedType.map; } if (typeof Set !== "undefined" && data instanceof Set) { return ZodParsedType.set; } if (typeof Date !== "undefined" && data instanceof Date) { return ZodParsedType.date; } return ZodParsedType.object; default: return ZodParsedType.unknown; } }; // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js var ZodIssueCode = util.arrayToEnum([ "invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of", "not_finite" ]); var quotelessJson = (obj) => { const json = JSON.stringify(obj, null, 2); return json.replace(/"([^"]+)":/g, "$1:"); }; var ZodError = class _ZodError extends Error { get errors() { return this.issues; } constructor(issues) { super(); this.issues = []; this.addIssue = (sub) => { this.issues = [...this.issues, sub]; }; this.addIssues = (subs = []) => { this.issues = [...this.issues, ...subs]; }; const actualProto = new.target.prototype; if (Object.setPrototypeOf) { Object.setPrototypeOf(this, actualProto); } else { this.__proto__ = actualProto; } this.name = "ZodError"; this.issues = issues; } format(_mapper) { const mapper = _mapper || function(issue) { return issue.message; }; const fieldErrors = { _errors: [] }; const processError = (error) => { for (const issue of error.issues) { if (issue.code === "invalid_union") { issue.unionErrors.map(processError); } else if (issue.code === "invalid_return_type") { processError(issue.returnTypeError); } else if (issue.code === "invalid_arguments") { processError(issue.argumentsError); } else if (issue.path.length === 0) { fieldErrors._errors.push(mapper(issue)); } else { let curr = fieldErrors; let i = 0; while (i < issue.path.length) { const el = issue.path[i]; const terminal = i === issue.path.length - 1; if (!terminal) { curr[el] = curr[el] || { _errors: [] }; } else { curr[el] = curr[el] || { _errors: [] }; curr[el]._errors.push(mapper(issue)); } curr = curr[el]; i++; } } } }; processError(this); return fieldErrors; } static assert(value) { if (!(value instanceof _ZodError)) { throw new Error(`Not a ZodError: ${value}`); } } toString() { return this.message; } get message() { return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); } get isEmpty() { return this.issues.length === 0; } flatten(mapper = (issue) => issue.message) { const fieldErrors = {}; const formErrors = []; for (const sub of this.issues) { if (sub.path.length > 0) { const firstEl = sub.path[0]; fieldErrors[firstEl] = fieldErrors[firstEl] || []; fieldErrors[firstEl].push(mapper(sub)); } else { formErrors.push(mapper(sub)); } } return { formErrors, fieldErrors }; } get formErrors() { return this.flatten(); } }; ZodError.create = (issues) => { const error = new ZodError(issues); return error; }; // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js var errorMap = (issue, _ctx) => { let message; switch (issue.code) { case ZodIssueCode.invalid_type: if (issue.received === ZodParsedType.undefined) { message = "Required"; } else { message = `Expected ${issue.expected}, received ${issue.received}`; } break; case ZodIssueCode.invalid_literal: message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`; break; case ZodIssueCode.unrecognized_keys: message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`; break; case ZodIssueCode.invalid_union: message = `Invalid input`; break; case ZodIssueCode.invalid_union_discriminator: message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`; break; case ZodIssueCode.invalid_enum_value: message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`; break; case ZodIssueCode.invalid_arguments: message = `Invalid function arguments`; break; case ZodIssueCode.invalid_return_type: message = `Invalid function return type`; break; case ZodIssueCode.invalid_date: message = `Invalid date`; break; case ZodIssueCode.invalid_string: if (typeof issue.validation === "object") { if ("includes" in issue.validation) { message = `Invalid input: must include "${issue.validation.includes}"`; if (typeof issue.validation.position === "number") { message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`; } } else if ("startsWith" in issue.validation) { message = `Invalid input: must start with "${issue.validation.startsWith}"`; } else if ("endsWith" in issue.validation) { message = `Invalid input: must end with "${issue.validation.endsWith}"`; } else { util.assertNever(issue.validation); } } else if (issue.validation !== "regex") { message = `Invalid ${issue.validation}`; } else { message = "Invalid"; } break; case ZodIssueCode.too_small: if (issue.type === "array") message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`; else if (issue.type === "string") message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`; else if (issue.type === "number") message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`; else if (issue.type === "bigint") message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`; else if (issue.type === "date") message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`; else message = "Invalid input"; break; case ZodIssueCode.too_big: if (issue.type === "array") message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`; else if (issue.type === "string") message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`; else if (issue.type === "number") message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; else if (issue.type === "bigint") message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; else if (issue.type === "date") message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`; else message = "Invalid input"; break; case ZodIssueCode.custom: message = `Invalid input`; break; case ZodIssueCode.invalid_intersection_types: message = `Intersection results could not be merged`; break; case ZodIssueCode.not_multiple_of: message = `Number must be a multiple of ${issue.multipleOf}`; break; case ZodIssueCode.not_finite: message = "Number must be finite"; break; default: message = _ctx.defaultError; util.assertNever(issue); } return { message }; }; var en_default = errorMap; // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js var overrideErrorMap = en_default; function setErrorMap(map) { overrideErrorMap = map; } function getErrorMap() { return overrideErrorMap; } // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js var makeIssue = (params) => { const { data, path, errorMaps, issueData } = params; const fullPath = [...path, ...issueData.path || []]; const fullIssue = { ...issueData, path: fullPath }; if (issueData.message !== void 0) { return { ...issueData, path: fullPath, message: issueData.message }; } let errorMessage = ""; const maps = errorMaps.filter((m) => !!m).slice().reverse(); for (const map of maps) { errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; } return { ...issueData, path: fullPath, message: errorMessage }; }; var EMPTY_PATH = []; function addIssueToContext(ctx, issueData) { const overrideMap = getErrorMap(); const issue = makeIssue({ issueData, data: ctx.data, path: ctx.path, errorMaps: [ ctx.common.contextualErrorMap, // contextual error map is first priority ctx.schemaErrorMap, // then schema-bound map if available overrideMap, // then global override map overrideMap === en_default ? void 0 : en_default // then global default map ].filter((x) => !!x) }); ctx.common.issues.push(issue); } var ParseStatus = class _ParseStatus { constructor() { this.value = "valid"; } dirty() { if (this.value === "valid") this.value = "dirty"; } abort() { if (this.value !== "aborted") this.value = "aborted"; } static mergeArray(status, results) { const arrayValue = []; for (const s of results) { if (s.status === "aborted") return INVALID; if (s.status === "dirty") status.dirty(); arrayValue.push(s.value); } return { status: status.value, value: arrayValue }; } static async mergeObjectAsync(status, pairs) { const syncPairs = []; for (const pair of pairs) { const key = await pair.key; const value = await pair.value; syncPairs.push({ key, value }); } return _ParseStatus.mergeObjectSync(status, syncPairs); } static mergeObjectSync(status, pairs) { const finalObject = {}; for (const pair of pairs) { const { key, value } = pair; if (key.status === "aborted") return INVALID; if (value.status === "aborted") return INVALID; if (key.status === "dirty") status.dirty(); if (value.status === "dirty") status.dirty(); if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { finalObject[key.value] = value.value; } } return { status: status.value, value: finalObject }; } }; var INVALID = Object.freeze({ status: "aborted" }); var DIRTY = (value) => ({ status: "dirty", value }); var OK = (value) => ({ status: "valid", value }); var isAborted = (x) => x.status === "aborted"; var isDirty = (x) => x.status === "dirty"; var isValid = (x) => x.status === "valid"; var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise; // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js var errorUtil; (function(errorUtil2) { errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {}; errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message; })(errorUtil || (errorUtil = {})); // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js var ParseInputLazyPath = class { constructor(parent, value, path, key) { this._cachedPath = []; this.parent = parent; this.data = value; this._path = path; this._key = key; } get path() { if (!this._cachedPath.length) { if (Array.isArray(this._key)) { this._cachedPath.push(...this._path, ...this._key); } else { this._cachedPath.push(...this._path, this._key); } } return this._cachedPath; } }; var handleResult = (ctx, result) => { if (isValid(result)) { return { success: true, data: result.value }; } else { if (!ctx.common.issues.length) { throw new Error("Validation failed but no issues detected."); } return { success: false, get error() { if (this._error) return this._error; const error = new ZodError(ctx.common.issues); this._error = error; return this._error; } }; } }; function processCreateParams(params) { if (!params) return {}; const { errorMap: errorMap2, invalid_type_error, required_error, description } = params; if (errorMap2 && (invalid_type_error || required_error)) { throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); } if (errorMap2) return { errorMap: errorMap2, description }; const customMap = (iss, ctx) => { const { message } = params; if (iss.code === "invalid_enum_value") { return { message: message ?? ctx.defaultError }; } if (typeof ctx.data === "undefined") { return { message: message ?? required_error ?? ctx.defaultError }; } if (iss.code !== "invalid_type") return { message: ctx.defaultError }; return { message: message ?? invalid_type_error ?? ctx.defaultError }; }; return { errorMap: customMap, description }; } var ZodType = class { get description() { return this._def.description; } _getType(input) { return getParsedType(input.data); } _getOrReturnCtx(input, ctx) { return ctx || { common: input.parent.common, data: input.data, parsedType: getParsedType(input.data), schemaErrorMap: this._def.errorMap, path: input.path, parent: input.parent }; } _processInputParams(input) { return { status: new ParseStatus(), ctx: { common: input.parent.common, data: input.data, parsedType: getParsedType(input.data), schemaErrorMap: this._def.errorMap, path: input.path, parent: input.parent } }; } _parseSync(input) { const result = this._parse(input); if (isAsync(result)) { throw new Error("Synchronous parse encountered promise."); } return result; } _parseAsync(input) { const result = this._parse(input); return Promise.resolve(result); } parse(data, params) { const result = this.safeParse(data, params); if (result.success) return result.data; throw result.error; } safeParse(data, params) { const ctx = { common: { issues: [], async: params?.async ?? false, contextualErrorMap: params?.errorMap }, path: params?.path || [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data) }; const result = this._parseSync({ data, path: ctx.path, parent: ctx }); return handleResult(ctx, result); } "~validate"(data) { const ctx = { common: { issues: [], async: !!this["~standard"].async }, path: [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data) }; if (!this["~standard"].async) { try { const result = this._parseSync({ data, path: [], parent: ctx }); return isValid(result) ? { value: result.value } : { issues: ctx.common.issues }; } catch (err) { if (err?.message?.toLowerCase()?.includes("encountered")) { this["~standard"].async = true; } ctx.common = { issues: [], async: true }; } } return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result) ? { value: result.value } : { issues: ctx.common.issues }); } async parseAsync(data, params) { const result = await this.safeParseAsync(data, params); if (result.success) return result.data; throw result.error; } async safeParseAsync(data, params) { const ctx = { common: { issues: [], contextualErrorMap: params?.errorMap, async: true }, path: params?.path || [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data) }; const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx }); const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); return handleResult(ctx, result); } refine(check, message) { const getIssueProperties = (val) => { if (typeof message === "string" || typeof message === "undefined") { return { message }; } else if (typeof message === "function") { return message(val); } else { return message; } }; return this._refinement((val, ctx) => { const result = check(val); const setError = () => ctx.addIssue({ code: ZodIssueCode.custom, ...getIssueProperties(val) }); if (typeof Promise !== "undefined" && result instanceof Promise) { return result.then((data) => { if (!data) { setError(); return false; } else { return true; } }); } if (!result) { setError(); return false; } else { return true; } }); } refinement(check, refinementData) { return this._refinement((val, ctx) => { if (!check(val)) { ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); return false; } else { return true; } }); } _refinement(refinement) { return new ZodEffects({ schema: this, typeName: ZodFirstPartyTypeKind.ZodEffects, effect: { type: "refinement", refinement } }); } superRefine(refinement) { return this._refinement(refinement); } constructor(def) { this.spa = this.safeParseAsync; this._def = def; this.parse = this.parse.bind(this); this.safeParse = this.safeParse.bind(this); this.parseAsync = this.parseAsync.bind(this); this.safeParseAsync = this.safeParseAsync.bind(this); this.spa = this.spa.bind(this); this.refine = this.refine.bind(this); this.refinement = this.refinement.bind(this); this.superRefine = this.superRefine.bind(this); this.optional = this.optional.bind(this); this.nullable = this.nullable.bind(this); this.nullish = this.nullish.bind(this); this.array = this.array.bind(this); this.promise = this.promise.bind(this); this.or = this.or.bind(this); this.and = this.and.bind(this); this.transform = this.transform.bind(this); this.brand = this.brand.bind(this); this.default = this.default.bind(this); this.catch = this.catch.bind(this); this.describe = this.describe.bind(this); this.pipe = this.pipe.bind(this); this.readonly = this.readonly.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); this["~standard"] = { version: 1, vendor: "zod", validate: (data) => this["~validate"](data) }; } optional() { return ZodOptional.create(this, this._def); } nullable() { return ZodNullable.create(this, this._def); } nullish() { return this.nullable().optional(); } array() { return ZodArray.create(this); } promise() { return ZodPromise.create(this, this._def); } or(option) { return ZodUnion.create([this, option], this._def); } and(incoming) { return ZodIntersection.create(this, incoming, this._def); } transform(transform) { return new ZodEffects({ ...processCreateParams(this._def), schema: this, typeName: ZodFirstPartyTypeKind.ZodEffects, effect: { type: "transform", transform } }); } default(def) { const defaultValueFunc = typeof def === "function" ? def : () => def; return new ZodDefault({ ...processCreateParams(this._def), innerType: this, defaultValue: defaultValueFunc, typeName: ZodFirstPartyTypeKind.ZodDefault }); } brand() { return new ZodBranded({ typeName: ZodFirstPartyTypeKind.ZodBranded, type: this, ...processCreateParams(this._def) }); } catch(def) { const catchValueFunc = typeof def === "function" ? def : () => def; return new ZodCatch({ ...processCreateParams(this._def), innerType: this, catchValue: catchValueFunc, typeName: ZodFirstPartyTypeKind.ZodCatch }); } describe(description) { const This = this.constructor; return new This({ ...this._def, description }); } pipe(target) { return ZodPipeline.create(this, target); } readonly() { return ZodReadonly.create(this); } isOptional() { return this.safeParse(void 0).success; } isNullable() { return this.safeParse(null).success; } }; var cuidRegex = /^c[^\s-]{8,}$/i; var cuid2Regex = /^[0-9a-z]+$/; var ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i; var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; var nanoidRegex = /^[a-z0-9_-]{21}$/i; var jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/; var durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; var emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; var _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`; var emojiRegex; var ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; var ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/; var ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; var ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/; var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/; var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`; var dateRegex = new RegExp(`^${dateRegexSource}$`); function timeRegexSource(args) { let secondsRegexSource = `[0-5]\\d`; if (args.precision) { secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`; } else if (args.precision == null) { secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`; } const secondsQuantifier = args.precision ? "+" : "?"; return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`; } function timeRegex(args) { return new RegExp(`^${timeRegexSource(args)}$`); } function datetimeRegex(args) { let regex = `${dateRegexSource}T${timeRegexSource(args)}`; const opts = []; opts.push(args.local ? `Z?` : `Z`); if (args.offset) opts.push(`([+-]\\d{2}:?\\d{2})`); regex = `${regex}(${opts.join("|")})`; return new RegExp(`^${regex}$`); } function isValidIP(ip, version) { if ((version === "v4" || !version) && ipv4Regex.test(ip)) { return true; } if ((version === "v6" || !version) && ipv6Regex.test(ip)) { return true; } return false; } function isValidJWT(jwt, alg) { if (!jwtRegex.test(jwt)) return false; try { const [header] = jwt.split("."); if (!header) return false; const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "="); const decoded = JSON.parse(atob(base64)); if (typeof decoded !== "object" || decoded === null) return false; if ("typ" in decoded && decoded?.typ !== "JWT") return false; if (!decoded.alg) return false; if (alg && decoded.alg !== alg) return false; return true; } catch { return false; } } function isValidCidr(ip, version) { if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) { return true; } if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) { return true; } return false; } var ZodString = class _ZodString extends ZodType { _parse(input) { if (this._def.coerce) { input.data = String(input.data); } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.string) { const ctx2 = this._getOrReturnCtx(input); addIssueToContext(ctx2, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.string, received: ctx2.parsedType }); return INVALID; } const status = new ParseStatus(); let ctx = void 0; for (const check of this._def.checks) { if (check.kind === "min") { if (input.data.length < check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: check.value, type: "string", inclusive: true, exact: false, message: check.message }); status.dirty(); } } else if (check.kind === "max") { if (input.data.length > check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: check.value, type: "string", inclusive: true, exact: false, message: check.message });