UNPKG

@conform-to/zod

Version:

Conform helpers for integrating with Zod

161 lines (156 loc) 6.26 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js'); var dom = require('@conform-to/dom'); var future = require('@conform-to/dom/future'); var keys = ['required', 'minLength', 'maxLength', 'min', 'max', 'step', 'multiple', 'pattern']; function getZodConstraint(schema) { var processingPaths = new Map(); var aliases = []; var result = {}; var cache = {}; function updateConstraint(schema, data) { var _data$name; var name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var processingPath = processingPaths.get(schema); if (typeof processingPath !== 'undefined') { aliases.push({ from: dom.getPaths(name), to: dom.getPaths(processingPath) }); return; } processingPaths.set(schema, name); var constraint = name !== '' ? (_data$name = data[name]) !== null && _data$name !== void 0 ? _data$name : data[name] = { required: true } : {}; var def = schema['_def']; if (def.typeName === 'ZodObject') { for (var key in def.shape()) { updateConstraint(def.shape()[key], data, name ? "".concat(name, ".").concat(key) : key); } } else if (def.typeName === 'ZodEffects') { updateConstraint(def.schema, data, name); } else if (def.typeName === 'ZodPipeline') { // FIXME: What to do with .pipe()? updateConstraint(def.out, data, name); } else if (def.typeName === 'ZodIntersection') { var leftResult = {}; var rightResult = {}; updateConstraint(def.left, leftResult, name); updateConstraint(def.right, rightResult, name); Object.assign(data, leftResult, rightResult); } else if (def.typeName === 'ZodUnion' || def.typeName === 'ZodDiscriminatedUnion') { Object.assign(data, def.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]; if (prevConstraint && nextConstraint) { 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 Both are on the same type _constraint[_key] = prevConstraint[_key]; } } } else { result[_name] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prevConstraint), nextConstraint), {}, { required: false }); } } return result; })); } else if (name === '') { // All the cases below are not allowed on root throw new Error('Unsupported schema'); } else if (def.typeName === 'ZodArray') { constraint.multiple = true; updateConstraint(def.type, data, "".concat(name, "[]")); } else if (def.typeName === 'ZodString') { var _schema = schema; if (_schema.minLength !== null) { var _schema$minLength; constraint.minLength = (_schema$minLength = _schema.minLength) !== null && _schema$minLength !== void 0 ? _schema$minLength : undefined; } if (_schema.maxLength !== null) { constraint.maxLength = _schema.maxLength; } var regexChecks = def.checks.filter(check => check.kind === 'regex'); if (regexChecks.length > 0) { var pattern = future.serializeHtmlPattern(regexChecks.map(c => c.regex)); if (pattern) { constraint.pattern = pattern; } } } else if (def.typeName === 'ZodOptional') { constraint.required = false; updateConstraint(def.innerType, data, name); } else if (def.typeName === 'ZodNullable') { updateConstraint(def.innerType, data, name); } else if (def.typeName === 'ZodDefault') { constraint.required = false; updateConstraint(def.innerType, data, name); } else if (def.typeName === 'ZodNumber') { var _schema2 = schema; if (_schema2.minValue !== null) { constraint.min = _schema2.minValue; } if (_schema2.maxValue !== null) { constraint.max = _schema2.maxValue; } } else if (def.typeName === 'ZodEnum') { constraint.pattern = def.values.map(option => // To escape unsafe characters on regex option.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')).join('|'); } else if (def.typeName === 'ZodTuple') { for (var i = 0; i < def.items.length; i++) { updateConstraint(def.items[i], data, "".concat(name, "[").concat(i, "]")); } } else if (def.typeName === 'ZodLazy') { var inner = def.getter(); updateConstraint(inner, data, name); } processingPaths.delete(schema); } function resolve(nameOrSegments) { var name = typeof nameOrSegments === 'string' ? nameOrSegments : dom.formatPaths(nameOrSegments); if (name in result) { return result[name]; } var segments = typeof nameOrSegments === 'string' ? dom.getPaths(nameOrSegments) : nameOrSegments; for (var alias of aliases) { var tail = dom.getRelativePath(segments, alias.from); if (tail !== null && tail.length > 0) { return resolve([...alias.to, ...tail]); } } for (var i = segments.length - 1; i >= 0; i--) { if (typeof segments[i] === 'number') { segments[i] = ''; return resolve(segments); } } return undefined; } updateConstraint(schema, result); return new Proxy(result, { get(target, name, receiver) { if (typeof name !== 'string') { return Reflect.get(target, name, receiver); } if (name in cache) { return cache[name]; } return cache[name] = resolve(name); } }); } exports.getZodConstraint = getZodConstraint;