UNPKG

remix-params-helper

Version:

This package makes it simple to use Zod with standard URLSearchParams and FormData which are typically used in Remix apps.

236 lines (235 loc) 7.54 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var helper_exports = {}; __export(helper_exports, { getFormData: () => getFormData, getFormDataOrFail: () => getFormDataOrFail, getParams: () => getParams, getParamsOrFail: () => getParamsOrFail, getSearchParams: () => getSearchParams, getSearchParamsOrFail: () => getSearchParamsOrFail, useFormInputProps: () => useFormInputProps }); module.exports = __toCommonJS(helper_exports); var import_zod = require("zod"); function isIterable(maybeIterable) { return Symbol.iterator in Object(maybeIterable); } function parseParams(o, schema, key, value) { let shape = schema; while (shape instanceof import_zod.ZodObject || shape instanceof import_zod.ZodEffects) { shape = shape instanceof import_zod.ZodObject ? shape.shape : shape instanceof import_zod.ZodEffects ? shape._def.schema : null; if (shape === null) { throw new Error(`Could not find shape for key ${key}`); } } if (key.includes(".")) { let [parentProp, ...rest] = key.split("."); o[parentProp] = o[parentProp] ?? {}; parseParams(o[parentProp], shape[parentProp], rest.join("."), value); return; } let isArray = false; if (key.includes("[]")) { isArray = true; key = key.replace("[]", ""); } const def = shape[key]; if (def) { processDef(def, o, key, value); } } function getParamsInternal(params, schema) { let o = {}; let entries = []; if (isIterable(params)) { entries = Array.from(params); } else { entries = Object.entries(params); } for (let [key, value] of entries) { if (value === "") { continue; } parseParams(o, schema, key, value); } const result = schema.safeParse(o); if (result.success) { return { success: true, data: result.data, errors: void 0 }; } else { let errors = {}; const addError = (key, message) => { if (!errors.hasOwnProperty(key)) { errors[key] = message; } else { if (!Array.isArray(errors[key])) { errors[key] = [errors[key]]; } errors[key].push(message); } }; for (let issue of result.error.issues) { const { message, path, code, expected, received } = issue; const [key, index] = path; let value = o[key]; let prop = key; if (index !== void 0) { value = value[index]; prop = `${key}[${index}]`; } addError(key, message); } return { success: false, data: void 0, errors }; } } function getParams(params, schema) { return getParamsInternal(params, schema); } function getSearchParams(request, schema) { let url = new URL(request.url); return getParamsInternal(url.searchParams, schema); } async function getFormData(request, schema) { let data = await request.formData(); return getParamsInternal(data, schema); } function getParamsOrFail(params, schema) { const result = getParamsInternal(params, schema); if (!result.success) { throw new Error(JSON.stringify(result.errors)); } return result.data; } function getSearchParamsOrFail(request, schema) { let url = new URL(request.url); const result = getParamsInternal(url.searchParams, schema); if (!result.success) { throw new Error(JSON.stringify(result.errors)); } return result.data; } async function getFormDataOrFail(request, schema) { let data = await request.formData(); const result = getParamsInternal(data, schema); if (!result.success) { throw new Error(JSON.stringify(result.errors)); } return result.data; } function useFormInputProps(schema, options = {}) { const shape = schema.shape; const defaultOptions = options; return function props(key, options2 = {}) { options2 = { ...defaultOptions, ...options2 }; const def = shape[key]; if (!def) { throw new Error(`no such key: ${key}`); } return getInputProps(key, def); }; } function processDef(def, o, key, value) { let parsedValue; if (def instanceof import_zod.ZodString || def instanceof import_zod.ZodLiteral) { parsedValue = value; } else if (def instanceof import_zod.ZodNumber) { const num = Number(value); parsedValue = isNaN(num) ? value : num; } else if (def instanceof import_zod.ZodDate) { const date = Date.parse(value); parsedValue = isNaN(date) ? value : new Date(date); } else if (def instanceof import_zod.ZodBoolean) { parsedValue = value === "true" ? true : value === "false" ? false : Boolean(value); } else if (def instanceof import_zod.ZodNativeEnum || def instanceof import_zod.ZodEnum) { parsedValue = value; } else if (def instanceof import_zod.ZodOptional || def instanceof import_zod.ZodDefault) { processDef(def._def.innerType, o, key, value); return; } else if (def instanceof import_zod.ZodArray) { if (o[key] === void 0) { o[key] = []; } processDef(def.element, o, key, value); return; } else if (def instanceof import_zod.ZodEffects) { processDef(def._def.schema, o, key, value); return; } else { throw new Error(`Unexpected type ${def._def.typeName} for key ${key}`); } if (Array.isArray(o[key])) { o[key].push(parsedValue); } else { o[key] = parsedValue; } } function getInputProps(name, def) { let type = "text"; let min, max, minlength, maxlength, pattern; if (def instanceof import_zod.ZodString) { if (def.isEmail) { type = "email"; } else if (def.isURL) { type = "url"; } minlength = def.minLength ?? void 0; maxlength = def.maxLength ?? void 0; const check = def._def.checks.find((c) => c.kind === "regex"); pattern = check ? check.regex.source : void 0; } else if (def instanceof import_zod.ZodNumber) { type = "number"; min = def.minValue ?? void 0; max = def.maxValue ?? void 0; } else if (def instanceof import_zod.ZodBoolean) { type = "checkbox"; } else if (def instanceof import_zod.ZodDate) { type = "date"; } else if (def instanceof import_zod.ZodArray) { return getInputProps(name, def.element); } else if (def instanceof import_zod.ZodOptional) { return getInputProps(name, def.unwrap()); } let inputProps = { name, type }; if (!def.isOptional()) inputProps.required = true; if (min) inputProps.min = min; if (max) inputProps.max = max; if (minlength && Number.isFinite(minlength)) inputProps.minLength = minlength; if (maxlength && Number.isFinite(maxlength)) inputProps.maxLength = maxlength; if (pattern) inputProps.pattern = pattern; return inputProps; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { getFormData, getFormDataOrFail, getParams, getParamsOrFail, getSearchParams, getSearchParamsOrFail, useFormInputProps });