@conform-to/zod
Advanced tools
Comparing version 1.0.0-pre.0 to 1.0.0-pre.1
@@ -1,3 +0,3 @@ | ||
import { type Constraint } from '@conform-to/dom'; | ||
import type { Constraint } from '@conform-to/dom'; | ||
import { type ZodTypeAny } from 'zod'; | ||
export declare function getConstraint(schema: ZodTypeAny): Record<string, Constraint>; |
@@ -6,105 +6,49 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
var dom = require('@conform-to/dom'); | ||
var zod = require('zod'); | ||
var keys = ['required', 'minLength', 'maxLength', 'min', 'max', 'step', 'multiple', 'pattern']; | ||
function getConstraint(schema) { | ||
function inferConstraint(schema) { | ||
var constraint = {}; | ||
if (schema instanceof zod.ZodEffects) { | ||
constraint = _rollupPluginBabelHelpers.objectSpread2({}, inferConstraint(schema.innerType())); | ||
} else if (schema instanceof zod.ZodPipeline) { | ||
constraint = _rollupPluginBabelHelpers.objectSpread2({}, inferConstraint(schema._def.out)); | ||
} else if (schema instanceof zod.ZodOptional) { | ||
constraint = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, inferConstraint(schema.unwrap())), {}, { | ||
required: false | ||
}); | ||
} else if (schema instanceof zod.ZodDefault) { | ||
constraint = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, inferConstraint(schema.removeDefault())), {}, { | ||
required: false | ||
}); | ||
} else if (schema instanceof zod.ZodArray) { | ||
constraint = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, inferConstraint(schema.element)), {}, { | ||
multiple: true | ||
}); | ||
} else if (schema instanceof zod.ZodString) { | ||
for (var check of schema._def.checks) { | ||
switch (check.kind) { | ||
case 'min': | ||
if (!constraint.minLength || constraint.minLength < check.value) { | ||
constraint.minLength = check.value; | ||
} | ||
break; | ||
case 'max': | ||
if (!constraint.maxLength || constraint.maxLength > check.value) { | ||
constraint.maxLength = check.value; | ||
} | ||
break; | ||
case 'regex': | ||
if (!constraint.pattern) { | ||
constraint.pattern = check.regex.source; | ||
} | ||
break; | ||
} | ||
} | ||
} else if (schema instanceof zod.ZodNumber) { | ||
for (var _check of schema._def.checks) { | ||
switch (_check.kind) { | ||
case 'min': | ||
dom.invariant(typeof constraint.min !== 'string', 'min is not a number'); | ||
if (typeof constraint.min === 'undefined' || constraint.min < _check.value) { | ||
constraint.min = _check.value; | ||
} | ||
break; | ||
case 'max': | ||
dom.invariant(typeof constraint.max !== 'string', 'max is not a number'); | ||
if (typeof constraint.max === 'undefined' || constraint.max > _check.value) { | ||
constraint.max = _check.value; | ||
} | ||
break; | ||
} | ||
} | ||
} else if (schema instanceof zod.ZodEnum) { | ||
constraint.pattern = schema.options.map(option => | ||
// To escape unsafe characters on regex | ||
option.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')).join('|'); | ||
} | ||
if (typeof constraint.required === 'undefined') { | ||
constraint.required = true; | ||
} | ||
return constraint; | ||
} | ||
var keys = ['required', 'minLength', 'maxLength', 'min', 'max', 'step', 'multiple', 'pattern']; | ||
function resolveFieldsetConstraint(schema) { | ||
function updateConstraint(schema, data) { | ||
var _data$name; | ||
var name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; | ||
var constraint = name !== '' ? (_data$name = data[name]) !== null && _data$name !== void 0 ? _data$name : data[name] = { | ||
required: true | ||
} : {}; | ||
if (schema instanceof zod.ZodObject) { | ||
var result = {}; | ||
for (var [key, def] of Object.entries(schema.shape)) { | ||
// @ts-expect-error | ||
result[key] = inferConstraint(def); | ||
for (var key in schema.shape) { | ||
updateConstraint(schema.shape[key], data, name ? "".concat(name, ".").concat(key) : key); | ||
} | ||
return result; | ||
} | ||
if (schema instanceof zod.ZodEffects) { | ||
return resolveFieldsetConstraint(schema.innerType()); | ||
} else if (schema instanceof zod.ZodOptional) { | ||
return resolveFieldsetConstraint(schema.unwrap()); | ||
} else if (schema instanceof zod.ZodEffects) { | ||
updateConstraint(schema.innerType(), data, name); | ||
} else if (schema instanceof zod.ZodPipeline) { | ||
// FIXME: What to do with .pipe()? | ||
updateConstraint(schema._def.out, data, name); | ||
} else if (schema instanceof zod.ZodIntersection) { | ||
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, resolveFieldsetConstraint(schema._def.left)), resolveFieldsetConstraint(schema._def.right)); | ||
var leftResult = {}; | ||
var rightResult = {}; | ||
updateConstraint(schema._def.left, leftResult, name); | ||
updateConstraint(schema._def.right, rightResult, name); | ||
Object.assign(data, leftResult, rightResult); | ||
} else if (schema instanceof zod.ZodUnion || schema instanceof zod.ZodDiscriminatedUnion) { | ||
var options = schema.options; | ||
return options.map(resolveFieldsetConstraint).reduce((prev, next) => { | ||
Object.assign(data, schema.options.map(option => { | ||
var result = {}; | ||
updateConstraint(option, result, name); | ||
return result; | ||
}).reduce((prev, next) => { | ||
var list = new Set([...Object.keys(prev), ...Object.keys(next)]); | ||
var result = {}; | ||
for (var name of list) { | ||
var prevConstraint = prev[name]; | ||
var nextConstraint = next[name]; | ||
for (var _name of list) { | ||
var prevConstraint = prev[_name]; | ||
var nextConstraint = next[_name]; | ||
if (prevConstraint && nextConstraint) { | ||
result[name] = {}; | ||
var _constraint = {}; | ||
result[_name] = _constraint; | ||
for (var _key of keys) { | ||
if (typeof prevConstraint[_key] !== 'undefined' && typeof nextConstraint[_key] !== 'undefined' && prevConstraint[_key] === nextConstraint[_key]) { | ||
// @ts-expect-error | ||
result[name][_key] = prevConstraint[_key]; | ||
// @ts-expect-error Both are on the same type | ||
_constraint[_key] = prevConstraint[_key]; | ||
} | ||
} | ||
} else { | ||
result[name] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prevConstraint), nextConstraint), {}, { | ||
result[_name] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prevConstraint), nextConstraint), {}, { | ||
required: false | ||
@@ -115,9 +59,44 @@ }); | ||
return result; | ||
}); | ||
} | ||
return {}; | ||
})); | ||
} else if (name === '') { | ||
// All the cases below are not allowed on root | ||
throw new Error('Unsupported schema'); | ||
} else if (schema instanceof zod.ZodArray) { | ||
constraint.multiple = true; | ||
updateConstraint(schema.element, data, "".concat(name, "[]")); | ||
} else if (schema instanceof zod.ZodString) { | ||
if (schema.minLength !== null) { | ||
constraint.minLength = schema.minLength; | ||
} | ||
if (schema.maxLength !== null) { | ||
constraint.maxLength = schema.maxLength; | ||
} | ||
} else if (schema instanceof zod.ZodOptional) { | ||
constraint.required = false; | ||
updateConstraint(schema.unwrap(), data, name); | ||
} else if (schema instanceof zod.ZodDefault) { | ||
constraint.required = false; | ||
updateConstraint(schema.removeDefault(), data, name); | ||
} else if (schema instanceof zod.ZodNumber) { | ||
if (schema.minValue !== null) { | ||
constraint.min = schema.minValue; | ||
} | ||
if (schema.maxValue !== null) { | ||
constraint.max = schema.maxValue; | ||
} | ||
} else if (schema instanceof zod.ZodEnum) { | ||
constraint.pattern = schema.options.map(option => | ||
// To escape unsafe characters on regex | ||
option.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')).join('|'); | ||
} else if (schema instanceof zod.ZodTuple) { | ||
for (var i = 0; i < schema.items.length; i++) { | ||
updateConstraint(schema.items[i], data, "".concat(name, "[").concat(i, "]")); | ||
} | ||
} else ; | ||
} | ||
return resolveFieldsetConstraint(schema); | ||
var result = {}; | ||
updateConstraint(schema, result); | ||
return result; | ||
} | ||
exports.getConstraint = getConstraint; |
@@ -1,2 +0,2 @@ | ||
export { getConstraint as getFieldsetConstraint } from './constraint'; | ||
export { getConstraint } from './constraint'; | ||
export { parse, refine } from './parse'; |
@@ -10,4 +10,4 @@ 'use strict'; | ||
exports.getFieldsetConstraint = constraint.getConstraint; | ||
exports.getConstraint = constraint.getConstraint; | ||
exports.parse = parse.parse; | ||
exports.refine = parse.refine; |
@@ -6,3 +6,3 @@ { | ||
"license": "MIT", | ||
"version": "1.0.0-pre.0", | ||
"version": "1.0.0-pre.1", | ||
"main": "index.js", | ||
@@ -29,3 +29,3 @@ "module": "index.mjs", | ||
"peerDependencies": { | ||
"@conform-to/dom": "1.0.0-pre.0", | ||
"@conform-to/dom": "1.0.0-pre.1", | ||
"zod": "^3.21.0" | ||
@@ -32,0 +32,0 @@ }, |
@@ -1,13 +0,25 @@ | ||
import { type Submission } from '@conform-to/dom'; | ||
import { type IssueData, type output, type RefinementCtx, type ZodTypeAny, type ZodErrorMap } from 'zod'; | ||
import { type Intent, type Submission } from '@conform-to/dom'; | ||
import { type IssueData, type RefinementCtx, type ZodTypeAny, type ZodErrorMap, type input, type output, type ZodIssue } from 'zod'; | ||
export declare function parse<Schema extends ZodTypeAny>(payload: FormData | URLSearchParams, options: { | ||
schema: Schema | ((intent: string) => Schema); | ||
schema: Schema | ((intents: Array<Intent> | null) => Schema); | ||
async?: false; | ||
errorMap?: ZodErrorMap; | ||
}): Submission<output<Schema>>; | ||
}): Submission<input<Schema>, string[], output<Schema>>; | ||
export declare function parse<Schema extends ZodTypeAny, Error>(payload: FormData | URLSearchParams, options: { | ||
schema: Schema | ((intents: Array<Intent> | null) => Schema); | ||
async?: false; | ||
errorMap?: ZodErrorMap; | ||
formatError: (issues: Array<ZodIssue>) => Error; | ||
}): Submission<input<Schema>, Error, output<Schema>>; | ||
export declare function parse<Schema extends ZodTypeAny>(payload: FormData | URLSearchParams, options: { | ||
schema: Schema | ((intent: string) => Schema); | ||
schema: Schema | ((intents: Array<Intent> | null) => Schema); | ||
async: true; | ||
errorMap?: ZodErrorMap; | ||
}): Promise<Submission<output<Schema>>>; | ||
}): Promise<Submission<input<Schema>, string[], output<Schema>>>; | ||
export declare function parse<Schema extends ZodTypeAny, Error>(payload: FormData | URLSearchParams, options: { | ||
schema: Schema | ((intents: Array<Intent> | null) => Schema); | ||
async: true; | ||
errorMap?: ZodErrorMap; | ||
formatError: (issues: Array<ZodIssue>) => Error; | ||
}): Promise<Submission<input<Schema>, Error, output<Schema>>>; | ||
/** | ||
@@ -14,0 +26,0 @@ * A helper function to define a custom constraint on a superRefine check. |
51
parse.js
@@ -9,12 +9,29 @@ 'use strict'; | ||
function getError(_ref) { | ||
var { | ||
errors | ||
} = _ref; | ||
return errors.reduce((result, error) => { | ||
var _result$name; | ||
var name = dom.formatPaths(error.path); | ||
var messages = (_result$name = result[name]) !== null && _result$name !== void 0 ? _result$name : []; | ||
messages.push(error.message); | ||
result[name] = messages; | ||
function getError(zodError, formatError) { | ||
var result = {}; | ||
for (var issue of zodError.errors) { | ||
var name = dom.formatPaths(issue.path); | ||
switch (issue.message) { | ||
case '__undefined__': | ||
return null; | ||
case '__skipped__': | ||
result[name] = null; | ||
break; | ||
default: | ||
{ | ||
var _issues = result[name]; | ||
if (_issues !== null) { | ||
if (_issues) { | ||
result[name] = _issues.concat(issue); | ||
} else { | ||
result[name] = [issue]; | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
return Object.entries(result).reduce((result, _ref) => { | ||
var [name, issues] = _ref; | ||
result[name] = issues ? formatError(issues) : null; | ||
return result; | ||
@@ -25,9 +42,10 @@ }, {}); | ||
return dom.parse(payload, { | ||
resolve(payload, intent) { | ||
resolve(payload, intents) { | ||
var errorMap = options.errorMap; | ||
var schema = coercion.enableTypeCoercion(typeof options.schema === 'function' ? options.schema(intent) : options.schema); | ||
var schema = coercion.enableTypeCoercion(typeof options.schema === 'function' ? options.schema(intents) : options.schema); | ||
var resolveSubmission = result => { | ||
var _options$formatError; | ||
return { | ||
value: result.success ? result.data : null, | ||
error: !result.success ? getError(result.error) : {} | ||
error: !result.success ? getError(result.error, (_options$formatError = options.formatError) !== null && _options$formatError !== void 0 ? _options$formatError : issues => issues.map(issue => issue.message)) : {} | ||
}; | ||
@@ -54,3 +72,3 @@ }; | ||
code: zod.ZodIssueCode.custom, | ||
message: dom.VALIDATION_SKIPPED, | ||
message: '__skipped__', | ||
path: options.path | ||
@@ -67,4 +85,5 @@ }); | ||
code: zod.ZodIssueCode.custom, | ||
message: dom.VALIDATION_UNDEFINED, | ||
path: options.path | ||
message: '__undefined__', | ||
path: options.path, | ||
fatal: true | ||
}); | ||
@@ -71,0 +90,0 @@ return; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
40518
871