1419 lines
48 KiB
JavaScript
1419 lines
48 KiB
JavaScript
|
import { p as parseRequest, m as mergeDefaults, a as mapErrors, r as replaceInvalidDefaults, s as splitPath, t as traversePath, b as baseMemoize, S as SuperFormError, d as defaultValues, c as schemaShape, e as schemaInfo, f as merge$1 } from './index-k1TR3EJq.js';
|
||
|
import { f as fail$1 } from './index-Ddp2AB5f.js';
|
||
|
import { ZodFirstPartyTypeKind } from 'zod';
|
||
|
|
||
|
const ignoreOverride = Symbol("Let zodToJsonSchema decide on which parser to use");
|
||
|
const defaultOptions$1 = {
|
||
|
name: undefined,
|
||
|
$refStrategy: "root",
|
||
|
basePath: ["#"],
|
||
|
effectStrategy: "input",
|
||
|
pipeStrategy: "all",
|
||
|
dateStrategy: "format:date-time",
|
||
|
mapStrategy: "entries",
|
||
|
removeAdditionalStrategy: "passthrough",
|
||
|
definitionPath: "definitions",
|
||
|
target: "jsonSchema7",
|
||
|
strictUnions: false,
|
||
|
definitions: {},
|
||
|
errorMessages: false,
|
||
|
markdownDescription: false,
|
||
|
patternStrategy: "escape",
|
||
|
emailStrategy: "format:email",
|
||
|
base64Strategy: "contentEncoding:base64",
|
||
|
};
|
||
|
const getDefaultOptions = (options) => (typeof options === "string"
|
||
|
? {
|
||
|
...defaultOptions$1,
|
||
|
name: options,
|
||
|
}
|
||
|
: {
|
||
|
...defaultOptions$1,
|
||
|
...options,
|
||
|
});
|
||
|
|
||
|
const getRefs = (options) => {
|
||
|
const _options = getDefaultOptions(options);
|
||
|
const currentPath = _options.name !== undefined
|
||
|
? [..._options.basePath, _options.definitionPath, _options.name]
|
||
|
: _options.basePath;
|
||
|
return {
|
||
|
..._options,
|
||
|
currentPath: currentPath,
|
||
|
propertyPath: undefined,
|
||
|
seen: new Map(Object.entries(_options.definitions).map(([name, def]) => [
|
||
|
def._def,
|
||
|
{
|
||
|
def: def._def,
|
||
|
path: [..._options.basePath, _options.definitionPath, name],
|
||
|
// Resolution of references will be forced even though seen, so it's ok that the schema is undefined here for now.
|
||
|
jsonSchema: undefined,
|
||
|
},
|
||
|
])),
|
||
|
};
|
||
|
};
|
||
|
|
||
|
function addErrorMessage(res, key, errorMessage, refs) {
|
||
|
if (!refs?.errorMessages)
|
||
|
return;
|
||
|
if (errorMessage) {
|
||
|
res.errorMessage = {
|
||
|
...res.errorMessage,
|
||
|
[key]: errorMessage,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
|
||
|
res[key] = value;
|
||
|
addErrorMessage(res, key, errorMessage, refs);
|
||
|
}
|
||
|
|
||
|
function parseAnyDef() {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
function parseArrayDef(def, refs) {
|
||
|
const res = {
|
||
|
type: "array",
|
||
|
};
|
||
|
if (def.type?._def?.typeName !== ZodFirstPartyTypeKind.ZodAny) {
|
||
|
res.items = parseDef(def.type._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items"],
|
||
|
});
|
||
|
}
|
||
|
if (def.minLength) {
|
||
|
setResponseValueAndErrors(res, "minItems", def.minLength.value, def.minLength.message, refs);
|
||
|
}
|
||
|
if (def.maxLength) {
|
||
|
setResponseValueAndErrors(res, "maxItems", def.maxLength.value, def.maxLength.message, refs);
|
||
|
}
|
||
|
if (def.exactLength) {
|
||
|
setResponseValueAndErrors(res, "minItems", def.exactLength.value, def.exactLength.message, refs);
|
||
|
setResponseValueAndErrors(res, "maxItems", def.exactLength.value, def.exactLength.message, refs);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
function parseBigintDef(def, refs) {
|
||
|
const res = {
|
||
|
type: "integer",
|
||
|
format: "int64",
|
||
|
};
|
||
|
if (!def.checks)
|
||
|
return res;
|
||
|
for (const check of def.checks) {
|
||
|
switch (check.kind) {
|
||
|
case "min":
|
||
|
if (refs.target === "jsonSchema7") {
|
||
|
if (check.inclusive) {
|
||
|
setResponseValueAndErrors(res, "minimum", check.value, check.message, refs);
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(res, "exclusiveMinimum", check.value, check.message, refs);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!check.inclusive) {
|
||
|
res.exclusiveMinimum = true;
|
||
|
}
|
||
|
setResponseValueAndErrors(res, "minimum", check.value, check.message, refs);
|
||
|
}
|
||
|
break;
|
||
|
case "max":
|
||
|
if (refs.target === "jsonSchema7") {
|
||
|
if (check.inclusive) {
|
||
|
setResponseValueAndErrors(res, "maximum", check.value, check.message, refs);
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(res, "exclusiveMaximum", check.value, check.message, refs);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!check.inclusive) {
|
||
|
res.exclusiveMaximum = true;
|
||
|
}
|
||
|
setResponseValueAndErrors(res, "maximum", check.value, check.message, refs);
|
||
|
}
|
||
|
break;
|
||
|
case "multipleOf":
|
||
|
setResponseValueAndErrors(res, "multipleOf", check.value, check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
function parseBooleanDef() {
|
||
|
return {
|
||
|
type: "boolean",
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseBrandedDef(_def, refs) {
|
||
|
return parseDef(_def.type._def, refs);
|
||
|
}
|
||
|
|
||
|
const parseCatchDef = (def, refs) => {
|
||
|
return parseDef(def.innerType._def, refs);
|
||
|
};
|
||
|
|
||
|
function parseDateDef(def, refs, overrideDateStrategy) {
|
||
|
const strategy = overrideDateStrategy ?? refs.dateStrategy;
|
||
|
if (Array.isArray(strategy)) {
|
||
|
return {
|
||
|
anyOf: strategy.map((item, i) => parseDateDef(def, refs, item)),
|
||
|
};
|
||
|
}
|
||
|
switch (strategy) {
|
||
|
case "string":
|
||
|
case "format:date-time":
|
||
|
return {
|
||
|
type: "string",
|
||
|
format: "date-time",
|
||
|
};
|
||
|
case "format:date":
|
||
|
return {
|
||
|
type: "string",
|
||
|
format: "date",
|
||
|
};
|
||
|
case "integer":
|
||
|
return integerDateParser(def, refs);
|
||
|
}
|
||
|
}
|
||
|
const integerDateParser = (def, refs) => {
|
||
|
const res = {
|
||
|
type: "integer",
|
||
|
format: "unix-time",
|
||
|
};
|
||
|
if (refs.target === "openApi3") {
|
||
|
return res;
|
||
|
}
|
||
|
for (const check of def.checks) {
|
||
|
switch (check.kind) {
|
||
|
case "min":
|
||
|
setResponseValueAndErrors(res, "minimum", check.value, // This is in milliseconds
|
||
|
check.message, refs);
|
||
|
break;
|
||
|
case "max":
|
||
|
setResponseValueAndErrors(res, "maximum", check.value, // This is in milliseconds
|
||
|
check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
function parseDefaultDef(_def, refs) {
|
||
|
return {
|
||
|
...parseDef(_def.innerType._def, refs),
|
||
|
default: _def.defaultValue(),
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseEffectsDef(_def, refs) {
|
||
|
return refs.effectStrategy === "input"
|
||
|
? parseDef(_def.schema._def, refs)
|
||
|
: {};
|
||
|
}
|
||
|
|
||
|
function parseEnumDef(def) {
|
||
|
return {
|
||
|
type: "string",
|
||
|
enum: def.values,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const isJsonSchema7AllOfType = (type) => {
|
||
|
if ("type" in type && type.type === "string")
|
||
|
return false;
|
||
|
return "allOf" in type;
|
||
|
};
|
||
|
function parseIntersectionDef(def, refs) {
|
||
|
const allOf = [
|
||
|
parseDef(def.left._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "allOf", "0"],
|
||
|
}),
|
||
|
parseDef(def.right._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "allOf", "1"],
|
||
|
}),
|
||
|
].filter((x) => !!x);
|
||
|
let unevaluatedProperties = refs.target === "jsonSchema2019-09"
|
||
|
? { unevaluatedProperties: false }
|
||
|
: undefined;
|
||
|
const mergedAllOf = [];
|
||
|
// If either of the schemas is an allOf, merge them into a single allOf
|
||
|
allOf.forEach((schema) => {
|
||
|
if (isJsonSchema7AllOfType(schema)) {
|
||
|
mergedAllOf.push(...schema.allOf);
|
||
|
if (schema.unevaluatedProperties === undefined) {
|
||
|
// If one of the schemas has no unevaluatedProperties set,
|
||
|
// the merged schema should also have no unevaluatedProperties set
|
||
|
unevaluatedProperties = undefined;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
let nestedSchema = schema;
|
||
|
if ("additionalProperties" in schema &&
|
||
|
schema.additionalProperties === false) {
|
||
|
const { additionalProperties, ...rest } = schema;
|
||
|
nestedSchema = rest;
|
||
|
}
|
||
|
else {
|
||
|
// As soon as one of the schemas has additionalProperties set not to false, we allow unevaluatedProperties
|
||
|
unevaluatedProperties = undefined;
|
||
|
}
|
||
|
mergedAllOf.push(nestedSchema);
|
||
|
}
|
||
|
});
|
||
|
return mergedAllOf.length
|
||
|
? {
|
||
|
allOf: mergedAllOf,
|
||
|
...unevaluatedProperties,
|
||
|
}
|
||
|
: undefined;
|
||
|
}
|
||
|
|
||
|
function parseLiteralDef(def, refs) {
|
||
|
const parsedType = typeof def.value;
|
||
|
if (parsedType !== "bigint" &&
|
||
|
parsedType !== "number" &&
|
||
|
parsedType !== "boolean" &&
|
||
|
parsedType !== "string") {
|
||
|
return {
|
||
|
type: Array.isArray(def.value) ? "array" : "object",
|
||
|
};
|
||
|
}
|
||
|
if (refs.target === "openApi3") {
|
||
|
return {
|
||
|
type: parsedType === "bigint" ? "integer" : parsedType,
|
||
|
enum: [def.value],
|
||
|
};
|
||
|
}
|
||
|
return {
|
||
|
type: parsedType === "bigint" ? "integer" : parsedType,
|
||
|
const: def.value,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generated from the .source property of regular expressins found here:
|
||
|
* https://github.com/colinhacks/zod/blob/master/src/types.ts.
|
||
|
*
|
||
|
* Escapes have been doubled, and expressions with /i flag have been changed accordingly
|
||
|
*/
|
||
|
const zodPatterns = {
|
||
|
/**
|
||
|
* `c` was changed to `[cC]` to replicate /i flag
|
||
|
*/
|
||
|
cuid: "^[cC][^\\s-]{8,}$",
|
||
|
cuid2: "^[a-z][a-z0-9]*$",
|
||
|
ulid: "^[0-9A-HJKMNP-TV-Z]{26}$",
|
||
|
/**
|
||
|
* `a-z` was added to replicate /i flag
|
||
|
*/
|
||
|
email: "^(?!\\.)(?!.*\\.\\.)([a-zA-Z0-9_+-\\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\\-]*\\.)+[a-zA-Z]{2,}$",
|
||
|
emoji: "^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$",
|
||
|
/**
|
||
|
* Unused
|
||
|
*/
|
||
|
uuid: "^[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}$",
|
||
|
/**
|
||
|
* Unused
|
||
|
*/
|
||
|
ipv4: "^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$",
|
||
|
/**
|
||
|
* Unused
|
||
|
*/
|
||
|
ipv6: "^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$",
|
||
|
base64: "^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$",
|
||
|
nanoid: "^[a-zA-Z0-9_-]{21}$",
|
||
|
};
|
||
|
function parseStringDef(def, refs) {
|
||
|
const res = {
|
||
|
type: "string",
|
||
|
};
|
||
|
function processPattern(value) {
|
||
|
return refs.patternStrategy === "escape"
|
||
|
? escapeNonAlphaNumeric(value)
|
||
|
: value;
|
||
|
}
|
||
|
if (def.checks) {
|
||
|
for (const check of def.checks) {
|
||
|
switch (check.kind) {
|
||
|
case "min":
|
||
|
setResponseValueAndErrors(res, "minLength", typeof res.minLength === "number"
|
||
|
? Math.max(res.minLength, check.value)
|
||
|
: check.value, check.message, refs);
|
||
|
break;
|
||
|
case "max":
|
||
|
setResponseValueAndErrors(res, "maxLength", typeof res.maxLength === "number"
|
||
|
? Math.min(res.maxLength, check.value)
|
||
|
: check.value, check.message, refs);
|
||
|
break;
|
||
|
case "email":
|
||
|
switch (refs.emailStrategy) {
|
||
|
case "format:email":
|
||
|
addFormat(res, "email", check.message, refs);
|
||
|
break;
|
||
|
case "format:idn-email":
|
||
|
addFormat(res, "idn-email", check.message, refs);
|
||
|
break;
|
||
|
case "pattern:zod":
|
||
|
addPattern(res, zodPatterns.email, check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case "url":
|
||
|
addFormat(res, "uri", check.message, refs);
|
||
|
break;
|
||
|
case "uuid":
|
||
|
addFormat(res, "uuid", check.message, refs);
|
||
|
break;
|
||
|
case "regex":
|
||
|
addPattern(res, check.regex.source, check.message, refs);
|
||
|
break;
|
||
|
case "cuid":
|
||
|
addPattern(res, zodPatterns.cuid, check.message, refs);
|
||
|
break;
|
||
|
case "cuid2":
|
||
|
addPattern(res, zodPatterns.cuid2, check.message, refs);
|
||
|
break;
|
||
|
case "startsWith":
|
||
|
addPattern(res, "^" + processPattern(check.value), check.message, refs);
|
||
|
break;
|
||
|
case "endsWith":
|
||
|
addPattern(res, processPattern(check.value) + "$", check.message, refs);
|
||
|
break;
|
||
|
case "datetime":
|
||
|
addFormat(res, "date-time", check.message, refs);
|
||
|
break;
|
||
|
case "date":
|
||
|
addFormat(res, "date", check.message, refs);
|
||
|
break;
|
||
|
case "time":
|
||
|
addFormat(res, "time", check.message, refs);
|
||
|
break;
|
||
|
case "duration":
|
||
|
addFormat(res, "duration", check.message, refs);
|
||
|
break;
|
||
|
case "length":
|
||
|
setResponseValueAndErrors(res, "minLength", typeof res.minLength === "number"
|
||
|
? Math.max(res.minLength, check.value)
|
||
|
: check.value, check.message, refs);
|
||
|
setResponseValueAndErrors(res, "maxLength", typeof res.maxLength === "number"
|
||
|
? Math.min(res.maxLength, check.value)
|
||
|
: check.value, check.message, refs);
|
||
|
break;
|
||
|
case "includes": {
|
||
|
addPattern(res, processPattern(check.value), check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
case "ip": {
|
||
|
if (check.version !== "v6") {
|
||
|
addFormat(res, "ipv4", check.message, refs);
|
||
|
}
|
||
|
if (check.version !== "v4") {
|
||
|
addFormat(res, "ipv6", check.message, refs);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case "emoji":
|
||
|
addPattern(res, zodPatterns.emoji, check.message, refs);
|
||
|
break;
|
||
|
case "ulid": {
|
||
|
addPattern(res, zodPatterns.ulid, check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
case "base64": {
|
||
|
switch (refs.base64Strategy) {
|
||
|
case "format:binary": {
|
||
|
addFormat(res, "binary", check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
case "contentEncoding:base64": {
|
||
|
setResponseValueAndErrors(res, "contentEncoding", "base64", check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
case "pattern:zod": {
|
||
|
addPattern(res, zodPatterns.base64, check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case "nanoid": {
|
||
|
addPattern(res, zodPatterns.nanoid, check.message, refs);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
const escapeNonAlphaNumeric = (value) => Array.from(value)
|
||
|
.map((c) => (/[a-zA-Z0-9]/.test(c) ? c : `\\${c}`))
|
||
|
.join("");
|
||
|
const addFormat = (schema, value, message, refs) => {
|
||
|
if (schema.format || schema.anyOf?.some((x) => x.format)) {
|
||
|
if (!schema.anyOf) {
|
||
|
schema.anyOf = [];
|
||
|
}
|
||
|
if (schema.format) {
|
||
|
schema.anyOf.push({
|
||
|
format: schema.format,
|
||
|
...(schema.errorMessage &&
|
||
|
refs.errorMessages && {
|
||
|
errorMessage: { format: schema.errorMessage.format },
|
||
|
}),
|
||
|
});
|
||
|
delete schema.format;
|
||
|
if (schema.errorMessage) {
|
||
|
delete schema.errorMessage.format;
|
||
|
if (Object.keys(schema.errorMessage).length === 0) {
|
||
|
delete schema.errorMessage;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
schema.anyOf.push({
|
||
|
format: value,
|
||
|
...(message &&
|
||
|
refs.errorMessages && { errorMessage: { format: message } }),
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(schema, "format", value, message, refs);
|
||
|
}
|
||
|
};
|
||
|
const addPattern = (schema, value, message, refs) => {
|
||
|
if (schema.pattern || schema.allOf?.some((x) => x.pattern)) {
|
||
|
if (!schema.allOf) {
|
||
|
schema.allOf = [];
|
||
|
}
|
||
|
if (schema.pattern) {
|
||
|
schema.allOf.push({
|
||
|
pattern: schema.pattern,
|
||
|
...(schema.errorMessage &&
|
||
|
refs.errorMessages && {
|
||
|
errorMessage: { pattern: schema.errorMessage.pattern },
|
||
|
}),
|
||
|
});
|
||
|
delete schema.pattern;
|
||
|
if (schema.errorMessage) {
|
||
|
delete schema.errorMessage.pattern;
|
||
|
if (Object.keys(schema.errorMessage).length === 0) {
|
||
|
delete schema.errorMessage;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
schema.allOf.push({
|
||
|
pattern: value,
|
||
|
...(message &&
|
||
|
refs.errorMessages && { errorMessage: { pattern: message } }),
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(schema, "pattern", value, message, refs);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function parseRecordDef(def, refs) {
|
||
|
if (refs.target === "openApi3" &&
|
||
|
def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {
|
||
|
return {
|
||
|
type: "object",
|
||
|
required: def.keyType._def.values,
|
||
|
properties: def.keyType._def.values.reduce((acc, key) => ({
|
||
|
...acc,
|
||
|
[key]: parseDef(def.valueType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "properties", key],
|
||
|
}) ?? {},
|
||
|
}), {}),
|
||
|
additionalProperties: false,
|
||
|
};
|
||
|
}
|
||
|
const schema = {
|
||
|
type: "object",
|
||
|
additionalProperties: parseDef(def.valueType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "additionalProperties"],
|
||
|
}) ?? {},
|
||
|
};
|
||
|
if (refs.target === "openApi3") {
|
||
|
return schema;
|
||
|
}
|
||
|
if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodString &&
|
||
|
def.keyType._def.checks?.length) {
|
||
|
const keyType = Object.entries(parseStringDef(def.keyType._def, refs)).reduce((acc, [key, value]) => (key === "type" ? acc : { ...acc, [key]: value }), {});
|
||
|
return {
|
||
|
...schema,
|
||
|
propertyNames: keyType,
|
||
|
};
|
||
|
}
|
||
|
else if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {
|
||
|
return {
|
||
|
...schema,
|
||
|
propertyNames: {
|
||
|
enum: def.keyType._def.values,
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
return schema;
|
||
|
}
|
||
|
|
||
|
function parseMapDef(def, refs) {
|
||
|
if (refs.mapStrategy === "record") {
|
||
|
return parseRecordDef(def, refs);
|
||
|
}
|
||
|
const keys = parseDef(def.keyType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items", "items", "0"],
|
||
|
}) || {};
|
||
|
const values = parseDef(def.valueType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items", "items", "1"],
|
||
|
}) || {};
|
||
|
return {
|
||
|
type: "array",
|
||
|
maxItems: 125,
|
||
|
items: {
|
||
|
type: "array",
|
||
|
items: [keys, values],
|
||
|
minItems: 2,
|
||
|
maxItems: 2,
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseNativeEnumDef(def) {
|
||
|
const object = def.values;
|
||
|
const actualKeys = Object.keys(def.values).filter((key) => {
|
||
|
return typeof object[object[key]] !== "number";
|
||
|
});
|
||
|
const actualValues = actualKeys.map((key) => object[key]);
|
||
|
const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
|
||
|
return {
|
||
|
type: parsedTypes.length === 1
|
||
|
? parsedTypes[0] === "string"
|
||
|
? "string"
|
||
|
: "number"
|
||
|
: ["string", "number"],
|
||
|
enum: actualValues,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseNeverDef() {
|
||
|
return {
|
||
|
not: {},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseNullDef(refs) {
|
||
|
return refs.target === "openApi3"
|
||
|
? {
|
||
|
enum: ["null"],
|
||
|
nullable: true,
|
||
|
}
|
||
|
: {
|
||
|
type: "null",
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const primitiveMappings = {
|
||
|
ZodString: "string",
|
||
|
ZodNumber: "number",
|
||
|
ZodBigInt: "integer",
|
||
|
ZodBoolean: "boolean",
|
||
|
ZodNull: "null",
|
||
|
};
|
||
|
function parseUnionDef(def, refs) {
|
||
|
if (refs.target === "openApi3")
|
||
|
return asAnyOf(def, refs);
|
||
|
const options = def.options instanceof Map ? Array.from(def.options.values()) : def.options;
|
||
|
// This blocks tries to look ahead a bit to produce nicer looking schemas with type array instead of anyOf.
|
||
|
if (options.every((x) => x._def.typeName in primitiveMappings &&
|
||
|
(!x._def.checks || !x._def.checks.length))) {
|
||
|
// all types in union are primitive and lack checks, so might as well squash into {type: [...]}
|
||
|
const types = options.reduce((types, x) => {
|
||
|
const type = primitiveMappings[x._def.typeName]; //Can be safely casted due to row 43
|
||
|
return type && !types.includes(type) ? [...types, type] : types;
|
||
|
}, []);
|
||
|
return {
|
||
|
type: types.length > 1 ? types : types[0],
|
||
|
};
|
||
|
}
|
||
|
else if (options.every((x) => x._def.typeName === "ZodLiteral" && !x.description)) {
|
||
|
// all options literals
|
||
|
const types = options.reduce((acc, x) => {
|
||
|
const type = typeof x._def.value;
|
||
|
switch (type) {
|
||
|
case "string":
|
||
|
case "number":
|
||
|
case "boolean":
|
||
|
return [...acc, type];
|
||
|
case "bigint":
|
||
|
return [...acc, "integer"];
|
||
|
case "object":
|
||
|
if (x._def.value === null)
|
||
|
return [...acc, "null"];
|
||
|
case "symbol":
|
||
|
case "undefined":
|
||
|
case "function":
|
||
|
default:
|
||
|
return acc;
|
||
|
}
|
||
|
}, []);
|
||
|
if (types.length === options.length) {
|
||
|
// all the literals are primitive, as far as null can be considered primitive
|
||
|
const uniqueTypes = types.filter((x, i, a) => a.indexOf(x) === i);
|
||
|
return {
|
||
|
type: uniqueTypes.length > 1 ? uniqueTypes : uniqueTypes[0],
|
||
|
enum: options.reduce((acc, x) => {
|
||
|
return acc.includes(x._def.value) ? acc : [...acc, x._def.value];
|
||
|
}, []),
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
else if (options.every((x) => x._def.typeName === "ZodEnum")) {
|
||
|
return {
|
||
|
type: "string",
|
||
|
enum: options.reduce((acc, x) => [
|
||
|
...acc,
|
||
|
...x._def.values.filter((x) => !acc.includes(x)),
|
||
|
], []),
|
||
|
};
|
||
|
}
|
||
|
return asAnyOf(def, refs);
|
||
|
}
|
||
|
const asAnyOf = (def, refs) => {
|
||
|
const anyOf = (def.options instanceof Map
|
||
|
? Array.from(def.options.values())
|
||
|
: def.options)
|
||
|
.map((x, i) => parseDef(x._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "anyOf", `${i}`],
|
||
|
}))
|
||
|
.filter((x) => !!x &&
|
||
|
(!refs.strictUnions ||
|
||
|
(typeof x === "object" && Object.keys(x).length > 0)));
|
||
|
return anyOf.length ? { anyOf } : undefined;
|
||
|
};
|
||
|
|
||
|
function parseNullableDef(def, refs) {
|
||
|
if (["ZodString", "ZodNumber", "ZodBigInt", "ZodBoolean", "ZodNull"].includes(def.innerType._def.typeName) &&
|
||
|
(!def.innerType._def.checks || !def.innerType._def.checks.length)) {
|
||
|
if (refs.target === "openApi3") {
|
||
|
return {
|
||
|
type: primitiveMappings[def.innerType._def.typeName],
|
||
|
nullable: true,
|
||
|
};
|
||
|
}
|
||
|
return {
|
||
|
type: [
|
||
|
primitiveMappings[def.innerType._def.typeName],
|
||
|
"null",
|
||
|
],
|
||
|
};
|
||
|
}
|
||
|
if (refs.target === "openApi3") {
|
||
|
const base = parseDef(def.innerType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath],
|
||
|
});
|
||
|
if (base && '$ref' in base)
|
||
|
return { allOf: [base], nullable: true };
|
||
|
return base && { ...base, nullable: true };
|
||
|
}
|
||
|
const base = parseDef(def.innerType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "anyOf", "0"],
|
||
|
});
|
||
|
return base && { anyOf: [base, { type: "null" }] };
|
||
|
}
|
||
|
|
||
|
function parseNumberDef(def, refs) {
|
||
|
const res = {
|
||
|
type: "number",
|
||
|
};
|
||
|
if (!def.checks)
|
||
|
return res;
|
||
|
for (const check of def.checks) {
|
||
|
switch (check.kind) {
|
||
|
case "int":
|
||
|
res.type = "integer";
|
||
|
addErrorMessage(res, "type", check.message, refs);
|
||
|
break;
|
||
|
case "min":
|
||
|
if (refs.target === "jsonSchema7") {
|
||
|
if (check.inclusive) {
|
||
|
setResponseValueAndErrors(res, "minimum", check.value, check.message, refs);
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(res, "exclusiveMinimum", check.value, check.message, refs);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!check.inclusive) {
|
||
|
res.exclusiveMinimum = true;
|
||
|
}
|
||
|
setResponseValueAndErrors(res, "minimum", check.value, check.message, refs);
|
||
|
}
|
||
|
break;
|
||
|
case "max":
|
||
|
if (refs.target === "jsonSchema7") {
|
||
|
if (check.inclusive) {
|
||
|
setResponseValueAndErrors(res, "maximum", check.value, check.message, refs);
|
||
|
}
|
||
|
else {
|
||
|
setResponseValueAndErrors(res, "exclusiveMaximum", check.value, check.message, refs);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!check.inclusive) {
|
||
|
res.exclusiveMaximum = true;
|
||
|
}
|
||
|
setResponseValueAndErrors(res, "maximum", check.value, check.message, refs);
|
||
|
}
|
||
|
break;
|
||
|
case "multipleOf":
|
||
|
setResponseValueAndErrors(res, "multipleOf", check.value, check.message, refs);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
function decideAdditionalProperties(def, refs) {
|
||
|
if (refs.removeAdditionalStrategy === "strict") {
|
||
|
return def.catchall._def.typeName === "ZodNever"
|
||
|
? def.unknownKeys !== "strict"
|
||
|
: parseDef(def.catchall._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "additionalProperties"],
|
||
|
}) ?? true;
|
||
|
}
|
||
|
else {
|
||
|
return def.catchall._def.typeName === "ZodNever"
|
||
|
? def.unknownKeys === "passthrough"
|
||
|
: parseDef(def.catchall._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "additionalProperties"],
|
||
|
}) ?? true;
|
||
|
}
|
||
|
}
|
||
|
function parseObjectDef(def, refs) {
|
||
|
const result = {
|
||
|
type: "object",
|
||
|
...Object.entries(def.shape()).reduce((acc, [propName, propDef]) => {
|
||
|
if (propDef === undefined || propDef._def === undefined)
|
||
|
return acc;
|
||
|
const parsedDef = parseDef(propDef._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "properties", propName],
|
||
|
propertyPath: [...refs.currentPath, "properties", propName],
|
||
|
});
|
||
|
if (parsedDef === undefined)
|
||
|
return acc;
|
||
|
return {
|
||
|
properties: { ...acc.properties, [propName]: parsedDef },
|
||
|
required: propDef.isOptional()
|
||
|
? acc.required
|
||
|
: [...acc.required, propName],
|
||
|
};
|
||
|
}, { properties: {}, required: [] }),
|
||
|
additionalProperties: decideAdditionalProperties(def, refs),
|
||
|
};
|
||
|
if (!result.required.length)
|
||
|
delete result.required;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
const parseOptionalDef = (def, refs) => {
|
||
|
if (refs.currentPath.toString() === refs.propertyPath?.toString()) {
|
||
|
return parseDef(def.innerType._def, refs);
|
||
|
}
|
||
|
const innerSchema = parseDef(def.innerType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "anyOf", "1"],
|
||
|
});
|
||
|
return innerSchema
|
||
|
? {
|
||
|
anyOf: [
|
||
|
{
|
||
|
not: {},
|
||
|
},
|
||
|
innerSchema,
|
||
|
],
|
||
|
}
|
||
|
: {};
|
||
|
};
|
||
|
|
||
|
const parsePipelineDef = (def, refs) => {
|
||
|
if (refs.pipeStrategy === "input") {
|
||
|
return parseDef(def.in._def, refs);
|
||
|
}
|
||
|
else if (refs.pipeStrategy === "output") {
|
||
|
return parseDef(def.out._def, refs);
|
||
|
}
|
||
|
const a = parseDef(def.in._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "allOf", "0"],
|
||
|
});
|
||
|
const b = parseDef(def.out._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "allOf", a ? "1" : "0"],
|
||
|
});
|
||
|
return {
|
||
|
allOf: [a, b].filter((x) => x !== undefined),
|
||
|
};
|
||
|
};
|
||
|
|
||
|
function parsePromiseDef(def, refs) {
|
||
|
return parseDef(def.type._def, refs);
|
||
|
}
|
||
|
|
||
|
function parseSetDef(def, refs) {
|
||
|
const items = parseDef(def.valueType._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items"],
|
||
|
});
|
||
|
const schema = {
|
||
|
type: "array",
|
||
|
uniqueItems: true,
|
||
|
items,
|
||
|
};
|
||
|
if (def.minSize) {
|
||
|
setResponseValueAndErrors(schema, "minItems", def.minSize.value, def.minSize.message, refs);
|
||
|
}
|
||
|
if (def.maxSize) {
|
||
|
setResponseValueAndErrors(schema, "maxItems", def.maxSize.value, def.maxSize.message, refs);
|
||
|
}
|
||
|
return schema;
|
||
|
}
|
||
|
|
||
|
function parseTupleDef(def, refs) {
|
||
|
if (def.rest) {
|
||
|
return {
|
||
|
type: "array",
|
||
|
minItems: def.items.length,
|
||
|
items: def.items
|
||
|
.map((x, i) => parseDef(x._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items", `${i}`],
|
||
|
}))
|
||
|
.reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),
|
||
|
additionalItems: parseDef(def.rest._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "additionalItems"],
|
||
|
}),
|
||
|
};
|
||
|
}
|
||
|
else {
|
||
|
return {
|
||
|
type: "array",
|
||
|
minItems: def.items.length,
|
||
|
maxItems: def.items.length,
|
||
|
items: def.items
|
||
|
.map((x, i) => parseDef(x._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.currentPath, "items", `${i}`],
|
||
|
}))
|
||
|
.reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function parseUndefinedDef() {
|
||
|
return {
|
||
|
not: {},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseUnknownDef() {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
const parseReadonlyDef = (def, refs) => {
|
||
|
return parseDef(def.innerType._def, refs);
|
||
|
};
|
||
|
|
||
|
function parseDef(def, refs, forceResolution = false) {
|
||
|
const seenItem = refs.seen.get(def);
|
||
|
if (refs.override) {
|
||
|
const overrideResult = refs.override?.(def, refs, seenItem, forceResolution);
|
||
|
if (overrideResult !== ignoreOverride) {
|
||
|
return overrideResult;
|
||
|
}
|
||
|
}
|
||
|
if (seenItem && !forceResolution) {
|
||
|
const seenSchema = get$ref(seenItem, refs);
|
||
|
if (seenSchema !== undefined) {
|
||
|
return seenSchema;
|
||
|
}
|
||
|
}
|
||
|
const newItem = { def, path: refs.currentPath, jsonSchema: undefined };
|
||
|
refs.seen.set(def, newItem);
|
||
|
const jsonSchema = selectParser(def, def.typeName, refs);
|
||
|
if (jsonSchema) {
|
||
|
addMeta(def, refs, jsonSchema);
|
||
|
}
|
||
|
newItem.jsonSchema = jsonSchema;
|
||
|
return jsonSchema;
|
||
|
}
|
||
|
const get$ref = (item, refs) => {
|
||
|
switch (refs.$refStrategy) {
|
||
|
case "root":
|
||
|
return { $ref: item.path.join("/") };
|
||
|
case "relative":
|
||
|
return { $ref: getRelativePath(refs.currentPath, item.path) };
|
||
|
case "none":
|
||
|
case "seen": {
|
||
|
if (item.path.length < refs.currentPath.length &&
|
||
|
item.path.every((value, index) => refs.currentPath[index] === value)) {
|
||
|
console.warn(`Recursive reference detected at ${refs.currentPath.join("/")}! Defaulting to any`);
|
||
|
return {};
|
||
|
}
|
||
|
return refs.$refStrategy === "seen" ? {} : undefined;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
const getRelativePath = (pathA, pathB) => {
|
||
|
let i = 0;
|
||
|
for (; i < pathA.length && i < pathB.length; i++) {
|
||
|
if (pathA[i] !== pathB[i])
|
||
|
break;
|
||
|
}
|
||
|
return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
|
||
|
};
|
||
|
const selectParser = (def, typeName, refs) => {
|
||
|
switch (typeName) {
|
||
|
case ZodFirstPartyTypeKind.ZodString:
|
||
|
return parseStringDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodNumber:
|
||
|
return parseNumberDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodObject:
|
||
|
return parseObjectDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodBigInt:
|
||
|
return parseBigintDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodBoolean:
|
||
|
return parseBooleanDef();
|
||
|
case ZodFirstPartyTypeKind.ZodDate:
|
||
|
return parseDateDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodUndefined:
|
||
|
return parseUndefinedDef();
|
||
|
case ZodFirstPartyTypeKind.ZodNull:
|
||
|
return parseNullDef(refs);
|
||
|
case ZodFirstPartyTypeKind.ZodArray:
|
||
|
return parseArrayDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodUnion:
|
||
|
case ZodFirstPartyTypeKind.ZodDiscriminatedUnion:
|
||
|
return parseUnionDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodIntersection:
|
||
|
return parseIntersectionDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodTuple:
|
||
|
return parseTupleDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodRecord:
|
||
|
return parseRecordDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodLiteral:
|
||
|
return parseLiteralDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodEnum:
|
||
|
return parseEnumDef(def);
|
||
|
case ZodFirstPartyTypeKind.ZodNativeEnum:
|
||
|
return parseNativeEnumDef(def);
|
||
|
case ZodFirstPartyTypeKind.ZodNullable:
|
||
|
return parseNullableDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodOptional:
|
||
|
return parseOptionalDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodMap:
|
||
|
return parseMapDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodSet:
|
||
|
return parseSetDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodLazy:
|
||
|
return parseDef(def.getter()._def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodPromise:
|
||
|
return parsePromiseDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodNaN:
|
||
|
case ZodFirstPartyTypeKind.ZodNever:
|
||
|
return parseNeverDef();
|
||
|
case ZodFirstPartyTypeKind.ZodEffects:
|
||
|
return parseEffectsDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodAny:
|
||
|
return parseAnyDef();
|
||
|
case ZodFirstPartyTypeKind.ZodUnknown:
|
||
|
return parseUnknownDef();
|
||
|
case ZodFirstPartyTypeKind.ZodDefault:
|
||
|
return parseDefaultDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodBranded:
|
||
|
return parseBrandedDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodReadonly:
|
||
|
return parseReadonlyDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodCatch:
|
||
|
return parseCatchDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodPipeline:
|
||
|
return parsePipelineDef(def, refs);
|
||
|
case ZodFirstPartyTypeKind.ZodFunction:
|
||
|
case ZodFirstPartyTypeKind.ZodVoid:
|
||
|
case ZodFirstPartyTypeKind.ZodSymbol:
|
||
|
return undefined;
|
||
|
default:
|
||
|
return ((_) => undefined)();
|
||
|
}
|
||
|
};
|
||
|
const addMeta = (def, refs, jsonSchema) => {
|
||
|
if (def.description) {
|
||
|
jsonSchema.description = def.description;
|
||
|
if (refs.markdownDescription) {
|
||
|
jsonSchema.markdownDescription = def.description;
|
||
|
}
|
||
|
}
|
||
|
return jsonSchema;
|
||
|
};
|
||
|
|
||
|
const zodToJsonSchema = (schema, options) => {
|
||
|
const refs = getRefs(options);
|
||
|
const definitions = typeof options === "object" && options.definitions
|
||
|
? Object.entries(options.definitions).reduce((acc, [name, schema]) => ({
|
||
|
...acc,
|
||
|
[name]: parseDef(schema._def, {
|
||
|
...refs,
|
||
|
currentPath: [...refs.basePath, refs.definitionPath, name],
|
||
|
}, true) ?? {},
|
||
|
}), {})
|
||
|
: undefined;
|
||
|
const name = typeof options === "string" ? options : options?.name;
|
||
|
const main = parseDef(schema._def, name === undefined
|
||
|
? refs
|
||
|
: {
|
||
|
...refs,
|
||
|
currentPath: [...refs.basePath, refs.definitionPath, name],
|
||
|
}, false) ?? {};
|
||
|
const combined = name === undefined
|
||
|
? definitions
|
||
|
? {
|
||
|
...main,
|
||
|
[refs.definitionPath]: definitions,
|
||
|
}
|
||
|
: main
|
||
|
: {
|
||
|
$ref: [
|
||
|
...(refs.$refStrategy === "relative" ? [] : refs.basePath),
|
||
|
refs.definitionPath,
|
||
|
name,
|
||
|
].join("/"),
|
||
|
[refs.definitionPath]: {
|
||
|
...definitions,
|
||
|
[name]: main,
|
||
|
},
|
||
|
};
|
||
|
if (refs.target === "jsonSchema7") {
|
||
|
combined.$schema = "http://json-schema.org/draft-07/schema#";
|
||
|
}
|
||
|
else if (refs.target === "jsonSchema2019-09") {
|
||
|
combined.$schema = "https://json-schema.org/draft/2019-09/schema#";
|
||
|
}
|
||
|
return combined;
|
||
|
};
|
||
|
|
||
|
async function superValidate(data, adapter, options) {
|
||
|
if (data && "superFormValidationLibrary" in data) {
|
||
|
options = adapter;
|
||
|
adapter = data;
|
||
|
data = void 0;
|
||
|
}
|
||
|
const validator = adapter;
|
||
|
const defaults = options?.defaults ?? validator.defaults;
|
||
|
const jsonSchema = validator.jsonSchema;
|
||
|
const parsed = await parseRequest(data, jsonSchema, options);
|
||
|
const addErrors = options?.errors ?? (options?.strict ? true : !!parsed.data);
|
||
|
const parsedData = options?.strict ? parsed.data ?? {} : mergeDefaults(parsed.data, defaults);
|
||
|
let status;
|
||
|
if (!!parsed.data || addErrors) {
|
||
|
status = await /* @__PURE__ */ validator.validate(parsedData);
|
||
|
} else {
|
||
|
status = { success: false, issues: [] };
|
||
|
}
|
||
|
const valid = status.success;
|
||
|
const errors = valid || !addErrors ? {} : mapErrors(status.issues, validator.shape);
|
||
|
const dataWithDefaults = valid ? status.data : replaceInvalidDefaults(options?.strict ? mergeDefaults(parsedData, defaults) : parsedData, defaults, jsonSchema, status.issues, options?.preprocessed);
|
||
|
let outputData;
|
||
|
if (jsonSchema.additionalProperties === false) {
|
||
|
outputData = {};
|
||
|
for (const key of Object.keys(jsonSchema.properties ?? {})) {
|
||
|
if (key in dataWithDefaults)
|
||
|
outputData[key] = dataWithDefaults[key];
|
||
|
}
|
||
|
} else {
|
||
|
outputData = dataWithDefaults;
|
||
|
}
|
||
|
const output = {
|
||
|
id: parsed.id ?? options?.id ?? validator.id,
|
||
|
valid,
|
||
|
posted: parsed.posted,
|
||
|
errors,
|
||
|
data: outputData
|
||
|
};
|
||
|
if (!parsed.posted) {
|
||
|
output.constraints = validator.constraints;
|
||
|
if (Object.keys(validator.shape).length) {
|
||
|
output.shape = validator.shape;
|
||
|
}
|
||
|
}
|
||
|
return output;
|
||
|
}
|
||
|
function setError(form, path, error, options) {
|
||
|
if (error == void 0 || typeof error !== "string" && !Array.isArray(error)) {
|
||
|
options = error;
|
||
|
error = path;
|
||
|
path = "";
|
||
|
}
|
||
|
if (options === void 0)
|
||
|
options = {};
|
||
|
const errArr = Array.isArray(error) ? error : [error];
|
||
|
if (!form.errors)
|
||
|
form.errors = {};
|
||
|
if (path === null || path === "") {
|
||
|
if (!form.errors._errors)
|
||
|
form.errors._errors = [];
|
||
|
form.errors._errors = options.overwrite ? errArr : form.errors._errors.concat(errArr);
|
||
|
} else {
|
||
|
const realPath = splitPath(path);
|
||
|
const leaf = traversePath(form.errors, realPath, ({ parent, key, value }) => {
|
||
|
if (value === void 0)
|
||
|
parent[key] = {};
|
||
|
return parent[key];
|
||
|
});
|
||
|
if (leaf) {
|
||
|
leaf.parent[leaf.key] = Array.isArray(leaf.value) && !options.overwrite ? leaf.value.concat(errArr) : errArr;
|
||
|
}
|
||
|
}
|
||
|
form.valid = false;
|
||
|
const output = options.removeFiles === false ? { form } : withFiles({ form });
|
||
|
return fail$1(options.status ?? 400, output);
|
||
|
}
|
||
|
function withFiles(obj) {
|
||
|
if (typeof obj !== "object")
|
||
|
return obj;
|
||
|
for (const key in obj) {
|
||
|
const value = obj[key];
|
||
|
if (value instanceof File)
|
||
|
delete obj[key];
|
||
|
else if (value && typeof value === "object")
|
||
|
withFiles(value);
|
||
|
}
|
||
|
return obj;
|
||
|
}
|
||
|
const removeFiles = withFiles;
|
||
|
function fail(status, data) {
|
||
|
function checkForm(data2) {
|
||
|
return !!data2 && typeof data2 === "object" && "valid" in data2 && "data" in data2 && "id" in data2;
|
||
|
}
|
||
|
function checkObj(data2) {
|
||
|
if (data2 && typeof data2 === "object") {
|
||
|
for (const key in data2) {
|
||
|
const v = data2[key];
|
||
|
if (checkForm(v)) {
|
||
|
v.valid = false;
|
||
|
removeFiles(v);
|
||
|
} else if (v && typeof v === "object") {
|
||
|
checkObj(v);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return data2;
|
||
|
}
|
||
|
return fail$1(status, checkObj(data));
|
||
|
}
|
||
|
|
||
|
function constraints(schema) {
|
||
|
return _constraints(schemaInfo(schema, false, []), []);
|
||
|
}
|
||
|
function merge(...constraints2) {
|
||
|
const filtered = constraints2.filter((c) => !!c);
|
||
|
if (!filtered.length)
|
||
|
return void 0;
|
||
|
if (filtered.length == 1)
|
||
|
return filtered[0];
|
||
|
return merge$1(...filtered);
|
||
|
}
|
||
|
function _constraints(info, path) {
|
||
|
if (!info)
|
||
|
return void 0;
|
||
|
let output = void 0;
|
||
|
if (info.union && info.union.length) {
|
||
|
const infos = info.union.map((s) => schemaInfo(s, info.isOptional, path));
|
||
|
const merged = infos.map((i) => _constraints(i, path));
|
||
|
output = merge(output, ...merged);
|
||
|
if (output && (info.isNullable || info.isOptional || infos.some((i) => i?.isNullable || i?.isOptional))) {
|
||
|
delete output.required;
|
||
|
}
|
||
|
}
|
||
|
if (info.array) {
|
||
|
output = merge(output, ...info.array.map((i) => _constraints(schemaInfo(i, info.isOptional, path), path)));
|
||
|
}
|
||
|
if (info.properties) {
|
||
|
const obj = {};
|
||
|
for (const [key, prop] of Object.entries(info.properties)) {
|
||
|
const propInfo = schemaInfo(prop, !info.required?.includes(key) || prop.default !== void 0, [key]);
|
||
|
const propConstraint = _constraints(propInfo, [...path, key]);
|
||
|
if (typeof propConstraint === "object" && Object.values(propConstraint).length > 0) {
|
||
|
obj[key] = propConstraint;
|
||
|
}
|
||
|
}
|
||
|
output = merge(output, obj);
|
||
|
}
|
||
|
return output ?? constraint(info);
|
||
|
}
|
||
|
function constraint(info) {
|
||
|
const output = {};
|
||
|
const schema = info.schema;
|
||
|
const type = schema.type;
|
||
|
const format = schema.format;
|
||
|
if (type == "integer" && format == "unix-time") {
|
||
|
const date = schema;
|
||
|
if (date.minimum !== void 0)
|
||
|
output.min = new Date(date.minimum).toISOString();
|
||
|
if (date.maximum !== void 0)
|
||
|
output.max = new Date(date.maximum).toISOString();
|
||
|
} else if (type == "string") {
|
||
|
const str = schema;
|
||
|
const patterns = [
|
||
|
str.pattern,
|
||
|
...str.allOf ? str.allOf.map((s) => typeof s == "boolean" ? void 0 : s.pattern) : []
|
||
|
].filter((s) => s !== void 0);
|
||
|
if (patterns.length > 0)
|
||
|
output.pattern = patterns[0];
|
||
|
if (str.minLength !== void 0)
|
||
|
output.minlength = str.minLength;
|
||
|
if (str.maxLength !== void 0)
|
||
|
output.maxlength = str.maxLength;
|
||
|
} else if (type == "number" || type == "integer") {
|
||
|
const num = schema;
|
||
|
if (num.minimum !== void 0)
|
||
|
output.min = num.minimum;
|
||
|
else if (num.exclusiveMinimum !== void 0)
|
||
|
output.min = num.exclusiveMinimum + (type == "integer" ? 1 : Number.MIN_VALUE);
|
||
|
if (num.maximum !== void 0)
|
||
|
output.max = num.maximum;
|
||
|
else if (num.exclusiveMaximum !== void 0)
|
||
|
output.max = num.exclusiveMaximum - (type == "integer" ? 1 : Number.MIN_VALUE);
|
||
|
if (num.multipleOf !== void 0)
|
||
|
output.step = num.multipleOf;
|
||
|
} else if (type == "array") {
|
||
|
const arr = schema;
|
||
|
if (arr.minItems !== void 0)
|
||
|
output.min = arr.minItems;
|
||
|
if (arr.maxItems !== void 0)
|
||
|
output.max = arr.maxItems;
|
||
|
}
|
||
|
if (!info.isNullable && !info.isOptional) {
|
||
|
output.required = true;
|
||
|
}
|
||
|
return Object.keys(output).length > 0 ? output : void 0;
|
||
|
}
|
||
|
function schemaHash(schema) {
|
||
|
return hashCode(_schemaHash(schemaInfo(schema, false, []), 0, []));
|
||
|
}
|
||
|
function _schemaHash(info, depth, path) {
|
||
|
if (!info)
|
||
|
return "";
|
||
|
function tab() {
|
||
|
return " ".repeat(depth);
|
||
|
}
|
||
|
function mapSchemas(schemas) {
|
||
|
return schemas.map((s) => _schemaHash(schemaInfo(s, info?.isOptional ?? false, path), depth + 1, path)).filter((s) => s).join("|");
|
||
|
}
|
||
|
function nullish() {
|
||
|
const output = [];
|
||
|
if (info?.isNullable)
|
||
|
output.push("null");
|
||
|
if (info?.isOptional)
|
||
|
output.push("undefined");
|
||
|
return !output.length ? "" : "|" + output.join("|");
|
||
|
}
|
||
|
if (info.union) {
|
||
|
return "Union {\n " + tab() + mapSchemas(info.union) + "\n" + tab() + "}" + nullish();
|
||
|
}
|
||
|
if (info.properties) {
|
||
|
const output = [];
|
||
|
for (const [key, prop] of Object.entries(info.properties)) {
|
||
|
const propInfo = schemaInfo(prop, !info.required?.includes(key) || prop.default !== void 0, [key]);
|
||
|
output.push(key + ": " + _schemaHash(propInfo, depth + 1, path));
|
||
|
}
|
||
|
return "Object {\n " + tab() + output.join(",\n ") + "\n" + tab() + "}" + nullish();
|
||
|
}
|
||
|
if (info.array) {
|
||
|
return "Array[" + mapSchemas(info.array) + "]" + nullish();
|
||
|
}
|
||
|
return info.types.join("|") + nullish();
|
||
|
}
|
||
|
function hashCode(str) {
|
||
|
let hash = 0;
|
||
|
for (let i = 0, len = str.length; i < len; i++) {
|
||
|
const chr = str.charCodeAt(i);
|
||
|
hash = (hash << 5) - hash + chr;
|
||
|
hash |= 0;
|
||
|
}
|
||
|
if (hash < 0)
|
||
|
hash = hash >>> 0;
|
||
|
return hash.toString(36);
|
||
|
}
|
||
|
// @__NO_SIDE_EFFECTS__
|
||
|
function createAdapter(adapter, jsonSchema) {
|
||
|
if (!adapter || !("superFormValidationLibrary" in adapter)) {
|
||
|
throw new SuperFormError('Superforms v2 requires a validation adapter for the schema. Import one of your choice from "sveltekit-superforms/adapters" and wrap the schema with it.');
|
||
|
}
|
||
|
if (!jsonSchema)
|
||
|
jsonSchema = adapter.jsonSchema;
|
||
|
return {
|
||
|
...adapter,
|
||
|
constraints: adapter.constraints ?? constraints(jsonSchema),
|
||
|
defaults: adapter.defaults ?? defaultValues(jsonSchema),
|
||
|
shape: schemaShape(jsonSchema),
|
||
|
id: schemaHash(jsonSchema)
|
||
|
};
|
||
|
}
|
||
|
const memoize = baseMemoize;
|
||
|
const defaultOptions = {
|
||
|
dateStrategy: "integer",
|
||
|
pipeStrategy: "output",
|
||
|
$refStrategy: "none"
|
||
|
};
|
||
|
const zodToJSONSchema = /* @__NO_SIDE_EFFECTS__ */ (...params) => {
|
||
|
params[1] = typeof params[1] == "object" ? { ...defaultOptions, ...params[1] } : defaultOptions;
|
||
|
return zodToJsonSchema(...params);
|
||
|
};
|
||
|
async function validate(schema, data) {
|
||
|
const result = await schema.safeParseAsync(data);
|
||
|
if (result.success) {
|
||
|
return {
|
||
|
data: result.data,
|
||
|
success: true
|
||
|
};
|
||
|
}
|
||
|
return {
|
||
|
issues: result.error.issues.map(({ message, path }) => ({ message, path })),
|
||
|
success: false
|
||
|
};
|
||
|
}
|
||
|
function _zod(schema, options) {
|
||
|
return /* @__PURE__ */ createAdapter({
|
||
|
superFormValidationLibrary: "zod",
|
||
|
validate: async (data) => validate(schema, data),
|
||
|
jsonSchema: options?.jsonSchema ?? /* @__PURE__ */ zodToJSONSchema(schema, options?.config),
|
||
|
defaults: options?.defaults
|
||
|
});
|
||
|
}
|
||
|
function _zodClient(schema) {
|
||
|
return {
|
||
|
superFormValidationLibrary: "zod",
|
||
|
validate: async (data) => validate(schema, data)
|
||
|
};
|
||
|
}
|
||
|
const zod = /* @__PURE__ */ memoize(_zod);
|
||
|
const zodClient = /* @__PURE__ */ memoize(_zodClient);
|
||
|
|
||
|
export { setError as a, zodClient as b, fail as f, superValidate as s, zod as z };
|
||
|
//# sourceMappingURL=zod-BtM9a6Uj.js.map
|