Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@esmj/schema

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@esmj/schema - npm Package Compare versions

Comparing version
0.4.0
to
0.5.0
+1
dist/array.cjs
'use strict';var P={abortEarly:true};function l(e,o){if(!o)return e;let i=e?.cause?.key?`${o}.${e.cause.key}`:`${o}`;return {message:`Error parsing key "${i}": ${e.message}`,cause:{key:i}}}function g(e,o,i){!e.errors||e.errors.length===0||e.errors.forEach(u=>{let c=l(u,i);o.push(c);});}function S(e){return {...P,...e}}var k=e=>typeof e=="string"||e instanceof String,A=e=>typeof e=="number"||e instanceof Number,w=e=>e===true||e===false,E=e=>e instanceof Date&&!Number.isNaN(e.getTime()),_=e=>Array.isArray(e),O=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),R={object(e,o){let i=y(O,{...o,type:"object"});return i._getDescription=()=>`object({ ${Object.entries(e).map(([c,s])=>`${c}: ${s._getDescription()}`).join(", ")} })`,h(i,"_parse",(u,c,s)=>{let t=u(c,s),{abortEarly:r}=S(s);if(t.success===false)return t;let n={},a=[];for(let p in e){let f=e[p]._parse(t.data[p],s);if(f.success)n[p]=f.data;else {if(f=f,r!==false){let m=l(f.error,p);return {success:false,error:m,errors:[m]}}g(f,a,p);}}return a.length>0?{success:false,error:a[0],errors:a}:{success:true,data:n}}),i},string(e){return y(k,{...e,type:"string"})},number(e){return y(A,{...e,type:"number"})},boolean(e){return y(w,{...e,type:"boolean"})},date(e){return y(E,{...e,type:"date"})},enum(e,o){let i=t=>e.includes(t),u=t=>`Invalid ${c} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${t}".`,c="enum",s=y(i,{message:u,...o,type:c});return s._getDescription=()=>`enum(${e.map(t=>`"${t}"`).join(" | ")})`,s},array(e,o){let i=y(_,{...o,type:"array"});return i._getDescription=()=>`array(${e._getDescription()})`,h(i,"_parse",(u,c,s)=>{let t=u(c,s),{abortEarly:r}=S(s);if(t.success===false)return t;let n=[],a=[];for(let p=0;p<t.data.length;p++){let f=e._parse(t.data[p],s);if(f.success)n.push(f.data);else {if(f=f,r!==false){let m=l(f.error,p);return {success:false,error:m,errors:[m]}}g(f,a,p);}}return a.length>0?{success:false,error:a[0],errors:a}:{success:true,data:n}}),i},any(){return y(()=>true)},preprocess(e,o){return h(o,"_parse",(i,u)=>(u=e(u),i(u))),o},union(e,o){return y(s=>{for(let t=0;t<e.length;t++){let r=e[t]._parse(s);if(r.success)return r}return false},{message:s=>`Invalid union value. Expected the value to match one of the schemas:${e.map((t,r)=>` ${r+1}. ${t._getDescription()}`).join(",")} but received "${typeof s}" with value: ${O(s)?JSON.stringify(s):`"${s}"`}`,...o,type:"union"})}};function b(e){return o=>`The value "${o}" must be type of ${e} but is type of "${typeof o}".`}function h(e,o,i){let u=e[o];e[o]=(...c)=>i(u,...c);}function y(e,{type:o="any",name:i,message:u}={}){u=u||b(o);let c={name:i,message:u,type:o},s={_getName(){return i},_getType(){return o},_getDescription(){return this._getName()??this._getType()},_parse(t,r){let n=e(t);if(n===true)return {success:true,data:t};if(typeof n=="object"&&n?.success===true)return n;let a={message:typeof u=="function"?u(t):u};return {success:false,error:a,errors:[a]}},parse(t,r){let n=s._parse(t,r);if(!n.success)throw n=n,new Error(n.error.message,{cause:n.error.cause});return n.data},safeParse(t,r){return s._parse(t,r)},transform(t){return h(this,"_parse",(r,n,a)=>{let p=r(n,a);return p.success&&(p.data=t(p.data)),p}),this},optional(){return h(this,"_parse",(t,r,n)=>{let a=t(r,n);return !a.success&&r===void 0&&(a.data=void 0,a.success=true),a}),this},nullable(){return h(this,"_parse",(t,r,n)=>{let a=t(r,n);return !a.success&&r===null&&(a.data=null,a.success=true),a}),this},nullish(){return h(this,"_parse",(t,r,n)=>{let a=t(r,n);return !a.success&&r==null&&(a.success=true,a.data=r),a}),this},default(t){return h(this,"_parse",(r,n,a)=>(n===void 0&&(n=t,n=typeof t=="function"?t():t),r(n,a))),this},pipe(t){return h(this,"_parse",(r,n,a)=>{let p=r(n,a);return p.success?t._parse(p.data,a):p}),this},refine(t,{message:r,type:n}={}){return n&&(r=r||b(n),o=n),h(this,"_parse",(a,p,f)=>{let m=a(p,f);S(f);if(!m.success)return m;let I=t(m.data);if(I===true||typeof I=="object"&&I?.success===true)return m;let T={message:typeof r=="function"?r(p):r};return {success:false,error:T,errors:[T]}}),this}};return d.length>0?d.reduce((t,r)=>r(t,e,c)??t,s):s}var d=[];function x(e){d.push(e);}x((e,o,i)=>{if(i?.type==="array"){let u=e;u.min=function(c,{message:s}={}){return this.refine(t=>t.length>=c,{message:s||`Array must contain at least ${c} items.`})},u.max=function(c,{message:s}={}){return this.refine(t=>t.length<=c,{message:s||`Array must contain at most ${c} items.`})},u.length=function(c,{message:s}={}){return this.refine(t=>t.length===c,{message:s||`Array must contain exactly ${c} items.`})},u.nonEmpty=function({message:c}={}){return this.refine(s=>s.length>0,{message:c||"Array must not be empty."})},u.unique=function({message:c}={}){return this.refine(s=>{let t=new Set;try{return s.every(r=>{let n=JSON.stringify(r);return t.has(n)?!1:(t.add(n),!0)})}catch{return new Set(s).size===s.length}},{message:c||"Array items must be unique."})},u.sort=function(){return this.transform(c=>[...c].sort())},u.reverse=function(){return this.transform(c=>[...c].reverse())};}return e});exports.extend=x;exports.hookOriginal=h;exports.s=R;
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.cjs';
declare module './index.ts' {
interface ArraySchemaInterface<T extends SchemaType> {
min(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
max(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
length(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
nonEmpty(options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
unique(options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
sort(): ArraySchemaInterface<T>;
reverse(): ArraySchemaInterface<T>;
}
}
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.js';
declare module './index.ts' {
interface ArraySchemaInterface<T extends SchemaType> {
min(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
max(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
length(length: number, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
nonEmpty(options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
unique(options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
sort(): ArraySchemaInterface<T>;
reverse(): ArraySchemaInterface<T>;
}
}
import'./chunk-JFGD5PND.js';export{c as extend,b as hookOriginal,a as s}from'./chunk-5ARMWSHU.js';
var P={abortEarly:true};function d(e,s){if(!s)return e;let o=e?.cause?.key?`${s}.${e.cause.key}`:`${s}`;return {message:`Error parsing key "${o}": ${e.message}`,cause:{key:o}}}function b(e,s,o){!e.errors||e.errors.length===0||e.errors.forEach(i=>{let f=d(i,o);s.push(f);});}function y(e){return {...P,...e}}var x=e=>typeof e=="string"||e instanceof String,k=e=>typeof e=="number"||e instanceof Number,w=e=>e===true||e===false,E=e=>e instanceof Date&&!Number.isNaN(e.getTime()),_=e=>Array.isArray(e),g=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),R={object(e,s){let o=l(g,{...s,type:"object"});return o._getDescription=()=>`object({ ${Object.entries(e).map(([f,c])=>`${f}: ${c._getDescription()}`).join(", ")} })`,h(o,"_parse",(i,f,c)=>{let t=i(f,c),{abortEarly:r}=y(c);if(t.success===false)return t;let a={},n=[];for(let u in e){let p=e[u]._parse(t.data[u],c);if(p.success)a[u]=p.data;else {if(p=p,r!==false){let m=d(p.error,u);return {success:false,error:m,errors:[m]}}b(p,n,u);}}return n.length>0?{success:false,error:n[0],errors:n}:{success:true,data:a}}),o},string(e){return l(x,{...e,type:"string"})},number(e){return l(k,{...e,type:"number"})},boolean(e){return l(w,{...e,type:"boolean"})},date(e){return l(E,{...e,type:"date"})},enum(e,s){let o=t=>e.includes(t),i=t=>`Invalid ${f} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${t}".`,f="enum",c=l(o,{message:i,...s,type:f});return c._getDescription=()=>`enum(${e.map(t=>`"${t}"`).join(" | ")})`,c},array(e,s){let o=l(_,{...s,type:"array"});return o._getDescription=()=>`array(${e._getDescription()})`,h(o,"_parse",(i,f,c)=>{let t=i(f,c),{abortEarly:r}=y(c);if(t.success===false)return t;let a=[],n=[];for(let u=0;u<t.data.length;u++){let p=e._parse(t.data[u],c);if(p.success)a.push(p.data);else {if(p=p,r!==false){let m=d(p.error,u);return {success:false,error:m,errors:[m]}}b(p,n,u);}}return n.length>0?{success:false,error:n[0],errors:n}:{success:true,data:a}}),o},any(){return l(()=>true)},preprocess(e,s){return h(s,"_parse",(o,i)=>(i=e(i),o(i))),s},union(e,s){return l(c=>{for(let t=0;t<e.length;t++){let r=e[t]._parse(c);if(r.success)return r}return false},{message:c=>`Invalid union value. Expected the value to match one of the schemas:${e.map((t,r)=>` ${r+1}. ${t._getDescription()}`).join(",")} but received "${typeof c}" with value: ${g(c)?JSON.stringify(c):`"${c}"`}`,...s,type:"union"})}};function O(e){return s=>`The value "${s}" must be type of ${e} but is type of "${typeof s}".`}function h(e,s,o){let i=e[s];e[s]=(...f)=>o(i,...f);}function l(e,{type:s="any",name:o,message:i}={}){i=i||O(s);let f={name:o,message:i,type:s},c={_getName(){return o},_getType(){return s},_getDescription(){return this._getName()??this._getType()},_parse(t,r){let a=e(t);if(a===true)return {success:true,data:t};if(typeof a=="object"&&a?.success===true)return a;let n={message:typeof i=="function"?i(t):i};return {success:false,error:n,errors:[n]}},parse(t,r){let a=c._parse(t,r);if(!a.success)throw a=a,new Error(a.error.message,{cause:a.error.cause});return a.data},safeParse(t,r){return c._parse(t,r)},transform(t){return h(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success&&(u.data=t(u.data)),u}),this},optional(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r===void 0&&(n.data=void 0,n.success=true),n}),this},nullable(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r===null&&(n.data=null,n.success=true),n}),this},nullish(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r==null&&(n.success=true,n.data=r),n}),this},default(t){return h(this,"_parse",(r,a,n)=>(a===void 0&&(a=t,a=typeof t=="function"?t():t),r(a,n))),this},pipe(t){return h(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success?t._parse(u.data,n):u}),this},refine(t,{message:r,type:a}={}){return a&&(r=r||O(a),s=a),h(this,"_parse",(n,u,p)=>{let m=n(u,p);y(p);if(!m.success)return m;let I=t(m.data);if(I===true||typeof I=="object"&&I?.success===true)return m;let T={message:typeof r=="function"?r(u):r};return {success:false,error:T,errors:[T]}}),this}};return S.length>0?S.reduce((t,r)=>r(t,e,f)??t,c):c}var S=[];function $(e){S.push(e);}export{R as a,h as b,$ as c};
import {c}from'./chunk-5ARMWSHU.js';c((i,s,c)=>{if(c?.type==="string"){let r=i;r.min=function(t,{message:n}={}){return this.refine(e=>e.length>=t,{message:n||(e=>`String must be at least ${t} characters long (received ${e.length} characters: "${e}")`)})},r.max=function(t,{message:n}={}){return this.refine(e=>e.length<=t,{message:n||(e=>`String must be at most ${t} characters long (received ${e.length} characters: "${e}")`)})},r.length=function(t,{message:n}={}){return this.refine(e=>e.length===t,{message:n||(e=>`String must be exactly ${t} characters long (received ${e.length} characters: "${e}")`)})},r.nonEmpty=function({message:t}={}){return this.refine(n=>n.length>0,{message:t||"String must not be empty (received empty string)"})},r.startsWith=function(t,{message:n}={}){return this.refine(e=>e.startsWith(t),{message:n||(e=>`String must start with "${t}" (received: "${e}")`)})},r.endsWith=function(t,{message:n}={}){return this.refine(e=>e.endsWith(t),{message:n||(e=>`String must end with "${t}" (received: "${e}")`)})},r.includes=function(t,{message:n}={}){return this.refine(e=>e.includes(t),{message:n||(e=>`String must include "${t}" (received: "${e}")`)})},r.toLowerCase=function(){return this.transform(t=>t.toLowerCase())},r.toUpperCase=function(){return this.transform(t=>t.toUpperCase())},r.trim=function(){return this.transform(t=>t.trim())},r.padStart=function(t,n=" "){return this.transform(e=>e.padStart(t,n))},r.padEnd=function(t,n=" "){return this.transform(e=>e.padEnd(t,n))},r.replace=function(t,n){return this.transform(e=>e.replace(t,n))};}return i});
import {c}from'./chunk-5ARMWSHU.js';c((a,o,m)=>{if(m?.type==="array"){let r=a;r.min=function(e,{message:t}={}){return this.refine(n=>n.length>=e,{message:t||`Array must contain at least ${e} items.`})},r.max=function(e,{message:t}={}){return this.refine(n=>n.length<=e,{message:t||`Array must contain at most ${e} items.`})},r.length=function(e,{message:t}={}){return this.refine(n=>n.length===e,{message:t||`Array must contain exactly ${e} items.`})},r.nonEmpty=function({message:e}={}){return this.refine(t=>t.length>0,{message:e||"Array must not be empty."})},r.unique=function({message:e}={}){return this.refine(t=>{let n=new Set;try{return t.every(c=>{let s=JSON.stringify(c);return n.has(s)?!1:(n.add(s),!0)})}catch{return new Set(t).size===t.length}},{message:e||"Array items must be unique."})},r.sort=function(){return this.transform(e=>[...e].sort())},r.reverse=function(){return this.transform(e=>[...e].reverse())};}return a});
import {c}from'./chunk-5ARMWSHU.js';c((i,c,m)=>{if(m?.type==="number"){let n=i;n.min=function(e,{message:t}={}){return this.refine(r=>r>=e,{message:t||`Number must be greater than or equal to ${e}.`})},n.max=function(e,{message:t}={}){return this.refine(r=>r<=e,{message:t||`Number must be less than or equal to ${e}.`})},n.positive=function({message:e}={}){return this.refine(t=>t>0,{message:e||"Number must be positive."})},n.negative=function({message:e}={}){return this.refine(t=>t<0,{message:e||"Number must be negative."})},n.int=function({message:e}={}){return this.refine(t=>Number.isInteger(t),{message:e||"Number must be an integer."})},n.float=function({message:e}={}){return this.refine(t=>Number.isFinite(t)&&!Number.isInteger(t),{message:e||"Number must be a floating point (non-integer)."})},n.multipleOf=function(e,{message:t}={}){return this.refine(r=>r%e===0,{message:t||`Number must be a multiple of ${e}.`})},n.finite=function({message:e}={}){return this.refine(t=>Number.isFinite(t),{message:e||"Number must be finite."})};}return i});
'use strict';var P={abortEarly:true};function y(r,o){if(!o)return r;let u=r?.cause?.key?`${o}.${r.cause.key}`:`${o}`;return {message:`Error parsing key "${u}": ${r.message}`,cause:{key:u}}}function O(r,o,u){!r.errors||r.errors.length===0||r.errors.forEach(a=>{let t=y(a,u);o.push(t);});}function d(r){return {...P,...r}}var $=r=>typeof r=="string"||r instanceof String,N=r=>typeof r=="number"||r instanceof Number,k=r=>r===true||r===false,w=r=>r instanceof Date&&!Number.isNaN(r.getTime()),E=r=>Array.isArray(r),T=r=>typeof r=="object"&&r!==null&&!Array.isArray(r),D={object(r,o){let u=S(T,{...o,type:"object"});return u._getDescription=()=>`object({ ${Object.entries(r).map(([t,n])=>`${t}: ${n._getDescription()}`).join(", ")} })`,h(u,"_parse",(a,t,n)=>{let e=a(t,n),{abortEarly:s}=d(n);if(e.success===false)return e;let c={},i=[];for(let m in r){let p=r[m]._parse(e.data[m],n);if(p.success)c[m]=p.data;else {if(p=p,s!==false){let f=y(p.error,m);return {success:false,error:f,errors:[f]}}O(p,i,m);}}return i.length>0?{success:false,error:i[0],errors:i}:{success:true,data:c}}),u},string(r){return S($,{...r,type:"string"})},number(r){return S(N,{...r,type:"number"})},boolean(r){return S(k,{...r,type:"boolean"})},date(r){return S(w,{...r,type:"date"})},enum(r,o){let u=e=>r.includes(e),a=e=>`Invalid ${t} value. Expected ${r.map(s=>`"${s}"`).join(" | ")}, received "${e}".`,t="enum",n=S(u,{message:a,...o,type:t});return n._getDescription=()=>`enum(${r.map(e=>`"${e}"`).join(" | ")})`,n},array(r,o){let u=S(E,{...o,type:"array"});return u._getDescription=()=>`array(${r._getDescription()})`,h(u,"_parse",(a,t,n)=>{let e=a(t,n),{abortEarly:s}=d(n);if(e.success===false)return e;let c=[],i=[];for(let m=0;m<e.data.length;m++){let p=r._parse(e.data[m],n);if(p.success)c.push(p.data);else {if(p=p,s!==false){let f=y(p.error,m);return {success:false,error:f,errors:[f]}}O(p,i,m);}}return i.length>0?{success:false,error:i[0],errors:i}:{success:true,data:c}}),u},any(){return S(()=>true)},preprocess(r,o){return h(o,"_parse",(u,a)=>(a=r(a),u(a))),o},union(r,o){return S(n=>{for(let e=0;e<r.length;e++){let s=r[e]._parse(n);if(s.success)return s}return false},{message:n=>`Invalid union value. Expected the value to match one of the schemas:${r.map((e,s)=>` ${s+1}. ${e._getDescription()}`).join(",")} but received "${typeof n}" with value: ${T(n)?JSON.stringify(n):`"${n}"`}`,...o,type:"union"})}};function x(r){return o=>`The value "${o}" must be type of ${r} but is type of "${typeof o}".`}function h(r,o,u){let a=r[o];r[o]=(...t)=>u(a,...t);}function S(r,{type:o="any",name:u,message:a}={}){a=a||x(o);let t={name:u,message:a,type:o},n={_getName(){return u},_getType(){return o},_getDescription(){return this._getName()??this._getType()},_parse(e,s){let c=r(e);if(c===true)return {success:true,data:e};if(typeof c=="object"&&c?.success===true)return c;let i={message:typeof a=="function"?a(e):a};return {success:false,error:i,errors:[i]}},parse(e,s){let c=n._parse(e,s);if(!c.success)throw c=c,new Error(c.error.message,{cause:c.error.cause});return c.data},safeParse(e,s){return n._parse(e,s)},transform(e){return h(this,"_parse",(s,c,i)=>{let m=s(c,i);return m.success&&(m.data=e(m.data)),m}),this},optional(){return h(this,"_parse",(e,s,c)=>{let i=e(s,c);return !i.success&&s===void 0&&(i.data=void 0,i.success=true),i}),this},nullable(){return h(this,"_parse",(e,s,c)=>{let i=e(s,c);return !i.success&&s===null&&(i.data=null,i.success=true),i}),this},nullish(){return h(this,"_parse",(e,s,c)=>{let i=e(s,c);return !i.success&&s==null&&(i.success=true,i.data=s),i}),this},default(e){return h(this,"_parse",(s,c,i)=>(c===void 0&&(c=e,c=typeof e=="function"?e():e),s(c,i))),this},pipe(e){return h(this,"_parse",(s,c,i)=>{let m=s(c,i);return m.success?e._parse(m.data,i):m}),this},refine(e,{message:s,type:c}={}){return c&&(s=s||x(c),o=c),h(this,"_parse",(i,m,p)=>{let f=i(m,p);d(p);if(!f.success)return f;let l=e(f.data);if(l===true||typeof l=="object"&&l?.success===true)return f;let b={message:typeof s=="function"?s(m):s};return {success:false,error:b,errors:[b]}}),this}};return g.length>0?g.reduce((e,s)=>s(e,r,t)??e,n):n}var g=[];function I(r){g.push(r);}I((r,o,u)=>{if(u?.type==="string"){let a=r;a.min=function(t,{message:n}={}){return this.refine(e=>e.length>=t,{message:n||(e=>`String must be at least ${t} characters long (received ${e.length} characters: "${e}")`)})},a.max=function(t,{message:n}={}){return this.refine(e=>e.length<=t,{message:n||(e=>`String must be at most ${t} characters long (received ${e.length} characters: "${e}")`)})},a.length=function(t,{message:n}={}){return this.refine(e=>e.length===t,{message:n||(e=>`String must be exactly ${t} characters long (received ${e.length} characters: "${e}")`)})},a.nonEmpty=function({message:t}={}){return this.refine(n=>n.length>0,{message:t||"String must not be empty (received empty string)"})},a.startsWith=function(t,{message:n}={}){return this.refine(e=>e.startsWith(t),{message:n||(e=>`String must start with "${t}" (received: "${e}")`)})},a.endsWith=function(t,{message:n}={}){return this.refine(e=>e.endsWith(t),{message:n||(e=>`String must end with "${t}" (received: "${e}")`)})},a.includes=function(t,{message:n}={}){return this.refine(e=>e.includes(t),{message:n||(e=>`String must include "${t}" (received: "${e}")`)})},a.toLowerCase=function(){return this.transform(t=>t.toLowerCase())},a.toUpperCase=function(){return this.transform(t=>t.toUpperCase())},a.trim=function(){return this.transform(t=>t.trim())},a.padStart=function(t,n=" "){return this.transform(e=>e.padStart(t,n))},a.padEnd=function(t,n=" "){return this.transform(e=>e.padEnd(t,n))},a.replace=function(t,n){return this.transform(e=>e.replace(t,n))};}return r});I((r,o,u)=>{if(u?.type==="number"){let a=r;a.min=function(t,{message:n}={}){return this.refine(e=>e>=t,{message:n||`Number must be greater than or equal to ${t}.`})},a.max=function(t,{message:n}={}){return this.refine(e=>e<=t,{message:n||`Number must be less than or equal to ${t}.`})},a.positive=function({message:t}={}){return this.refine(n=>n>0,{message:t||"Number must be positive."})},a.negative=function({message:t}={}){return this.refine(n=>n<0,{message:t||"Number must be negative."})},a.int=function({message:t}={}){return this.refine(n=>Number.isInteger(n),{message:t||"Number must be an integer."})},a.float=function({message:t}={}){return this.refine(n=>Number.isFinite(n)&&!Number.isInteger(n),{message:t||"Number must be a floating point (non-integer)."})},a.multipleOf=function(t,{message:n}={}){return this.refine(e=>e%t===0,{message:n||`Number must be a multiple of ${t}.`})},a.finite=function({message:t}={}){return this.refine(n=>Number.isFinite(n),{message:t||"Number must be finite."})};}return r});I((r,o,u)=>{if(u?.type==="array"){let a=r;a.min=function(t,{message:n}={}){return this.refine(e=>e.length>=t,{message:n||`Array must contain at least ${t} items.`})},a.max=function(t,{message:n}={}){return this.refine(e=>e.length<=t,{message:n||`Array must contain at most ${t} items.`})},a.length=function(t,{message:n}={}){return this.refine(e=>e.length===t,{message:n||`Array must contain exactly ${t} items.`})},a.nonEmpty=function({message:t}={}){return this.refine(n=>n.length>0,{message:t||"Array must not be empty."})},a.unique=function({message:t}={}){return this.refine(n=>{let e=new Set;try{return n.every(s=>{let c=JSON.stringify(s);return e.has(c)?!1:(e.add(c),!0)})}catch{return new Set(n).size===n.length}},{message:t||"Array items must be unique."})},a.sort=function(){return this.transform(t=>[...t].sort())},a.reverse=function(){return this.transform(t=>[...t].reverse())};}return r});exports.extend=I;exports.hookOriginal=h;exports.s=D;
import './string.cjs';
import './number.cjs';
import './array.cjs';
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.cjs';
import './string.js';
import './number.js';
import './array.js';
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.js';
import'./chunk-JFGD5PND.js';import'./chunk-QEBUM44M.js';import'./chunk-6ABUMTDR.js';export{c as extend,b as hookOriginal,a as s}from'./chunk-5ARMWSHU.js';
'use strict';var P={abortEarly:true};function d(e,s){if(!s)return e;let o=e?.cause?.key?`${s}.${e.cause.key}`:`${s}`;return {message:`Error parsing key "${o}": ${e.message}`,cause:{key:o}}}function b(e,s,o){!e.errors||e.errors.length===0||e.errors.forEach(i=>{let f=d(i,o);s.push(f);});}function y(e){return {...P,...e}}var x=e=>typeof e=="string"||e instanceof String,k=e=>typeof e=="number"||e instanceof Number,w=e=>e===true||e===false,E=e=>e instanceof Date&&!Number.isNaN(e.getTime()),_=e=>Array.isArray(e),g=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),R={object(e,s){let o=l(g,{...s,type:"object"});return o._getDescription=()=>`object({ ${Object.entries(e).map(([f,c])=>`${f}: ${c._getDescription()}`).join(", ")} })`,h(o,"_parse",(i,f,c)=>{let t=i(f,c),{abortEarly:r}=y(c);if(t.success===false)return t;let a={},n=[];for(let u in e){let p=e[u]._parse(t.data[u],c);if(p.success)a[u]=p.data;else {if(p=p,r!==false){let m=d(p.error,u);return {success:false,error:m,errors:[m]}}b(p,n,u);}}return n.length>0?{success:false,error:n[0],errors:n}:{success:true,data:a}}),o},string(e){return l(x,{...e,type:"string"})},number(e){return l(k,{...e,type:"number"})},boolean(e){return l(w,{...e,type:"boolean"})},date(e){return l(E,{...e,type:"date"})},enum(e,s){let o=t=>e.includes(t),i=t=>`Invalid ${f} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${t}".`,f="enum",c=l(o,{message:i,...s,type:f});return c._getDescription=()=>`enum(${e.map(t=>`"${t}"`).join(" | ")})`,c},array(e,s){let o=l(_,{...s,type:"array"});return o._getDescription=()=>`array(${e._getDescription()})`,h(o,"_parse",(i,f,c)=>{let t=i(f,c),{abortEarly:r}=y(c);if(t.success===false)return t;let a=[],n=[];for(let u=0;u<t.data.length;u++){let p=e._parse(t.data[u],c);if(p.success)a.push(p.data);else {if(p=p,r!==false){let m=d(p.error,u);return {success:false,error:m,errors:[m]}}b(p,n,u);}}return n.length>0?{success:false,error:n[0],errors:n}:{success:true,data:a}}),o},any(){return l(()=>true)},preprocess(e,s){return h(s,"_parse",(o,i)=>(i=e(i),o(i))),s},union(e,s){return l(c=>{for(let t=0;t<e.length;t++){let r=e[t]._parse(c);if(r.success)return r}return false},{message:c=>`Invalid union value. Expected the value to match one of the schemas:${e.map((t,r)=>` ${r+1}. ${t._getDescription()}`).join(",")} but received "${typeof c}" with value: ${g(c)?JSON.stringify(c):`"${c}"`}`,...s,type:"union"})}};function O(e){return s=>`The value "${s}" must be type of ${e} but is type of "${typeof s}".`}function h(e,s,o){let i=e[s];e[s]=(...f)=>o(i,...f);}function l(e,{type:s="any",name:o,message:i}={}){i=i||O(s);let f={name:o,message:i,type:s},c={_getName(){return o},_getType(){return s},_getDescription(){return this._getName()??this._getType()},_parse(t,r){let a=e(t);if(a===true)return {success:true,data:t};if(typeof a=="object"&&a?.success===true)return a;let n={message:typeof i=="function"?i(t):i};return {success:false,error:n,errors:[n]}},parse(t,r){let a=c._parse(t,r);if(!a.success)throw a=a,new Error(a.error.message,{cause:a.error.cause});return a.data},safeParse(t,r){return c._parse(t,r)},transform(t){return h(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success&&(u.data=t(u.data)),u}),this},optional(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r===void 0&&(n.data=void 0,n.success=true),n}),this},nullable(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r===null&&(n.data=null,n.success=true),n}),this},nullish(){return h(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r==null&&(n.success=true,n.data=r),n}),this},default(t){return h(this,"_parse",(r,a,n)=>(a===void 0&&(a=t,a=typeof t=="function"?t():t),r(a,n))),this},pipe(t){return h(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success?t._parse(u.data,n):u}),this},refine(t,{message:r,type:a}={}){return a&&(r=r||O(a),s=a),h(this,"_parse",(n,u,p)=>{let m=n(u,p);y(p);if(!m.success)return m;let I=t(m.data);if(I===true||typeof I=="object"&&I?.success===true)return m;let T={message:typeof r=="function"?r(u):r};return {success:false,error:T,errors:[T]}}),this}};return S.length>0?S.reduce((t,r)=>r(t,e,f)??t,c):c}var S=[];function $(e){S.push(e);}exports.extend=$;exports.hookOriginal=h;exports.s=R;
type ErrorStructure = {
message: string;
cause?: {
key?: string;
};
};
type Valid<Output> = {
success: true;
data: Output;
};
type Invalid = {
success: false;
error: ErrorStructure;
errors?: ErrorStructure[];
};
type InternalParseOutput<Output> = Valid<Output> | Invalid;
type ValidationMethod<Input, Output> = (value: Input | Partial<Input>) => boolean | InternalParseOutput<Output>;
interface ParseOptions {
abortEarly?: boolean;
}
interface SchemaInterface<Input, Output> {
_getName(): string;
_getType(): string;
_getDescription(): string;
_parse(value: Input | Partial<Input>, options?: ParseOptions): InternalParseOutput<Output>;
parse(value: Input | Partial<Input>, options?: ParseOptions): Output;
safeParse(value: Input | Partial<Input>, options?: ParseOptions): InternalParseOutput<Output>;
optional(): SchemaInterface<Input, Partial<Output> | undefined>;
transform<NewOutput>(callback: (value: Input) => NewOutput): SchemaInterface<Input, NewOutput>;
nullable(): SchemaInterface<Input, Output | null>;
nullish(): SchemaInterface<Input, Output | undefined | null>;
default(defaultValue: Partial<Input> | (() => Partial<Input>) | Partial<Output>): SchemaInterface<Input, Output>;
pipe<NewOutput>(schema: SchemaInterface<Output, NewOutput>): SchemaInterface<Output, NewOutput>;
refine(validation: ValidationMethod<Input, Output>, options?: CreateSchemaInterfaceOptions): SchemaInterface<Input, Output>;
}
interface UnionSchemaInterface<T extends Array<SchemaInterface<unknown, unknown>>> extends SchemaInterface<ReturnType<T[number]['parse']>, ReturnType<T[number]['parse']>> {
}
interface EnumSchemaInterface<T extends string> extends SchemaInterface<string, T> {
}
interface StringSchemaInterface extends SchemaInterface<string, string> {
}
interface NumberSchemaInterface extends SchemaInterface<number, number> {
}
interface BooleanSchemaInterface extends SchemaInterface<boolean, boolean> {
}
interface DateSchemaInterface extends SchemaInterface<Date, Date> {
}
interface ArraySchemaInterface<T extends SchemaType> extends SchemaInterface<Array<ReturnType<T['parse']>>, Array<ReturnType<T['parse']>>> {
}
interface ObjectSchemaInterface<T extends Record<string, SchemaType>> extends SchemaInterface<{
[Property in keyof T]: ReturnType<T[Property]['parse']>;
}, {
[Property in keyof T]: ReturnType<T[Property]['parse']>;
}> {
}
type SchemaType = StringSchemaInterface | SchemaInterface<unknown, unknown> | SchemaInterface<string, string> | SchemaInterface<string, string | undefined> | SchemaInterface<string, string | null> | SchemaInterface<string, string | undefined | null> | ObjectSchemaInterface<Record<string, SchemaType>> | SchemaInterface<object, object> | SchemaInterface<object, object | undefined> | SchemaInterface<object, object | null> | SchemaInterface<object, object | undefined | null> | NumberSchemaInterface | SchemaInterface<number, number> | SchemaInterface<number, number | undefined> | SchemaInterface<number, number | null> | SchemaInterface<number, number | undefined | null> | BooleanSchemaInterface | SchemaInterface<boolean, boolean> | SchemaInterface<boolean, boolean | undefined> | SchemaInterface<boolean, boolean | null> | SchemaInterface<boolean, boolean | undefined | null> | DateSchemaInterface | SchemaInterface<Date, Date> | SchemaInterface<Date, Date | undefined> | SchemaInterface<Date, Date | null> | SchemaInterface<Date, Date | undefined | null> | EnumSchemaInterface<string> | UnionSchemaInterface<Array<SchemaInterface<unknown, unknown>>> | ArraySchemaInterface<StringSchemaInterface | ObjectSchemaInterface<Record<string, SchemaType>> | NumberSchemaInterface | BooleanSchemaInterface | DateSchemaInterface | EnumSchemaInterface<string>> | SchemaInterface<Array<unknown>, Array<unknown>> | SchemaInterface<Array<unknown>, Array<unknown> | undefined> | SchemaInterface<Array<unknown>, Array<unknown> | null> | SchemaInterface<Array<unknown>, Array<unknown> | undefined | null>;
type ErrorMessage = string | ((value: unknown) => string);
type ExtenderType = (inter: SchemaType, validation: Function, options?: {
message: ErrorMessage;
type: string;
}) => SchemaType;
interface CreateSchemaInterfaceOptions {
name?: string;
type?: string;
message?: ErrorMessage;
}
type SchemaInterfaceOptions = Omit<CreateSchemaInterfaceOptions, 'type'>;
declare const s: {
/**
* Creates an object schema with validated fields.
*
* @param definition - Object containing field schemas
* @param options - Optional configuration (name, message)
* @returns Object schema interface
*
* @example
* ```typescript
* const userSchema = s.object({
* name: s.string(),
* age: s.number()
* });
* ```
*/
object<T extends Record<string, SchemaType>>(definition: { [Property in keyof T]: T[Property]; }, options?: SchemaInterfaceOptions): ObjectSchemaInterface<T>;
/**
* Creates a string schema.
*
* @param options - Optional configuration (name, message)
* @returns String schema interface
*
* @example
* ```typescript
* const nameSchema = s.string();
* const result = nameSchema.parse('John'); // 'John'
* ```
*/
string(options?: SchemaInterfaceOptions): StringSchemaInterface;
/**
* Creates a number schema.
*
* @param options - Optional configuration (name, message)
* @returns Number schema interface
*
* @example
* ```typescript
* const ageSchema = s.number();
* const result = ageSchema.parse(25); // 25
* ```
*/
number(options?: SchemaInterfaceOptions): NumberSchemaInterface;
/**
* Creates a boolean schema.
*
* @param options - Optional configuration (name, message)
* @returns Boolean schema interface
*
* @example
* ```typescript
* const isActiveSchema = s.boolean();
* const result = isActiveSchema.parse(true); // true
* ```
*/
boolean(options?: SchemaInterfaceOptions): BooleanSchemaInterface;
/**
* Creates a date schema.
*
* @param options - Optional configuration (name, message)
* @returns Date schema interface
*
* @example
* ```typescript
* const birthdateSchema = s.date();
* const result = birthdateSchema.parse(new Date()); // Date object
* ```
*/
date(options?: SchemaInterfaceOptions): DateSchemaInterface;
/**
* Creates an enum schema with predefined values.
*
* @param definition - Array of allowed string values
* @param options - Optional configuration (name, message)
* @returns Enum schema interface
*
* @example
* ```typescript
* const roleSchema = s.enum(['admin', 'user', 'guest']);
* const result = roleSchema.parse('admin'); // 'admin'
* ```
*/
enum(definition: Readonly<Array<string>>, options?: SchemaInterfaceOptions): EnumSchemaInterface<(typeof definition)[number]>;
/**
* Creates an array schema with element validation.
*
* @param definition - Schema for array elements
* @param options - Optional configuration (name, message)
* @returns Array schema interface
*
* @example
* ```typescript
* const tagsSchema = s.array(s.string());
* const result = tagsSchema.parse(['tag1', 'tag2']); // ['tag1', 'tag2']
* ```
*/
array<T extends SchemaType>(definition: T, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
/**
* Creates a schema that accepts any value without validation.
*
* @returns Schema interface that accepts any value
*
* @example
* ```typescript
* const anySchema = s.any();
* const result = anySchema.parse({ anything: true }); // { anything: true }
* ```
*/
any(): any;
/**
* Preprocesses a value before passing it to a schema for validation.
*
* @param callback - Function to transform the value before validation
* @param schema - Schema to validate the transformed value
* @returns Modified schema with preprocessing
*
* @example
* ```typescript
* const schema = s.preprocess(
* (val) => String(val).trim(),
* s.string().min(3)
* );
* const result = schema.parse(' hello '); // 'hello'
* ```
*/
preprocess<T extends SchemaType>(callback: Function, schema: T): T;
/**
* Creates a union schema that validates against multiple schemas.
* The value must match at least one of the provided schemas.
*
* @param definitions - Array of schemas to validate against
* @param options - Optional configuration (name, message)
* @returns Union schema interface
*
* @example
* ```typescript
* const idSchema = s.union([s.string(), s.number()]);
* const result1 = idSchema.parse('abc'); // 'abc'
* const result2 = idSchema.parse(123); // 123
* ```
*/
union<T extends Array<SchemaType>>(definitions: T, options?: SchemaInterfaceOptions): UnionSchemaInterface<T>;
};
declare function hookOriginal<Input, Output>(object: SchemaInterface<Input, Output> | SchemaType, method: string, action: (original: Function, ...args: unknown[]) => InternalParseOutput<Output>): void;
/**
* Extends the schema system with custom validation methods.
* Used to add new methods to schema interfaces like StringSchemaInterface, NumberSchemaInterface, etc.
*
* @param callback - Function that receives schema, validation, and options, and can add new methods
*
* @example
* ```typescript
* import { extend, type StringSchemaInterface } from '@esmj/schema';
*
* // Extend StringSchemaInterface with email validation
* declare module '@esmj/schema' {
* interface StringSchemaInterface {
* email(): StringSchemaInterface;
* }
* }
*
* extend((schema, _, options) => {
* if (options?.type === 'string') {
* schema.email = function() {
* return this.refine(
* (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
* { message: 'Invalid email address' }
* );
* };
* }
* return schema;
* });
*
* // Now you can use the email() method
* const emailSchema = s.string().email();
* ```
*/
declare function extend(callback: ExtenderType): void;
/**
* Type helper to infer the output type of a schema.
* Extracts the TypeScript type that a schema will produce after parsing.
*
* @template T - The schema type to infer from
*
* @example
* ```typescript
* const userSchema = s.object({
* name: s.string(),
* age: s.number(),
* email: s.string().optional()
* });
*
* type User = Infer<typeof userSchema>;
* // type User = {
* // name: string;
* // age: number;
* // email?: string;
* // }
* ```
*/
type Infer<T> = T extends SchemaType ? ReturnType<T['parse']> : unknown;
export { type ArraySchemaInterface, type BooleanSchemaInterface, type DateSchemaInterface, type EnumSchemaInterface, type ErrorStructure, type ExtenderType, type Infer, type Invalid, type NumberSchemaInterface, type ObjectSchemaInterface, type SchemaInterface, type SchemaInterfaceOptions, type SchemaType, type StringSchemaInterface, type UnionSchemaInterface, type Valid, extend, hookOriginal, s };
'use strict';var P={abortEarly:true};function S(e,o){if(!o)return e;let i=e?.cause?.key?`${o}.${e.cause.key}`:`${o}`;return {message:`Error parsing key "${i}": ${e.message}`,cause:{key:i}}}function g(e,o,i){!e.errors||e.errors.length===0||e.errors.forEach(u=>{let c=S(u,i);o.push(c);});}function d(e){return {...P,...e}}var N=e=>typeof e=="string"||e instanceof String,k=e=>typeof e=="number"||e instanceof Number,w=e=>e===true||e===false,E=e=>e instanceof Date&&!Number.isNaN(e.getTime()),_=e=>Array.isArray(e),O=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),A={object(e,o){let i=I(O,{...o,type:"object"});return i._getDescription=()=>`object({ ${Object.entries(e).map(([c,r])=>`${c}: ${r._getDescription()}`).join(", ")} })`,h(i,"_parse",(u,c,r)=>{let t=u(c,r),{abortEarly:n}=d(r);if(t.success===false)return t;let s={},a=[];for(let p in e){let f=e[p]._parse(t.data[p],r);if(f.success)s[p]=f.data;else {if(f=f,n!==false){let m=S(f.error,p);return {success:false,error:m,errors:[m]}}g(f,a,p);}}return a.length>0?{success:false,error:a[0],errors:a}:{success:true,data:s}}),i},string(e){return I(N,{...e,type:"string"})},number(e){return I(k,{...e,type:"number"})},boolean(e){return I(w,{...e,type:"boolean"})},date(e){return I(E,{...e,type:"date"})},enum(e,o){let i=t=>e.includes(t),u=t=>`Invalid ${c} value. Expected ${e.map(n=>`"${n}"`).join(" | ")}, received "${t}".`,c="enum",r=I(i,{message:u,...o,type:c});return r._getDescription=()=>`enum(${e.map(t=>`"${t}"`).join(" | ")})`,r},array(e,o){let i=I(_,{...o,type:"array"});return i._getDescription=()=>`array(${e._getDescription()})`,h(i,"_parse",(u,c,r)=>{let t=u(c,r),{abortEarly:n}=d(r);if(t.success===false)return t;let s=[],a=[];for(let p=0;p<t.data.length;p++){let f=e._parse(t.data[p],r);if(f.success)s.push(f.data);else {if(f=f,n!==false){let m=S(f.error,p);return {success:false,error:m,errors:[m]}}g(f,a,p);}}return a.length>0?{success:false,error:a[0],errors:a}:{success:true,data:s}}),i},any(){return I(()=>true)},preprocess(e,o){return h(o,"_parse",(i,u)=>(u=e(u),i(u))),o},union(e,o){return I(r=>{for(let t=0;t<e.length;t++){let n=e[t]._parse(r);if(n.success)return n}return false},{message:r=>`Invalid union value. Expected the value to match one of the schemas:${e.map((t,n)=>` ${n+1}. ${t._getDescription()}`).join(",")} but received "${typeof r}" with value: ${O(r)?JSON.stringify(r):`"${r}"`}`,...o,type:"union"})}};function T(e){return o=>`The value "${o}" must be type of ${e} but is type of "${typeof o}".`}function h(e,o,i){let u=e[o];e[o]=(...c)=>i(u,...c);}function I(e,{type:o="any",name:i,message:u}={}){u=u||T(o);let c={name:i,message:u,type:o},r={_getName(){return i},_getType(){return o},_getDescription(){return this._getName()??this._getType()},_parse(t,n){let s=e(t);if(s===true)return {success:true,data:t};if(typeof s=="object"&&s?.success===true)return s;let a={message:typeof u=="function"?u(t):u};return {success:false,error:a,errors:[a]}},parse(t,n){let s=r._parse(t,n);if(!s.success)throw s=s,new Error(s.error.message,{cause:s.error.cause});return s.data},safeParse(t,n){return r._parse(t,n)},transform(t){return h(this,"_parse",(n,s,a)=>{let p=n(s,a);return p.success&&(p.data=t(p.data)),p}),this},optional(){return h(this,"_parse",(t,n,s)=>{let a=t(n,s);return !a.success&&n===void 0&&(a.data=void 0,a.success=true),a}),this},nullable(){return h(this,"_parse",(t,n,s)=>{let a=t(n,s);return !a.success&&n===null&&(a.data=null,a.success=true),a}),this},nullish(){return h(this,"_parse",(t,n,s)=>{let a=t(n,s);return !a.success&&n==null&&(a.success=true,a.data=n),a}),this},default(t){return h(this,"_parse",(n,s,a)=>(s===void 0&&(s=t,s=typeof t=="function"?t():t),n(s,a))),this},pipe(t){return h(this,"_parse",(n,s,a)=>{let p=n(s,a);return p.success?t._parse(p.data,a):p}),this},refine(t,{message:n,type:s}={}){return s&&(n=n||T(s),o=s),h(this,"_parse",(a,p,f)=>{let m=a(p,f);d(f);if(!m.success)return m;let l=t(m.data);if(l===true||typeof l=="object"&&l?.success===true)return m;let b={message:typeof n=="function"?n(p):n};return {success:false,error:b,errors:[b]}}),this}};return y.length>0?y.reduce((t,n)=>n(t,e,c)??t,r):r}var y=[];function x(e){y.push(e);}x((e,o,i)=>{if(i?.type==="number"){let u=e;u.min=function(c,{message:r}={}){return this.refine(t=>t>=c,{message:r||`Number must be greater than or equal to ${c}.`})},u.max=function(c,{message:r}={}){return this.refine(t=>t<=c,{message:r||`Number must be less than or equal to ${c}.`})},u.positive=function({message:c}={}){return this.refine(r=>r>0,{message:c||"Number must be positive."})},u.negative=function({message:c}={}){return this.refine(r=>r<0,{message:c||"Number must be negative."})},u.int=function({message:c}={}){return this.refine(r=>Number.isInteger(r),{message:c||"Number must be an integer."})},u.float=function({message:c}={}){return this.refine(r=>Number.isFinite(r)&&!Number.isInteger(r),{message:c||"Number must be a floating point (non-integer)."})},u.multipleOf=function(c,{message:r}={}){return this.refine(t=>t%c===0,{message:r||`Number must be a multiple of ${c}.`})},u.finite=function({message:c}={}){return this.refine(r=>Number.isFinite(r),{message:c||"Number must be finite."})};}return e});exports.extend=x;exports.hookOriginal=h;exports.s=A;
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.cjs';
declare module './index.ts' {
interface NumberSchemaInterface {
min(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
max(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
positive(options?: SchemaInterfaceOptions): NumberSchemaInterface;
negative(options?: SchemaInterfaceOptions): NumberSchemaInterface;
int(options?: SchemaInterfaceOptions): NumberSchemaInterface;
float(options?: SchemaInterfaceOptions): NumberSchemaInterface;
multipleOf(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
finite(options?: SchemaInterfaceOptions): NumberSchemaInterface;
}
}
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.js';
declare module './index.ts' {
interface NumberSchemaInterface {
min(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
max(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
positive(options?: SchemaInterfaceOptions): NumberSchemaInterface;
negative(options?: SchemaInterfaceOptions): NumberSchemaInterface;
int(options?: SchemaInterfaceOptions): NumberSchemaInterface;
float(options?: SchemaInterfaceOptions): NumberSchemaInterface;
multipleOf(value: number, options?: SchemaInterfaceOptions): NumberSchemaInterface;
finite(options?: SchemaInterfaceOptions): NumberSchemaInterface;
}
}
import'./chunk-QEBUM44M.js';export{c as extend,b as hookOriginal,a as s}from'./chunk-5ARMWSHU.js';
'use strict';var P={abortEarly:true};function I(t,o){if(!o)return t;let i=t?.cause?.key?`${o}.${t.cause.key}`:`${o}`;return {message:`Error parsing key "${i}": ${t.message}`,cause:{key:i}}}function O(t,o,i){!t.errors||t.errors.length===0||t.errors.forEach(c=>{let r=I(c,i);o.push(r);});}function d(t){return {...P,...t}}var k=t=>typeof t=="string"||t instanceof String,w=t=>typeof t=="number"||t instanceof Number,E=t=>t===true||t===false,$=t=>t instanceof Date&&!Number.isNaN(t.getTime()),_=t=>Array.isArray(t),b=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),A={object(t,o){let i=S(b,{...o,type:"object"});return i._getDescription=()=>`object({ ${Object.entries(t).map(([r,n])=>`${r}: ${n._getDescription()}`).join(", ")} })`,h(i,"_parse",(c,r,n)=>{let e=c(r,n),{abortEarly:a}=d(n);if(e.success===false)return e;let u={},s=[];for(let p in t){let f=t[p]._parse(e.data[p],n);if(f.success)u[p]=f.data;else {if(f=f,a!==false){let m=I(f.error,p);return {success:false,error:m,errors:[m]}}O(f,s,p);}}return s.length>0?{success:false,error:s[0],errors:s}:{success:true,data:u}}),i},string(t){return S(k,{...t,type:"string"})},number(t){return S(w,{...t,type:"number"})},boolean(t){return S(E,{...t,type:"boolean"})},date(t){return S($,{...t,type:"date"})},enum(t,o){let i=e=>t.includes(e),c=e=>`Invalid ${r} value. Expected ${t.map(a=>`"${a}"`).join(" | ")}, received "${e}".`,r="enum",n=S(i,{message:c,...o,type:r});return n._getDescription=()=>`enum(${t.map(e=>`"${e}"`).join(" | ")})`,n},array(t,o){let i=S(_,{...o,type:"array"});return i._getDescription=()=>`array(${t._getDescription()})`,h(i,"_parse",(c,r,n)=>{let e=c(r,n),{abortEarly:a}=d(n);if(e.success===false)return e;let u=[],s=[];for(let p=0;p<e.data.length;p++){let f=t._parse(e.data[p],n);if(f.success)u.push(f.data);else {if(f=f,a!==false){let m=I(f.error,p);return {success:false,error:m,errors:[m]}}O(f,s,p);}}return s.length>0?{success:false,error:s[0],errors:s}:{success:true,data:u}}),i},any(){return S(()=>true)},preprocess(t,o){return h(o,"_parse",(i,c)=>(c=t(c),i(c))),o},union(t,o){return S(n=>{for(let e=0;e<t.length;e++){let a=t[e]._parse(n);if(a.success)return a}return false},{message:n=>`Invalid union value. Expected the value to match one of the schemas:${t.map((e,a)=>` ${a+1}. ${e._getDescription()}`).join(",")} but received "${typeof n}" with value: ${b(n)?JSON.stringify(n):`"${n}"`}`,...o,type:"union"})}};function T(t){return o=>`The value "${o}" must be type of ${t} but is type of "${typeof o}".`}function h(t,o,i){let c=t[o];t[o]=(...r)=>i(c,...r);}function S(t,{type:o="any",name:i,message:c}={}){c=c||T(o);let r={name:i,message:c,type:o},n={_getName(){return i},_getType(){return o},_getDescription(){return this._getName()??this._getType()},_parse(e,a){let u=t(e);if(u===true)return {success:true,data:e};if(typeof u=="object"&&u?.success===true)return u;let s={message:typeof c=="function"?c(e):c};return {success:false,error:s,errors:[s]}},parse(e,a){let u=n._parse(e,a);if(!u.success)throw u=u,new Error(u.error.message,{cause:u.error.cause});return u.data},safeParse(e,a){return n._parse(e,a)},transform(e){return h(this,"_parse",(a,u,s)=>{let p=a(u,s);return p.success&&(p.data=e(p.data)),p}),this},optional(){return h(this,"_parse",(e,a,u)=>{let s=e(a,u);return !s.success&&a===void 0&&(s.data=void 0,s.success=true),s}),this},nullable(){return h(this,"_parse",(e,a,u)=>{let s=e(a,u);return !s.success&&a===null&&(s.data=null,s.success=true),s}),this},nullish(){return h(this,"_parse",(e,a,u)=>{let s=e(a,u);return !s.success&&a==null&&(s.success=true,s.data=a),s}),this},default(e){return h(this,"_parse",(a,u,s)=>(u===void 0&&(u=e,u=typeof e=="function"?e():e),a(u,s))),this},pipe(e){return h(this,"_parse",(a,u,s)=>{let p=a(u,s);return p.success?e._parse(p.data,s):p}),this},refine(e,{message:a,type:u}={}){return u&&(a=a||T(u),o=u),h(this,"_parse",(s,p,f)=>{let m=s(p,f);d(f);if(!m.success)return m;let l=e(m.data);if(l===true||typeof l=="object"&&l?.success===true)return m;let g={message:typeof a=="function"?a(p):a};return {success:false,error:g,errors:[g]}}),this}};return y.length>0?y.reduce((e,a)=>a(e,t,r)??e,n):n}var y=[];function x(t){y.push(t);}x((t,o,i)=>{if(i?.type==="string"){let c=t;c.min=function(r,{message:n}={}){return this.refine(e=>e.length>=r,{message:n||(e=>`String must be at least ${r} characters long (received ${e.length} characters: "${e}")`)})},c.max=function(r,{message:n}={}){return this.refine(e=>e.length<=r,{message:n||(e=>`String must be at most ${r} characters long (received ${e.length} characters: "${e}")`)})},c.length=function(r,{message:n}={}){return this.refine(e=>e.length===r,{message:n||(e=>`String must be exactly ${r} characters long (received ${e.length} characters: "${e}")`)})},c.nonEmpty=function({message:r}={}){return this.refine(n=>n.length>0,{message:r||"String must not be empty (received empty string)"})},c.startsWith=function(r,{message:n}={}){return this.refine(e=>e.startsWith(r),{message:n||(e=>`String must start with "${r}" (received: "${e}")`)})},c.endsWith=function(r,{message:n}={}){return this.refine(e=>e.endsWith(r),{message:n||(e=>`String must end with "${r}" (received: "${e}")`)})},c.includes=function(r,{message:n}={}){return this.refine(e=>e.includes(r),{message:n||(e=>`String must include "${r}" (received: "${e}")`)})},c.toLowerCase=function(){return this.transform(r=>r.toLowerCase())},c.toUpperCase=function(){return this.transform(r=>r.toUpperCase())},c.trim=function(){return this.transform(r=>r.trim())},c.padStart=function(r,n=" "){return this.transform(e=>e.padStart(r,n))},c.padEnd=function(r,n=" "){return this.transform(e=>e.padEnd(r,n))},c.replace=function(r,n){return this.transform(e=>e.replace(r,n))};}return t});exports.extend=x;exports.hookOriginal=h;exports.s=A;
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.cjs';
declare module './index.ts' {
interface StringSchemaInterface {
min(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
max(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
length(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
nonEmpty(options?: SchemaInterfaceOptions): StringSchemaInterface;
startsWith(prefix: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
endsWith(suffix: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
includes(substring: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
trim(): StringSchemaInterface;
toLowerCase(): StringSchemaInterface;
toUpperCase(): StringSchemaInterface;
padStart(length: number, fillChar?: string): StringSchemaInterface;
padEnd(length: number, fillChar?: string): StringSchemaInterface;
replace(search: string | RegExp, replace: string): StringSchemaInterface;
}
}
export { ArraySchemaInterface, BooleanSchemaInterface, DateSchemaInterface, EnumSchemaInterface, ErrorStructure, ExtenderType, Infer, Invalid, NumberSchemaInterface, ObjectSchemaInterface, SchemaInterface, SchemaInterfaceOptions, SchemaType, StringSchemaInterface, UnionSchemaInterface, Valid, extend, hookOriginal, s } from './index.js';
declare module './index.ts' {
interface StringSchemaInterface {
min(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
max(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
length(length: number, options?: SchemaInterfaceOptions): StringSchemaInterface;
nonEmpty(options?: SchemaInterfaceOptions): StringSchemaInterface;
startsWith(prefix: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
endsWith(suffix: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
includes(substring: string, options?: SchemaInterfaceOptions): StringSchemaInterface;
trim(): StringSchemaInterface;
toLowerCase(): StringSchemaInterface;
toUpperCase(): StringSchemaInterface;
padStart(length: number, fillChar?: string): StringSchemaInterface;
padEnd(length: number, fillChar?: string): StringSchemaInterface;
replace(search: string | RegExp, replace: string): StringSchemaInterface;
}
}
import'./chunk-6ABUMTDR.js';export{c as extend,b as hookOriginal,a as s}from'./chunk-5ARMWSHU.js';
import { s } from '../src/full.ts';
// Advanced form validation example
const addressSchema = s.object({
street: s.string().min(3).max(100),
city: s.string().min(2).max(50),
zipCode: s.string().length(5).refine((val) => /^\d{5}$/.test(val), {
message: 'ZIP code must be 5 digits',
}),
country: s.enum(['US', 'CA', 'MX', 'UK']),
});
const userProfileSchema = s.object({
// Personal info
firstName: s.string().trim().min(2).max(50),
lastName: s.string().trim().min(2).max(50),
email: s
.string()
.trim()
.toLowerCase()
.refine((value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), {
message: 'Invalid email address',
}),
// Contact
phone: s
.string()
.optional()
.transform((val) => val?.replace(/\D/g, ''))
.refine((val) => !val || val.length === 10, {
message: 'Phone number must be 10 digits',
}),
// Address
address: addressSchema.optional(),
// Preferences
role: s.enum(['admin', 'editor', 'viewer']).default('viewer'),
tags: s.array(s.string()).min(1).max(5).unique(),
isActive: s.boolean().default(true),
// Metadata
createdAt: s.date(),
updatedAt: s.date().optional(),
});
console.log('=== Valid User Profile ===');
const validProfile = {
firstName: ' John ',
lastName: 'Doe',
email: ' JOHN.DOE@EXAMPLE.COM ',
phone: '(555) 123-4567',
address: {
street: '123 Main St',
city: 'New York',
zipCode: '10001',
country: 'US' as const,
},
role: 'admin' as const,
tags: ['developer', 'typescript', 'node'],
isActive: true,
createdAt: new Date(),
};
console.log('Input:', validProfile);
console.log('Parsed:', userProfileSchema.parse(validProfile));
console.log('\n=== Invalid User Profile (missing required fields) ===');
const invalidProfile = {
firstName: 'John',
// lastName missing
email: 'invalid-email',
tags: [],
createdAt: new Date(),
};
console.log('Result:', userProfileSchema.safeParse(invalidProfile));
console.log('\n=== Invalid ZIP Code ===');
const invalidZipProfile = {
...validProfile,
address: {
street: '123 Main St',
city: 'New York',
zipCode: 'ABC12', // Invalid: not digits
country: 'US' as const,
},
};
console.log('Result:', userProfileSchema.safeParse(invalidZipProfile));
// API response validation
const apiResponseSchema = s.object({
status: s.enum(['success', 'error']),
data: s
.object({
users: s.array(
s.object({
id: s.number().positive().int(),
name: s.string(),
email: s.string(),
}),
),
total: s.number().positive().int(),
})
.optional(),
error: s
.object({
code: s.string(),
message: s.string(),
})
.optional(),
});
console.log('\n=== API Response Validation (Success) ===');
const successResponse = {
status: 'success' as const,
data: {
users: [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' },
],
total: 2,
},
};
console.log('Result:', apiResponseSchema.parse(successResponse));
console.log('\n=== API Response Validation (Error) ===');
const errorResponse = {
status: 'error' as const,
error: {
code: 'NOT_FOUND',
message: 'User not found',
},
};
console.log('Result:', apiResponseSchema.parse(errorResponse));
import { s } from '../src/full.ts';
// String validations with transformations
console.log('=== String Validations ===');
console.log(
'trim + startsWith + endsWith:',
s
.string()
.trim()
.startsWith('Hello')
.endsWith('World')
.safeParse(' Hello, World '),
);
console.log(
'startsWith + endsWith (without trim):',
s.string().startsWith('Hello').endsWith('World').safeParse(' Hello, World '),
);
// Array validations
console.log('\n=== Array Validations ===');
console.log(
'Array with min/max:',
s.array(s.string()).min(2).max(5).safeParse(['Hello', 'World']),
);
// Number validations
console.log('\n=== Number Validations ===');
console.log('Integer + positive:', s.number().int().positive().safeParse(42));
console.log('Float validation:', s.number().float().safeParse(3.14));
// Union with extended methods
console.log('\n=== Union Validations ===');
console.log(
'Union with string validation:',
s
.union([
s.string({ message: 'stringSchema' }).startsWith('Hello'),
s.number(),
])
.safeParse('World'),
);
import { s, extend, type StringSchemaInterface } from '../src/index.ts';
// Extend StringSchemaInterface to add custom methods
declare module '../src/index.ts' {
interface StringSchemaInterface {
email(options?: { message?: string }): StringSchemaInterface;
url(options?: { message?: string }): StringSchemaInterface;
uuid(options?: { message?: string }): StringSchemaInterface;
}
}
// Implement the extensions
extend((schema, _, options) => {
if (options?.type === 'string') {
const stringSchema = schema as StringSchemaInterface;
// Email validation
stringSchema.email = function ({ message } = {}) {
return this.refine(
(value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
{
message: message || ((value: string) => `"${value}" is not a valid email address`),
},
);
};
// URL validation
stringSchema.url = function ({ message } = {}) {
return this.refine(
(value) => {
try {
new URL(value);
return true;
} catch {
return false;
}
},
{
message: message || ((value: string) => `"${value}" is not a valid URL`),
},
);
};
// UUID validation
stringSchema.uuid = function ({ message } = {}) {
return this.refine(
(value) =>
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
value,
),
{
message: message || ((value: string) => `"${value}" is not a valid UUID`),
},
);
};
}
return schema;
});
// Now use the extended schema
console.log('=== Email Validation ===');
const emailSchema = s.string().email();
console.log('Valid email:', emailSchema.safeParse('user@example.com'));
console.log('Invalid email:', emailSchema.safeParse('not-an-email'));
console.log('Empty string:', emailSchema.safeParse(''));
console.log('\n=== URL Validation ===');
const urlSchema = s.string().url();
console.log('Valid URL:', urlSchema.safeParse('https://example.com'));
console.log('Valid URL with path:', urlSchema.safeParse('https://example.com/path'));
console.log('Invalid URL:', urlSchema.safeParse('not a url'));
console.log('\n=== UUID Validation ===');
const uuidSchema = s.string().uuid();
console.log(
'Valid UUID:',
uuidSchema.safeParse('550e8400-e29b-41d4-a716-446655440000'),
);
console.log('Invalid UUID:', uuidSchema.safeParse('not-a-uuid'));
console.log(
'Invalid UUID format:',
uuidSchema.safeParse('550e8400-e29b-41d4-a716'),
);
// Combine extensions in a schema
console.log('\n=== Combined Schema ===');
const userSchema = s.object({
id: s.string().uuid(),
email: s.string().trim().toLowerCase().email(),
website: s.string().url().optional(),
});
console.log(
'Valid user:',
userSchema.parse({
id: '550e8400-e29b-41d4-a716-446655440000',
email: ' USER@EXAMPLE.COM ',
website: 'https://example.com',
}),
);
console.log(
'\nInvalid user (bad email):',
userSchema.safeParse({
id: '550e8400-e29b-41d4-a716-446655440000',
email: 'not-an-email',
}),
);
// Custom error messages
console.log('\n=== Custom Error Messages ===');
const customEmailSchema = s
.string()
.email({ message: 'Please enter a valid email address' });
console.log(
'Custom error:',
customEmailSchema.safeParse('invalid'),
);
import { s } from '../src/full.ts';
// Custom email validation using refine
const emailSchema = s
.string()
.trim()
.toLowerCase()
.refine((value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), {
message: 'Invalid email address format',
});
console.log('=== Custom Email Validation ===');
console.log('Valid email:', emailSchema.safeParse('user@example.com'));
console.log('Invalid email:', emailSchema.safeParse('not-an-email'));
console.log(
'Email with whitespace:',
emailSchema.safeParse(' User@Example.COM '),
);
// Custom URL validation
const urlSchema = s.string().refine(
(value) => {
try {
new URL(value);
return true;
} catch {
return false;
}
},
{
message: (value) => `"${value}" is not a valid URL`,
},
);
console.log('\n=== Custom URL Validation ===');
console.log('Valid URL:', urlSchema.safeParse('https://example.com'));
console.log('Invalid URL:', urlSchema.safeParse('not a url'));
// Custom age validation
const ageSchema = s
.number()
.int()
.positive()
.refine((value) => value >= 18, {
message: (value) =>
`Age must be at least 18 (received ${value} years old)`,
})
.refine((value) => value <= 120, {
message: (value) => `Age seems unrealistic (received ${value} years old)`,
});
console.log('\n=== Custom Age Validation ===');
console.log('Valid age:', ageSchema.safeParse(25));
console.log('Too young:', ageSchema.safeParse(15));
console.log('Too old:', ageSchema.safeParse(150));
// Custom password validation
const passwordSchema = s
.string()
.min(8, { message: 'Password must be at least 8 characters' })
.refine((value) => /[A-Z]/.test(value), {
message: 'Password must contain at least one uppercase letter',
})
.refine((value) => /[a-z]/.test(value), {
message: 'Password must contain at least one lowercase letter',
})
.refine((value) => /[0-9]/.test(value), {
message: 'Password must contain at least one number',
})
.refine((value) => /[^A-Za-z0-9]/.test(value), {
message: 'Password must contain at least one special character',
});
console.log('\n=== Custom Password Validation ===');
console.log('Valid password:', passwordSchema.safeParse('MyP@ssw0rd'));
console.log('Too short:', passwordSchema.safeParse('Pass1!'));
console.log('No uppercase:', passwordSchema.safeParse('myp@ssw0rd'));
console.log('No special char:', passwordSchema.safeParse('MyPassw0rd'));
// Custom object validation with cross-field checks
const registrationSchema = s
.object({
password: s.string().min(8),
confirmPassword: s.string(),
email: emailSchema,
age: ageSchema,
})
.refine((data) => data.password === data.confirmPassword, {
message: 'Passwords do not match',
});
console.log('\n=== Cross-Field Validation ===');
console.log(
'Valid registration:',
registrationSchema.safeParse({
password: 'MyP@ssw0rd',
confirmPassword: 'MyP@ssw0rd',
email: 'user@example.com',
age: 25,
}),
);
console.log(
'Password mismatch:',
registrationSchema.safeParse({
password: 'MyP@ssw0rd',
confirmPassword: 'Different123!',
email: 'user@example.com',
age: 25,
}),
);
{
"compilerOptions": {
"target": "es2022",
"module": "es2022",
"moduleResolution": "node",
"esModuleInterop": true,
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"noEmit": true
},
"include": ["src/**/*"]
}
+193
-3

@@ -17,2 +17,3 @@ type ErrorStructure = {

type InternalParseOutput<Output> = Valid<Output> | Invalid;
type ValidationMethod<Input, Output> = (value: Input | Partial<Input>) => boolean | InternalParseOutput<Output>;
interface ParseOptions {

@@ -22,2 +23,3 @@ abortEarly?: boolean;

interface SchemaInterface<Input, Output> {
_getName(): string;
_getType(): string;

@@ -34,3 +36,3 @@ _getDescription(): string;

pipe<NewOutput>(schema: SchemaInterface<Output, NewOutput>): SchemaInterface<Output, NewOutput>;
refine(validation: (value: Output) => boolean, options?: SchemaInterfaceOptions): SchemaInterface<Input, Output>;
refine(validation: ValidationMethod<Input, Output>, options?: CreateSchemaInterfaceOptions): SchemaInterface<Input, Output>;
}

@@ -49,3 +51,3 @@ interface UnionSchemaInterface<T extends Array<SchemaInterface<unknown, unknown>>> extends SchemaInterface<ReturnType<T[number]['parse']>, ReturnType<T[number]['parse']>> {

}
interface ArraySchemaInterface<T extends SchemaType> extends SchemaInterface<Array<T>, Array<ReturnType<T['parse']>>> {
interface ArraySchemaInterface<T extends SchemaType> extends SchemaInterface<Array<ReturnType<T['parse']>>, Array<ReturnType<T['parse']>>> {
}

@@ -65,2 +67,3 @@ interface ObjectSchemaInterface<T extends Record<string, SchemaType>> extends SchemaInterface<{

interface CreateSchemaInterfaceOptions {
name?: string;
type?: string;

@@ -71,16 +74,203 @@ message?: ErrorMessage;

declare const s: {
/**
* Creates an object schema with validated fields.
*
* @param definition - Object containing field schemas
* @param options - Optional configuration (name, message)
* @returns Object schema interface
*
* @example
* ```typescript
* const userSchema = s.object({
* name: s.string(),
* age: s.number()
* });
* ```
*/
object<T extends Record<string, SchemaType>>(definition: { [Property in keyof T]: T[Property]; }, options?: SchemaInterfaceOptions): ObjectSchemaInterface<T>;
/**
* Creates a string schema.
*
* @param options - Optional configuration (name, message)
* @returns String schema interface
*
* @example
* ```typescript
* const nameSchema = s.string();
* const result = nameSchema.parse('John'); // 'John'
* ```
*/
string(options?: SchemaInterfaceOptions): StringSchemaInterface;
/**
* Creates a number schema.
*
* @param options - Optional configuration (name, message)
* @returns Number schema interface
*
* @example
* ```typescript
* const ageSchema = s.number();
* const result = ageSchema.parse(25); // 25
* ```
*/
number(options?: SchemaInterfaceOptions): NumberSchemaInterface;
/**
* Creates a boolean schema.
*
* @param options - Optional configuration (name, message)
* @returns Boolean schema interface
*
* @example
* ```typescript
* const isActiveSchema = s.boolean();
* const result = isActiveSchema.parse(true); // true
* ```
*/
boolean(options?: SchemaInterfaceOptions): BooleanSchemaInterface;
/**
* Creates a date schema.
*
* @param options - Optional configuration (name, message)
* @returns Date schema interface
*
* @example
* ```typescript
* const birthdateSchema = s.date();
* const result = birthdateSchema.parse(new Date()); // Date object
* ```
*/
date(options?: SchemaInterfaceOptions): DateSchemaInterface;
/**
* Creates an enum schema with predefined values.
*
* @param definition - Array of allowed string values
* @param options - Optional configuration (name, message)
* @returns Enum schema interface
*
* @example
* ```typescript
* const roleSchema = s.enum(['admin', 'user', 'guest']);
* const result = roleSchema.parse('admin'); // 'admin'
* ```
*/
enum(definition: Readonly<Array<string>>, options?: SchemaInterfaceOptions): EnumSchemaInterface<(typeof definition)[number]>;
/**
* Creates an array schema with element validation.
*
* @param definition - Schema for array elements
* @param options - Optional configuration (name, message)
* @returns Array schema interface
*
* @example
* ```typescript
* const tagsSchema = s.array(s.string());
* const result = tagsSchema.parse(['tag1', 'tag2']); // ['tag1', 'tag2']
* ```
*/
array<T extends SchemaType>(definition: T, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
/**
* Creates a schema that accepts any value without validation.
*
* @returns Schema interface that accepts any value
*
* @example
* ```typescript
* const anySchema = s.any();
* const result = anySchema.parse({ anything: true }); // { anything: true }
* ```
*/
any(): any;
/**
* Preprocesses a value before passing it to a schema for validation.
*
* @param callback - Function to transform the value before validation
* @param schema - Schema to validate the transformed value
* @returns Modified schema with preprocessing
*
* @example
* ```typescript
* const schema = s.preprocess(
* (val) => String(val).trim(),
* s.string().min(3)
* );
* const result = schema.parse(' hello '); // 'hello'
* ```
*/
preprocess<T extends SchemaType>(callback: Function, schema: T): T;
/**
* Creates a union schema that validates against multiple schemas.
* The value must match at least one of the provided schemas.
*
* @param definitions - Array of schemas to validate against
* @param options - Optional configuration (name, message)
* @returns Union schema interface
*
* @example
* ```typescript
* const idSchema = s.union([s.string(), s.number()]);
* const result1 = idSchema.parse('abc'); // 'abc'
* const result2 = idSchema.parse(123); // 123
* ```
*/
union<T extends Array<SchemaType>>(definitions: T, options?: SchemaInterfaceOptions): UnionSchemaInterface<T>;
};
declare function hookOriginal<Input, Output>(object: SchemaInterface<Input, Output> | SchemaType, method: string, action: (original: Function, ...args: unknown[]) => InternalParseOutput<Output>): void;
/**
* Extends the schema system with custom validation methods.
* Used to add new methods to schema interfaces like StringSchemaInterface, NumberSchemaInterface, etc.
*
* @param callback - Function that receives schema, validation, and options, and can add new methods
*
* @example
* ```typescript
* import { extend, type StringSchemaInterface } from '@esmj/schema';
*
* // Extend StringSchemaInterface with email validation
* declare module '@esmj/schema' {
* interface StringSchemaInterface {
* email(): StringSchemaInterface;
* }
* }
*
* extend((schema, _, options) => {
* if (options?.type === 'string') {
* schema.email = function() {
* return this.refine(
* (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
* { message: 'Invalid email address' }
* );
* };
* }
* return schema;
* });
*
* // Now you can use the email() method
* const emailSchema = s.string().email();
* ```
*/
declare function extend(callback: ExtenderType): void;
/**
* Type helper to infer the output type of a schema.
* Extracts the TypeScript type that a schema will produce after parsing.
*
* @template T - The schema type to infer from
*
* @example
* ```typescript
* const userSchema = s.object({
* name: s.string(),
* age: s.number(),
* email: s.string().optional()
* });
*
* type User = Infer<typeof userSchema>;
* // type User = {
* // name: string;
* // age: number;
* // email?: string;
* // }
* ```
*/
type Infer<T> = T extends SchemaType ? ReturnType<T['parse']> : unknown;
export { type ArraySchemaInterface, type BooleanSchemaInterface, type DateSchemaInterface, type EnumSchemaInterface, type ExtenderType, type Infer, type NumberSchemaInterface, type ObjectSchemaInterface, type SchemaInterface, type SchemaInterfaceOptions, type SchemaType, type StringSchemaInterface, type UnionSchemaInterface, extend, s };
export { type ArraySchemaInterface, type BooleanSchemaInterface, type DateSchemaInterface, type EnumSchemaInterface, type ErrorStructure, type ExtenderType, type Infer, type Invalid, type NumberSchemaInterface, type ObjectSchemaInterface, type SchemaInterface, type SchemaInterfaceOptions, type SchemaType, type StringSchemaInterface, type UnionSchemaInterface, type Valid, extend, hookOriginal, s };
+1
-1

@@ -1,1 +0,1 @@

'use strict';var g={abortEarly:true};function I(e,s){if(!s)return e;let c=e?.cause?.key?`${s}.${e.cause.key}`:`${s}`;return {message:`Error parsing key "${c}": ${e.message}`,cause:{key:c}}}function y(e,s,c){!e.errors||e.errors.length===0||e.errors.forEach(i=>{let o=I(i,c);s.push(o);});}function S(e){return {...g,...e}}var b=e=>typeof e=="string"||e instanceof String,O=e=>typeof e=="number"||e instanceof Number,P=e=>e===true||e===false,k=e=>e instanceof Date&&!Number.isNaN(e.getTime()),x=e=>Array.isArray(e),T=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),E={object(e,s){let c=h(T,{...s,type:"object"});return c._getDescription=()=>`object({ ${Object.entries(e).map(([o,t])=>`${o}: ${t._getDescription()}`).join(", ")} })`,m(c,"_parse",(i,o,t)=>{let r=i(o,t),{abortEarly:a}=S(t);if(r.success===false)return r;let n={},u=[];for(let p in e){let f=e[p]._parse(r.data[p],t);if(f.success)n[p]=f.data;else {if(f=f,a!==false){let l=I(f.error,p);return {success:false,error:l,errors:[l]}}y(f,u,p);}}return u.length>0?{success:false,error:u[0],errors:u}:{success:true,data:n}}),c},string(e){return h(b,{...e,type:"string"})},number(e){return h(O,{...e,type:"number"})},boolean(e){return h(P,{...e,type:"boolean"})},date(e){return h(k,{...e,type:"date"})},enum(e,s){let c=r=>e.includes(r),i=r=>`Invalid ${o} value. Expected ${e.map(a=>`"${a}"`).join(" | ")}, received "${r}".`,o="enum",t=h(c,{message:i,...s,type:o});return t._getDescription=()=>`enum(${e.map(r=>`"${r}"`).join(" | ")})`,t},array(e,s){let c=h(x,{...s,type:"array"});return c._getDescription=()=>`array(${e._getDescription()})`,m(c,"_parse",(i,o,t)=>{let r=i(o,t),{abortEarly:a}=S(t);if(r.success===false)return r;let n=[],u=[];for(let p=0;p<r.data.length;p++){let f=e._parse(r.data[p],t);if(f.success)n.push(f.data);else {if(f=f,a!==false){let l=I(f.error,p);return {success:false,error:l,errors:[l]}}y(f,u,p);}}return u.length>0?{success:false,error:u[0],errors:u}:{success:true,data:n}}),c},any(){return h(()=>true)},preprocess(e,s){return m(s,"_parse",(c,i)=>(i=e(i),c(i))),s},union(e,s){return h(t=>{for(let r=0;r<e.length;r++)if(e[r]._parse(t).success)return true;return false},{message:t=>`Invalid union value. Expected the value to match one of the schemas:${e.map((r,a)=>` ${a+1}. ${r._getDescription()}`).join(",")} but received "${typeof t}" with value: ${T(t)?JSON.stringify(t):`"${t}"`}`,...s,type:"union"})}};function w(e){return s=>`The value "${s}" must be type of ${e} but is type of "${typeof s}".`}function m(e,s,c){let i=e[s];e[s]=(...o)=>c(i,...o);}function h(e,{type:s="any",message:c}={}){c=c||w(s);let i={message:c,type:s},o={_getType(){return s},_getDescription(){return this._getType()},_parse(t,r){if(e(t))return {success:true,data:t};let n={message:typeof c=="function"?c(t):c};return {success:false,error:n,errors:[n]}},parse(t,r){let a=o._parse(t,r);if(!a.success)throw a=a,new Error(a.error.message,{cause:a.error.cause});return a.data},safeParse(t,r){return o._parse(t,r)},transform(t){return m(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success&&(u.data=t(u.data)),u}),this},optional(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return n.success||(n.data=void 0,n.success=true),n}),this},nullable(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return n.success||(n.data=null,n.success=true),n}),this},nullish(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r==null&&(n.success=true,n.data=r),n}),this},default(t){return m(this,"_parse",(r,a,n)=>(a===void 0&&(a=t,a=typeof t=="function"?t():t),r(a,n))),this},pipe(t){return m(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success?t._parse(u.data,n):u}),this},refine(t,{message:r}={}){return m(this,"_parse",(a,n,u)=>{let p=a(n,u);if(!p.success)return p;if(!t(p.data)){let f=typeof r=="function"?r(n):r;return {success:false,error:{message:f},errors:[{message:f}]}}return p}),this}};return d.length>0?d.reduce((t,r)=>r(t,e,i)??t,o):o}var d=[];function _(e){d.push(e);}exports.extend=_;exports.s=E;
export{c as extend,b as hookOriginal,a as s}from'./chunk-5ARMWSHU.js';
{
"name": "@esmj/schema",
"version": "0.4.0",
"version": "0.5.0",
"description": "Tiny extendable package for schema validation.",
"type": "module",
"keywords": [

@@ -9,6 +10,11 @@ "schema",

"type",
"typescript",
"type-safe",
"validator",
"parse",
"transform",
"inference",
"zod",
"yup",
"@sinclair/typebox",
"yup",
"superstruct",

@@ -22,7 +28,33 @@ "joi",

".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./full": {
"types": "./dist/full.d.ts",
"import": "./dist/full.mjs",
"require": "./dist/full.js"
},
"./string": {
"types": "./dist/string.d.ts",
"import": "./dist/string.mjs",
"require": "./dist/string.js"
},
"./number": {
"types": "./dist/number.d.ts",
"import": "./dist/number.mjs",
"require": "./dist/number.js"
},
"./array": {
"types": "./dist/array.d.ts",
"import": "./dist/array.mjs",
"require": "./dist/array.js"
}
},
"sideEffects": false,
"sideEffects": [
"src/string.ts",
"src/number.ts",
"src/array.ts",
"src/full.ts"
],
"typings": "dist/index.d.ts",

@@ -75,20 +107,18 @@ "scripts": {

"@commitlint/config-conventional": "^19.8.1",
"@sinclair/typebox": "^0.34.38",
"@typescript-eslint/eslint-plugin": "^8.33.0",
"@typescript-eslint/parser": "^8.33.0",
"@sinclair/typebox": "^0.34.41",
"@zod/mini": "^4.0.0-beta.0",
"arktype": "^2.1.20",
"arktype": "^2.1.22",
"commitizen": "^4.3.1",
"conventional-changelog-cli": "^5.0.0",
"cz-conventional-changelog": "^3.3.0",
"effect": "^3.17.6",
"effect": "^3.17.13",
"git-cz": "^4.9.0",
"husky": "^9.1.7",
"joi": "^17.13.3",
"lint-staged": "^16.1.0",
"lint-staged": "^16.1.6",
"superstruct": "^2.0.2",
"tsup": "^8.5.0",
"yup": "^1.6.1",
"yup": "^1.7.0",
"zod": "^3.25.42"
}
}
+657
-13
# Schema
This small library provides a simple schema validation system for JavaScript/TypeScript. The library has basic types with opportunities for extending.
This small library provides a simple schema validation system for JavaScript/TypeScript. The library has basic types with opportunities for extending.
## Table of Contents
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Why Use @esmj/schema?](#why-use-esmjschema)
- [Comparison with Similar Libraries](#comparison-with-similar-libraries)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Modular Extensions](#modular-extensions)
- [String Extensions](#string-extensions-esmjschemastring)
- [Number Extensions](#number-extensions-esmjschemanumber)
- [Array Extensions](#array-extensions-esmjschemaarray)
- [Full Extensions](#full-extensions-esmjschemafull)
- [API Reference Summary](#api-reference-summary)
- [Schema Types](#schema-types)
- [Schema Methods](#schema-methods)
- [parse](#parsevalue-parseoptions)
- [safeParse](#safeparsevalue-parseoptions)
- [Error Collection with abortEarly](#error-collection-with-abortearly-option)
- [Extending Schemas](#extending-schemas)
- [More Examples](#more-examples)
- [Examples Folder](#examples-folder)
- [Migration Guide](#migration-guide)
- [From Zod](#from-zod)
- [From Yup](#from-yup)
- [License](#license)
## Installation

@@ -11,2 +38,57 @@

## Quick Start
Get started with `@esmj/schema` in seconds:
```typescript
import { s } from '@esmj/schema';
// Define a schema
const userSchema = s.object({
name: s.string(),
age: s.number(),
email: s.string().optional()
});
// Parse data
const user = userSchema.parse({
name: 'John Doe',
age: 30
});
console.log(user);
// { name: 'John Doe', age: 30 }
// Safe parse with error handling
const result = userSchema.safeParse({
name: 'Jane',
age: 'invalid'
});
if (result.success) {
console.log(result.data);
} else {
console.error(result.error.message);
}
```
**With Extensions:**
```typescript
import { s } from '@esmj/schema/full';
const schema = s.object({
username: s.string().trim().toLowerCase().min(3).max(20),
age: s.number().int().positive().min(18),
tags: s.array(s.string()).min(1).unique()
});
const result = schema.parse({
username: ' JohnDoe ',
age: 25,
tags: ['developer', 'typescript']
});
// { username: 'johndoe', age: 25, tags: ['developer', 'typescript'] }
```
## Why Use `@esmj/schema`?

@@ -18,7 +100,8 @@

2. **Extensibility**: Easily extend the library with custom logic, refinements, and preprocessors using the `extend` function.
3. **Rich Features**: Includes advanced features like preprocessing, transformations, piping, refinements, and robust error collection (`abortEarly`).
4. **Actionable Error Handling**: Collect all validation errors at once for better debugging and user experience, with clear and consistent error structures (`error` and `errors`).
3. **Rich Features**: Includes advanced features like preprocessing, transformations, piping, refinements, and robust error collection (`abortEarly`), which are not always available in similar libraries.
4. **Actionable Error Handling**: Collect all validation errors at once for better debugging and user experience, with clear and consistent error structures.
5. **Lightweight**: No dependencies and a small footprint make it ideal for projects where performance and simplicity are key.
6. **Customizable**: Offers fine-grained control over validation, error handling, and schema composition.
7. **Performance**: Optimized for speed, making it one of the fastest schema validation libraries available.
8. **Modular**: Import only what you need with separate string, number, and array extension modules to minimize bundle size.

@@ -39,3 +122,3 @@ ### Performance Highlights

|-------------------|---------------------------------|
| `@esmj/schema` | `~1,2 KB` |
| `@esmj/schema` | `~1,4 KB` |
| Superstruct | ~3.2 KB |

@@ -145,2 +228,283 @@ | @sinclair/typebox | ~11.7 KB |

## Modular Extensions
`@esmj/schema` provides modular extensions that can be imported individually or all together, allowing you to include only the validation helpers you need.
### Import Options
```typescript
// Minimal version (core only, ~1.4 KB)
import { s } from '@esmj/schema';
// Full version (all extensions included, ~4 KB)
import { s } from '@esmj/schema/full';
// String extensions only
import { s } from '@esmj/schema/string';
// Number extensions only
import { s } from '@esmj/schema/number';
// Array extensions only
import { s } from '@esmj/schema/array';
// Mix and match (side-effect imports)
import '@esmj/schema/string';
import '@esmj/schema/number';
import { s } from '@esmj/schema';
```
### Bundle Size Impact
- **Core only** (`@esmj/schema`): ~1.4 KB gzipped
- **String extensions** (`@esmj/schema/string`): +~0.8 KB
- **Number extensions** (`@esmj/schema/number`): +~0.6 KB
- **Array extensions** (`@esmj/schema/array`): +~0.5 KB
- **Full** (`@esmj/schema/full`): ~4 KB gzipped (all extensions)
**Recommendation:** Import only the extensions you need to minimize bundle size.
### String Extensions (`@esmj/schema/string`)
String extensions provide common validation and transformation methods for string schemas.
```typescript
import { s } from '@esmj/schema/string';
const userSchema = s.object({
username: s.string()
.trim() // Remove whitespace
.toLowerCase() // Convert to lowercase
.min(3) // Minimum 3 characters
.max(20) // Maximum 20 characters
.startsWith('user_'), // Must start with 'user_'
email: s.string()
.trim()
.toLowerCase()
.includes('@') // Must contain '@'
});
userSchema.parse({
username: ' USER_John ',
email: ' John@Example.com '
});
// ✓ { username: 'user_john', email: 'john@example.com' }
```
**Available String Methods:**
- **Length validations**: `min(length)`, `max(length)`, `length(exact)`, `nonEmpty()`
- **Pattern validations**: `startsWith(prefix)`, `endsWith(suffix)`, `includes(substring)`
- **Transformations**: `trim()`, `toLowerCase()`, `toUpperCase()`, `padStart(length, char)`, `padEnd(length, char)`, `replace(search, replace)`
### Number Extensions (`@esmj/schema/number`)
Number extensions provide validation methods for number schemas including range checks and type validations.
```typescript
import { s } from '@esmj/schema/number';
const productSchema = s.object({
price: s.number()
.positive() // Must be positive
.min(0.01) // Minimum value
.max(999999.99), // Maximum value
quantity: s.number()
.int() // Must be integer
.positive()
.min(1)
.max(1000),
discount: s.number()
.min(0)
.max(100)
.multipleOf(5) // Must be multiple of 5
});
productSchema.parse({
price: 29.99,
quantity: 5,
discount: 10
});
// ✓ { price: 29.99, quantity: 5, discount: 10 }
```
**Available Number Methods:**
- **Range validations**: `min(value)`, `max(value)`, `positive()`, `negative()`
- **Type validations**: `int()`, `float()`, `multipleOf(value)`, `finite()`
### Array Extensions (`@esmj/schema/array`)
Array extensions provide validation and transformation methods for array schemas.
```typescript
import { s } from '@esmj/schema/array';
const tagsSchema = s.object({
tags: s.array(s.string())
.min(1) // At least 1 item
.max(5) // At most 5 items
.unique() // All items must be unique
});
tagsSchema.parse({
tags: ['javascript', 'typescript', 'node']
});
// ✓ { tags: ['javascript', 'typescript', 'node'] }
```
**Available Array Methods:**
- **Size validations**: `min(length)`, `max(length)`, `length(exact)`, `nonEmpty()`
- **Content validations**: `unique()`
- **Transformations**: `sort()`, `reverse()`
### Full Extensions (`@esmj/schema/full`)
The full version includes all string, number, and array extensions in a single import.
```typescript
import { s } from '@esmj/schema/full';
const productSchema = s.object({
// String extensions
name: s.string()
.trim()
.min(3)
.max(100),
sku: s.string()
.toUpperCase()
.length(8)
.startsWith('PROD'),
// Number extensions
price: s.number()
.positive()
.min(0.01)
.max(999999.99),
stock: s.number()
.int()
.min(0),
// Array extensions
categories: s.array(s.string())
.min(1)
.max(5)
.unique(),
dimensions: s.array(s.number().positive())
.length(3) // [length, width, height]
});
```
**Custom Error Messages:**
All extension methods support custom error messages:
```typescript
const schema = s.object({
username: s.string().min(3, {
message: 'Username is too short! Please use at least 3 characters.'
}),
age: s.number().positive({
message: 'Age must be a positive number.'
}),
tags: s.array(s.string()).unique({
message: 'Duplicate tags are not allowed.'
})
});
```
## API Reference Summary
### Core Types
- `s.string()` - String validation
- `s.number()` - Number validation
- `s.boolean()` - Boolean validation
- `s.date()` - Date validation
- `s.object(def)` - Object validation
- `s.array(def)` - Array validation
- `s.enum(values)` - Enum validation
- `s.union(schemas)` - Union validation
- `s.any()` - Any type
- `s.null()` - Null type
- `s.undefined()` - Undefined type
- `s.unknown()` - Unknown type
### Modifiers
- `.optional()` - Makes field optional
- `.nullable()` - Makes field nullable
- `.nullish()` - Makes field optional and nullable
- `.default(value)` - Sets default value
### Transformations
- `.transform(fn)` - Transform value
- `s.preprocess(fn, schema)` - Preprocess before validation
- `.pipe(schema)` - Pipe to another schema
- `.refine(fn, opts)` - Custom validation
### String Extensions
Available when importing from `@esmj/schema/string` or `@esmj/schema/full`:
**Length Validations:**
- `.min(n)` - Minimum length
- `.max(n)` - Maximum length
- `.length(n)` - Exact length
- `.nonEmpty()` - Non-empty string
**Pattern Validations:**
- `.startsWith(prefix)` - Must start with prefix
- `.endsWith(suffix)` - Must end with suffix
- `.includes(substring)` - Must contain substring
**Transformations:**
- `.trim()` - Remove whitespace
- `.toLowerCase()` - Convert to lowercase
- `.toUpperCase()` - Convert to uppercase
- `.padStart(length, char)` - Pad start
- `.padEnd(length, char)` - Pad end
- `.replace(search, replace)` - Replace text
### Number Extensions
Available when importing from `@esmj/schema/number` or `@esmj/schema/full`:
**Range Validations:**
- `.min(n)` - Minimum value
- `.max(n)` - Maximum value
- `.positive()` - Must be positive
- `.negative()` - Must be negative
**Type Validations:**
- `.int()` - Must be integer
- `.float()` - Must be float (non-integer)
- `.multipleOf(n)` - Must be multiple of n
- `.finite()` - Must be finite
### Array Extensions
Available when importing from `@esmj/schema/array` or `@esmj/schema/full`:
**Size Validations:**
- `.min(n)` - Minimum length
- `.max(n)` - Maximum length
- `.length(n)` - Exact length
- `.nonEmpty()` - Non-empty array
**Content Validations:**
- `.unique()` - All items must be unique
**Transformations:**
- `.sort()` - Sort array
- `.reverse()` - Reverse array
### Schema Types

@@ -474,17 +838,47 @@

You can extend the schema system with custom logic.
You can extend the schema system with custom validation methods. This is useful for adding domain-specific validations like email or URL formats.
#### Basic Extension Example
```typescript
import { extend, type StringSchemaInterface } from '@esmj/schema';
import { extend, type SchemaType, type StringSchemaInterface } from '@esmj/schema';
interface StringSchemaInterface {
customMethod(value: string): string {}
// First, declare the new methods you want to add
declare module '@esmj/schema' {
interface StringSchemaInterface {
email(): StringSchemaInterface;
url(): StringSchemaInterface;
trim(): StringSchemaInterface;
}
}
extend((schema, validation, options) => {
schema.customMethod = (value) => {
// Custom logic
// Define validation patterns
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const URL_REGEX = /^(https?:\/\/[^\s$.?#].[^\s]*)$/;
return value;
};
// Extend the schema system
extend((schema: SchemaType, _, options) => {
// Only add methods to string schemas
if (options?.type === 'string') {
const stringSchema = schema as StringSchemaInterface;
// Add email validation
stringSchema.email = function() {
return this.refine((value) => EMAIL_REGEX.test(value), {
message: 'Invalid email format'
});
};
// Add URL validation
stringSchema.url = function() {
return this.refine((value) => URL_REGEX.test(value), {
message: 'Invalid URL format'
});
};
// Add string trimming
stringSchema.trim = function() {
return this.transform((value) => value.trim());
};
}

@@ -495,2 +889,92 @@ return schema;

#### Usage of Extended Schemas
Once extended, you can use your custom methods in schema definitions:
```typescript
const userSchema = s.object({
name: s.string().trim(),
email: s.string().email(),
website: s.string().url().optional()
});
// Valid data
userSchema.parse({
name: ' John Doe ', // Will be trimmed
email: 'john@example.com'
});
// Invalid data
try {
userSchema.parse({
name: 'John Doe',
email: 'not-an-email'
});
} catch (error) {
console.error(error); // "Invalid email format"
}
```
#### Advanced Extensions
You can extend any schema type and add complex validations:
```typescript
declare module '@esmj/schema' {
interface NumberSchemaInterface {
positive(): NumberSchemaInterface;
range(min: number, max: number): NumberSchemaInterface;
}
interface ArraySchemaInterface<T> {
minLength(length: number): ArraySchemaInterface<T>;
unique(): ArraySchemaInterface<T>;
}
}
extend((schema: SchemaType, _, options) => {
if (options?.type === 'number') {
const numberSchema = schema as NumberSchemaInterface;
numberSchema.positive = function() {
return this.refine((value) => value > 0, {
message: 'Number must be positive'
});
};
numberSchema.range = function(min, max) {
return this.refine((value) => value >= min && value <= max, {
message: `Number must be between ${min} and ${max}`
});
};
}
if (options?.type === 'array') {
const arraySchema = schema as ArraySchemaInterface<unknown>;
arraySchema.minLength = function(length) {
return this.refine((value) => value.length >= length, {
message: `Array must contain at least ${length} items`
});
};
arraySchema.unique = function() {
return this.refine((value) => {
const seen = new Set();
return value.every(item => {
const serialized = JSON.stringify(item);
if (seen.has(serialized)) return false;
seen.add(serialized);
return true;
});
}, { message: 'Array items must be unique' });
};
}
return schema;
});
```
This extension system gives you the flexibility to create domain-specific validation rules while maintaining type safety and the fluent API style.
### More Examples

@@ -662,2 +1146,162 @@

## Examples Folder
The `examples/` folder contains comprehensive, runnable examples demonstrating various use cases:
### Basic Usage (`examples/basic-usage.ts`)
Demonstrates the core validation features with strings, numbers, arrays, and unions:
```bash
node --experimental-strip-types examples/basic-usage.ts
```
### Custom Validation (`examples/custom-validation.ts`)
Shows how to create custom validators for common use cases:
- Email validation with regex
- URL validation
- Age range validation
- Password strength validation
- Cross-field validation (e.g., password confirmation)
```bash
node --experimental-strip-types examples/custom-validation.ts
```
### Advanced Forms (`examples/advanced-forms.ts`)
Real-world form validation examples:
- User profile schema with nested objects
- Address validation with postal codes
- Phone number formatting and validation
- API response validation
- Complex nested structures
```bash
node --experimental-strip-types examples/advanced-forms.ts
```
### Custom Extensions (`examples/custom-extensions.ts`)
Demonstrates how to extend the library with custom methods:
- Email validation extension
- URL validation extension
- UUID validation extension
- Combining custom extensions with built-in validators
```bash
node --experimental-strip-types examples/custom-extensions.ts
```
**To run all examples:**
```bash
# Using Node.js with experimental type stripping (built-in, no dependencies)
node --experimental-strip-types examples/basic-usage.ts
node --experimental-strip-types examples/custom-validation.ts
node --experimental-strip-types examples/advanced-forms.ts
node --experimental-strip-types examples/custom-extensions.ts
# OR using tsx (requires installation)
npm install -g tsx # If not already installed
npx tsx examples/basic-usage.ts
npx tsx examples/custom-validation.ts
npx tsx examples/advanced-forms.ts
npx tsx examples/custom-extensions.ts
```
## Migration Guide
### From Zod
`@esmj/schema` has a similar API to Zod, making migration straightforward:
```typescript
// Zod
import { z } from 'zod';
const userSchema = z.object({
name: z.string().min(3).max(50),
email: z.string().email(),
age: z.number().positive().int(),
role: z.enum(['admin', 'user']),
tags: z.array(z.string()).optional()
});
// @esmj/schema (with extensions)
import { s } from '@esmj/schema/full';
const userSchema = s.object({
name: s.string().min(3).max(50),
email: s.string(), // Note: email() validation requires custom extension
age: s.number().positive().int(),
role: s.enum(['admin', 'user']),
tags: s.array(s.string()).optional()
});
```
**Key Differences:**
| Feature | Zod | @esmj/schema |
|---------|-----|--------------|
| Import | `import { z } from 'zod'` | `import { s } from '@esmj/schema'` |
| Extensions | Built-in | Modular (`/string`, `/number`, `/array`, `/full`) |
| Bundle size | ~13 KB | ~1.4 KB (core), ~4 KB (full) |
| Email validation | `.email()` built-in | Custom extension (see [Extending Schemas](#extending-schemas)) |
| Error format | Native Error | Plain object `{ success, error, errors }` |
**Migration Tips:**
1. Replace `z` with `s` in your imports
2. For string methods like `.min()`, `.trim()`, import from `@esmj/schema/full` or `@esmj/schema/string`
3. Add custom extensions for email, URL validation (see examples below)
4. Update error handling to use the plain object structure
### From Yup
Migrating from Yup requires a few adjustments in syntax:
```typescript
// Yup
import * as yup from 'yup';
const userSchema = yup.object({
name: yup.string().required().min(3).max(50),
email: yup.string().required().email(),
age: yup.number().required().positive().integer(),
website: yup.string().url().nullable(),
tags: yup.array().of(yup.string()).min(1)
});
// @esmj/schema (with extensions)
import { s } from '@esmj/schema/full';
const userSchema = s.object({
name: s.string().min(3).max(50), // Fields are required by default
email: s.string(), // Note: email() validation requires custom extension
age: s.number().positive().int(),
website: s.string().nullable(),
tags: s.array(s.string()).min(1)
});
```
**Key Differences:**
| Feature | Yup | @esmj/schema |
|---------|-----|--------------|
| Required fields | `.required()` explicit | Required by default |
| Optional fields | Default behavior | `.optional()` explicit |
| Array of type | `.array().of(type)` | `.array(type)` |
| Integer | `.integer()` | `.int()` |
| Email validation | `.email()` built-in | Custom extension needed |
| Async validation | Supported | Not currently supported |
**Migration Tips:**
1. Remove `.required()` calls (fields are required by default)
2. Add `.optional()` for optional fields
3. Change `.array().of(type)` to `.array(type)`
4. Change `.integer()` to `.int()`
5. Add custom extensions for email, URL validation
## License

@@ -664,0 +1308,0 @@

type ErrorStructure = {
message: string;
cause?: {
key?: string;
};
};
type Valid<Output> = {
success: true;
data: Output;
};
type Invalid = {
success: false;
error: ErrorStructure;
errors?: ErrorStructure[];
};
type InternalParseOutput<Output> = Valid<Output> | Invalid;
interface ParseOptions {
abortEarly?: boolean;
}
interface SchemaInterface<Input, Output> {
_getType(): string;
_getDescription(): string;
_parse(value: Input | Partial<Input>, options?: ParseOptions): InternalParseOutput<Output>;
parse(value: Input | Partial<Input>, options?: ParseOptions): Output;
safeParse(value: Input | Partial<Input>, options?: ParseOptions): InternalParseOutput<Output>;
optional(): SchemaInterface<Input, Partial<Output> | undefined>;
transform<NewOutput>(callback: (value: Input) => NewOutput): SchemaInterface<Input, NewOutput>;
nullable(): SchemaInterface<Input, Output | null>;
nullish(): SchemaInterface<Input, Output | undefined | null>;
default(defaultValue: Partial<Input> | (() => Partial<Input>) | Partial<Output>): SchemaInterface<Input, Output>;
pipe<NewOutput>(schema: SchemaInterface<Output, NewOutput>): SchemaInterface<Output, NewOutput>;
refine(validation: (value: Output) => boolean, options?: SchemaInterfaceOptions): SchemaInterface<Input, Output>;
}
interface UnionSchemaInterface<T extends Array<SchemaInterface<unknown, unknown>>> extends SchemaInterface<ReturnType<T[number]['parse']>, ReturnType<T[number]['parse']>> {
}
interface EnumSchemaInterface<T extends string> extends SchemaInterface<string, T> {
}
interface StringSchemaInterface extends SchemaInterface<string, string> {
}
interface NumberSchemaInterface extends SchemaInterface<number, number> {
}
interface BooleanSchemaInterface extends SchemaInterface<boolean, boolean> {
}
interface DateSchemaInterface extends SchemaInterface<Date, Date> {
}
interface ArraySchemaInterface<T extends SchemaType> extends SchemaInterface<Array<T>, Array<ReturnType<T['parse']>>> {
}
interface ObjectSchemaInterface<T extends Record<string, SchemaType>> extends SchemaInterface<{
[Property in keyof T]: ReturnType<T[Property]['parse']>;
}, {
[Property in keyof T]: ReturnType<T[Property]['parse']>;
}> {
}
type SchemaType = StringSchemaInterface | SchemaInterface<unknown, unknown> | SchemaInterface<string, string> | SchemaInterface<string, string | undefined> | SchemaInterface<string, string | null> | SchemaInterface<string, string | undefined | null> | ObjectSchemaInterface<Record<string, SchemaType>> | SchemaInterface<object, object> | SchemaInterface<object, object | undefined> | SchemaInterface<object, object | null> | SchemaInterface<object, object | undefined | null> | NumberSchemaInterface | SchemaInterface<number, number> | SchemaInterface<number, number | undefined> | SchemaInterface<number, number | null> | SchemaInterface<number, number | undefined | null> | BooleanSchemaInterface | SchemaInterface<boolean, boolean> | SchemaInterface<boolean, boolean | undefined> | SchemaInterface<boolean, boolean | null> | SchemaInterface<boolean, boolean | undefined | null> | DateSchemaInterface | SchemaInterface<Date, Date> | SchemaInterface<Date, Date | undefined> | SchemaInterface<Date, Date | null> | SchemaInterface<Date, Date | undefined | null> | EnumSchemaInterface<string> | UnionSchemaInterface<Array<SchemaInterface<unknown, unknown>>> | ArraySchemaInterface<StringSchemaInterface | ObjectSchemaInterface<Record<string, SchemaType>> | NumberSchemaInterface | BooleanSchemaInterface | DateSchemaInterface | EnumSchemaInterface<string>> | SchemaInterface<Array<unknown>, Array<unknown>> | SchemaInterface<Array<unknown>, Array<unknown> | undefined> | SchemaInterface<Array<unknown>, Array<unknown> | null> | SchemaInterface<Array<unknown>, Array<unknown> | undefined | null>;
type ErrorMessage = string | ((value: unknown) => string);
type ExtenderType = (inter: SchemaType, validation: Function, options?: {
message: ErrorMessage;
type: string;
}) => SchemaType;
interface CreateSchemaInterfaceOptions {
type?: string;
message?: ErrorMessage;
}
type SchemaInterfaceOptions = Omit<CreateSchemaInterfaceOptions, 'type'>;
declare const s: {
object<T extends Record<string, SchemaType>>(definition: { [Property in keyof T]: T[Property]; }, options?: SchemaInterfaceOptions): ObjectSchemaInterface<T>;
string(options?: SchemaInterfaceOptions): StringSchemaInterface;
number(options?: SchemaInterfaceOptions): NumberSchemaInterface;
boolean(options?: SchemaInterfaceOptions): BooleanSchemaInterface;
date(options?: SchemaInterfaceOptions): DateSchemaInterface;
enum(definition: Readonly<Array<string>>, options?: SchemaInterfaceOptions): EnumSchemaInterface<(typeof definition)[number]>;
array<T extends SchemaType>(definition: T, options?: SchemaInterfaceOptions): ArraySchemaInterface<T>;
any(): any;
preprocess<T extends SchemaType>(callback: Function, schema: T): T;
union<T extends Array<SchemaType>>(definitions: T, options?: SchemaInterfaceOptions): UnionSchemaInterface<T>;
};
declare function extend(callback: ExtenderType): void;
type Infer<T> = T extends SchemaType ? ReturnType<T['parse']> : unknown;
export { type ArraySchemaInterface, type BooleanSchemaInterface, type DateSchemaInterface, type EnumSchemaInterface, type ExtenderType, type Infer, type NumberSchemaInterface, type ObjectSchemaInterface, type SchemaInterface, type SchemaInterfaceOptions, type SchemaType, type StringSchemaInterface, type UnionSchemaInterface, extend, s };
var g={abortEarly:true};function I(e,s){if(!s)return e;let c=e?.cause?.key?`${s}.${e.cause.key}`:`${s}`;return {message:`Error parsing key "${c}": ${e.message}`,cause:{key:c}}}function y(e,s,c){!e.errors||e.errors.length===0||e.errors.forEach(i=>{let o=I(i,c);s.push(o);});}function S(e){return {...g,...e}}var b=e=>typeof e=="string"||e instanceof String,O=e=>typeof e=="number"||e instanceof Number,P=e=>e===true||e===false,k=e=>e instanceof Date&&!Number.isNaN(e.getTime()),x=e=>Array.isArray(e),T=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),E={object(e,s){let c=h(T,{...s,type:"object"});return c._getDescription=()=>`object({ ${Object.entries(e).map(([o,t])=>`${o}: ${t._getDescription()}`).join(", ")} })`,m(c,"_parse",(i,o,t)=>{let r=i(o,t),{abortEarly:a}=S(t);if(r.success===false)return r;let n={},u=[];for(let p in e){let f=e[p]._parse(r.data[p],t);if(f.success)n[p]=f.data;else {if(f=f,a!==false){let l=I(f.error,p);return {success:false,error:l,errors:[l]}}y(f,u,p);}}return u.length>0?{success:false,error:u[0],errors:u}:{success:true,data:n}}),c},string(e){return h(b,{...e,type:"string"})},number(e){return h(O,{...e,type:"number"})},boolean(e){return h(P,{...e,type:"boolean"})},date(e){return h(k,{...e,type:"date"})},enum(e,s){let c=r=>e.includes(r),i=r=>`Invalid ${o} value. Expected ${e.map(a=>`"${a}"`).join(" | ")}, received "${r}".`,o="enum",t=h(c,{message:i,...s,type:o});return t._getDescription=()=>`enum(${e.map(r=>`"${r}"`).join(" | ")})`,t},array(e,s){let c=h(x,{...s,type:"array"});return c._getDescription=()=>`array(${e._getDescription()})`,m(c,"_parse",(i,o,t)=>{let r=i(o,t),{abortEarly:a}=S(t);if(r.success===false)return r;let n=[],u=[];for(let p=0;p<r.data.length;p++){let f=e._parse(r.data[p],t);if(f.success)n.push(f.data);else {if(f=f,a!==false){let l=I(f.error,p);return {success:false,error:l,errors:[l]}}y(f,u,p);}}return u.length>0?{success:false,error:u[0],errors:u}:{success:true,data:n}}),c},any(){return h(()=>true)},preprocess(e,s){return m(s,"_parse",(c,i)=>(i=e(i),c(i))),s},union(e,s){return h(t=>{for(let r=0;r<e.length;r++)if(e[r]._parse(t).success)return true;return false},{message:t=>`Invalid union value. Expected the value to match one of the schemas:${e.map((r,a)=>` ${a+1}. ${r._getDescription()}`).join(",")} but received "${typeof t}" with value: ${T(t)?JSON.stringify(t):`"${t}"`}`,...s,type:"union"})}};function w(e){return s=>`The value "${s}" must be type of ${e} but is type of "${typeof s}".`}function m(e,s,c){let i=e[s];e[s]=(...o)=>c(i,...o);}function h(e,{type:s="any",message:c}={}){c=c||w(s);let i={message:c,type:s},o={_getType(){return s},_getDescription(){return this._getType()},_parse(t,r){if(e(t))return {success:true,data:t};let n={message:typeof c=="function"?c(t):c};return {success:false,error:n,errors:[n]}},parse(t,r){let a=o._parse(t,r);if(!a.success)throw a=a,new Error(a.error.message,{cause:a.error.cause});return a.data},safeParse(t,r){return o._parse(t,r)},transform(t){return m(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success&&(u.data=t(u.data)),u}),this},optional(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return n.success||(n.data=void 0,n.success=true),n}),this},nullable(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return n.success||(n.data=null,n.success=true),n}),this},nullish(){return m(this,"_parse",(t,r,a)=>{let n=t(r,a);return !n.success&&r==null&&(n.success=true,n.data=r),n}),this},default(t){return m(this,"_parse",(r,a,n)=>(a===void 0&&(a=t,a=typeof t=="function"?t():t),r(a,n))),this},pipe(t){return m(this,"_parse",(r,a,n)=>{let u=r(a,n);return u.success?t._parse(u.data,n):u}),this},refine(t,{message:r}={}){return m(this,"_parse",(a,n,u)=>{let p=a(n,u);if(!p.success)return p;if(!t(p.data)){let f=typeof r=="function"?r(n):r;return {success:false,error:{message:f},errors:[{message:f}]}}return p}),this}};return d.length>0?d.reduce((t,r)=>r(t,e,i)??t,o):o}var d=[];function _(e){d.push(e);}export{_ as extend,E as s};