validator-fns 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -284,7 +284,7 @@ To use this with a library such as [Formik][formik], you can use the resulting `
284
284
 
285
285
  Casts value to a string, `null` or `undefined` if using the default string parser. `config` is optional.
286
286
 
287
- Supported validation tests: `email`, `exact`, `matches`, `max`, `min`, `oneOf`, `required`, and `url`.
287
+ Supported validation tests: `email`, `exact`, `matches`, `max`, `min`, `oneOf`, `required`, `url`, and `uuid`.
288
288
 
289
289
  <details><summary>config</summary>
290
290
 
@@ -311,6 +311,7 @@ A **validation test** is a simplified version of a validation type. It accepts a
311
311
  - [oneOf(values, message)](#oneofvalues-message)
312
312
  - [required(message, nullable?)](#requiredmessage-nullable)
313
313
  - [url(message, protocols?)](#urlmessage-protocols)
314
+ - [uuid(message)](#uuidmessage)
314
315
 
315
316
  #### email(message)
316
317
 
@@ -459,14 +460,26 @@ Ensures value is a valid URL. Works with strings. `protocols` is provided to the
459
460
 
460
461
  </details>
461
462
 
463
+ #### uuid(message)
464
+
465
+ Ensures the value is a UUID as defined by [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562): any version from 1 to 8 with the RFC's variant, or the nil or max UUID. Case-insensitive. Braces, a `urn:uuid:` prefix, and missing hyphens are invalid. Wraps the `matches` validation test. Works with strings.
466
+
467
+ <details><summary>arguments</summary>
468
+
469
+ | name | type | description |
470
+ | :-------- | :----------------- | :---------------------------- |
471
+ | `message` | string or function | The validation error message. |
472
+
473
+ </details>
474
+
462
475
  ### Custom validation
463
476
 
464
477
  Custom validation types and validators can be created and used as needed. There are some helpers that, while used internally, are considered part of the public API.
465
478
 
466
479
  - [formatMessage(template, params)](#formatmessagetemplate-params)
467
480
  - [createTypeValidatorTest(defaultConfig, applyConfig)](#createtypevalidatortestdefaultconfig-applyconfig)
468
- - [valid(value, field)](#validvalue-field)
469
- - [invalid(message, value, field, extras)](#invalidmessage-value-field-extras)
481
+ - [valid({ value, field })](#valid-value-field-)
482
+ - [invalid({ message, value, field, errors, extras })](#invalid-message-value-field-errors-extras-)
470
483
 
471
484
  #### formatMessage(template, params)
472
485
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var E=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.prototype.hasOwnProperty;var re=(e,r)=>{for(var t in r)E(e,t,{get:r[t],enumerable:!0})},ae=(e,r,t,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of ee(r))!te.call(e,n)&&n!==t&&E(e,n,{get:()=>r[n],enumerable:!(a=v(r,n))||a.enumerable});return e};var ne=e=>ae(E({},"__esModule",{value:!0}),e);var fe={};re(fe,{applyArrayConfig:()=>k,applyBooleanConfig:()=>N,applyDateConfig:()=>O,applyNumberConfig:()=>R,applyStringConfig:()=>B,array:()=>U,boolean:()=>q,createTypeValidatorTest:()=>g,createValidatorTest:()=>l,date:()=>G,email:()=>W,exact:()=>$,formatMessage:()=>h,hasOwnProperty:()=>P,integer:()=>H,invalid:()=>p,invalidDate:()=>M,isObject:()=>b,matches:()=>j,max:()=>F,maxDate:()=>_,min:()=>Z,minDate:()=>L,number:()=>J,object:()=>Q,oneOf:()=>K,parseArray:()=>C,parseBoolean:()=>S,parseDate:()=>T,parseNumber:()=>A,parseString:()=>I,required:()=>z,string:()=>Y,url:()=>X,valid:()=>m});module.exports=ne(fe);function b(e){return Object.prototype.toString.call(e)==="[object Object]"}function P(e,r){return Object.prototype.hasOwnProperty.call(e,r)}var se=/{(\w+)}/g;function h(e,r){return typeof e=="string"?e.replaceAll(se,(t,a)=>String(r[a])):e(r)}async function m({value:e,field:r}){return{isValid:!0,state:"valid",value:e,field:r}}async function p({errors:e,field:r,message:t,value:a,extras:n}){return{isValid:!1,state:"invalid",message:h(t,{...n,value:a,field:r}),value:a,field:r,errors:e}}function g(e,r){return(t,...a)=>{let n=e,o=a;return t!==void 0&&(typeof t=="function"?o=[t,...a]:n={...e,...t}),async(d,s)=>{try{let i=r(d,n);for(let f of o){let u=await f(i,s);if(u.state==="invalid")return u}return await m({value:i,field:s})}catch(i){return p({message:i instanceof Error?i.message:String(i),value:d,field:s})}}}}function l(e,r,t){return async(a,n)=>e(a,n)?m({value:a,field:n}):p({message:r,value:a,field:n,extras:t?t(a):void 0})}function z(e,r){return l(t=>r&&t===null||t!=null&&!(typeof t=="string"&&t==="")&&!(typeof t=="number"&&Number.isNaN(t))&&!(t instanceof Date&&Number.isNaN(t.valueOf())),e)}function c(e){return typeof e=="string"||Array.isArray(e)?e.length:e}function F(e,r,t){return l(a=>{let n=c(a);return n==null||a===""||(t?n<e:n<=e)},r,a=>({max:e,limit:e,amount:c(a),exclusive:t}))}function Z(e,r,t){return l(a=>{let n=c(a);return n==null||a===""||(t?n>e:n>=e)},r,a=>({min:e,limit:e,amount:c(a),exclusive:t}))}function $(e,r){return l(t=>{let a=c(t);return a==null||t===""||a===e},r,t=>({amount:c(t),limit:e,exact:e}))}function K(e,r){return l(t=>t==null||e.includes(t)||t instanceof Date&&e.some(a=>a.valueOf()===t.valueOf()),r,()=>({values:e}))}function C(e){if(Array.isArray(e)||e==null)return e;let r=e;return r[Symbol.iterator]?[...r]:[]}function k(e,r){let t=e.parser(r);return e.default!==void 0&&(t==null||t.length===0)&&(t=e.default),t}function U(e,...r){let t=r,a={parser:C};return e!==void 0&&(typeof e=="function"?t=[e,...r]:a={...a,...e}),async(n,o)=>{let d=k(a,n),s,i=!0,f=[],[u,...w]=t;for(let V of w){let x=await V(d,o);if(x.state==="invalid"){i=!1,s=x;break}}if(d&&u)for(let[V,x]of d.entries()){let D=await u(x,o?`${o}[${V}]`:`[${V}]`);D.state==="invalid"?(i=!1,f.push(D.message||D.errors)):f.push(null)}return i?m({value:d,field:o}):p({message:s?.state==="invalid"?s.message:"",value:n,field:o,errors:f})}}function S(e){return e==null||typeof e=="boolean"?e:!!e}function N(e,r){let t=r.parser(e);return r.default!==void 0&&t==null&&(t=r.default),t}var q=g({parser:S},N);var M=new Date(""),oe=/^(\d{4})(?:-([0-2]\d)(?:-([0-3]\d)(?:[ T]([0-2]\d):([0-5]\d)(?::([0-5]\d)(\.\d+)?(Z|[+-][0-2]\d:?[0-5]\d)?)?)?)?)?$/,ie=/^([+-])([0-2]\d):?([0-5]\d)$/;function de(e){let r=ie.exec(e);if(e==="Z"||!r)return 0;let[,t,a="0",n="0"]=r,o=t==="-"?-1:1,s=Number.parseInt(a,10)*60+Number.parseInt(n,10);return o*s}var y=10,le=[()=>0,(e="0")=>Number.parseInt(e,y),(e="1")=>Number.parseInt(e,y)-1,(e="1")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseFloat(e)*1e3];function T(e){if(e==null||e instanceof Date)return e;if(typeof e=="number")return new Date(e);if(typeof e!="string")return M;let r=oe.exec(e);if(r===null)return M;let[,t=0,a=0,n=0,o=0,d=0,s=0,i=0]=le.map((w,V)=>w(r[V])),f=r[8];if(!f)return new Date(t,a,n,o,d,s,i);let u=de(f);return new Date(Date.UTC(t,a,n,o,d+u,s,i))}function O(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||Number.isNaN(t.getTime()))&&(t=r.default),t}function L(e,r,t){let a=T(e);return l(n=>a!=null&&(n==null||n instanceof Date&&(t?n>a:n>=a)),r,()=>({min:a,limit:a,exclusive:t}))}function _(e,r,t){let a=T(e);return l(n=>a!=null&&(n==null||n instanceof Date&&(t?n<a:n<=a)),r,()=>({max:a,limit:a,exclusive:t}))}var G=g({parser:T},O);function A(e){return e==null||typeof e=="number"?e:e instanceof Date?e.getTime():typeof e=="string"?Number.parseFloat(e):Number.parseFloat(String(e))}function R(e,r){let t=r.parser(e);if(r.default!==void 0&&(t==null||Number.isNaN(t))&&(t=r.default),r.round&&typeof t=="number")switch(r.round){case"nearest":{t=Math.round(t);break}case"ceil":{t=Math.ceil(t);break}case"floor":{t=Math.floor(t);break}default:throw new Error(`Unknown round type: ${String(r.round)}`)}return t}function H(e){return async(r,t)=>r==null||typeof r=="number"&&Number.isFinite(r)&&Math.floor(r)===r?m({value:r,field:t}):p({message:e,value:r,field:t})}var J=g({parser:A},R);function Q(e){if(typeof e!="object"||e===null)throw new TypeError("`properties` must be a configuration object");return async(r,t)=>{let a=r??{},n={},o={},d=!0;for(let s in e)if(P(e,s)){let i=e[s],f=a[s],u=typeof i=="function"?await i(f,s):await p({field:s,message:"No validator set",value:f});o[s]=u.value,u.state==="invalid"&&(d=!1,n[s]=u.message||u.errors)}return d?m({value:o,field:t}):p({message:"",value:r,field:t,errors:n})}}var ue=/^[\w!#$%&'*+./=?^`{|}~-]+@[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?(?:\.[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?)*$/;function I(e){if(e==null||typeof e=="string")return e;if(e instanceof Date)return e.toISOString();if(b(e))throw new TypeError("Failed to parse value to string.");return String(e)}function B(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||t==="")&&(t=r.default),r.trim&&typeof t=="string"&&(t=t.trim()),t}function j(e,r){let t=new RegExp(e);return l(a=>(t.lastIndex=0,a==null||a===""||typeof a=="string"&&t.test(a)),r,()=>({pattern:e}))}function W(e){return j(ue,e)}function X(e,r){return l(t=>{try{let a;if(t==null||t===""||typeof t=="string"&&(a=new URL(t)))return!(a&&r&&!r.includes(a.protocol))}catch{}return!1},e,()=>({protocols:r}))}var Y=g({parser:I},B);0&&(module.exports={applyArrayConfig,applyBooleanConfig,applyDateConfig,applyNumberConfig,applyStringConfig,array,boolean,createTypeValidatorTest,createValidatorTest,date,email,exact,formatMessage,hasOwnProperty,integer,invalid,invalidDate,isObject,matches,max,maxDate,min,minDate,number,object,oneOf,parseArray,parseBoolean,parseDate,parseNumber,parseString,required,string,url,valid});
1
+ "use strict";var M=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var ee=(e,r)=>{for(var t in r)M(e,t,{get:r[t],enumerable:!0})},te=(e,r,t,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of Y(r))!v.call(e,n)&&n!==t&&M(e,n,{get:()=>r[n],enumerable:!(a=X(r,n))||a.enumerable});return e};var re=e=>te(M({},"__esModule",{value:!0}),e);var me={};ee(me,{applyArrayConfig:()=>C,applyBooleanConfig:()=>E,applyDateConfig:()=>k,applyNumberConfig:()=>N,applyStringConfig:()=>O,array:()=>I,boolean:()=>R,createTypeValidatorTest:()=>g,createValidatorTest:()=>d,date:()=>F,email:()=>G,exact:()=>_,formatMessage:()=>D,hasOwnProperty:()=>x,integer:()=>$,invalid:()=>f,invalidDate:()=>b,isObject:()=>T,matches:()=>P,max:()=>q,maxDate:()=>j,min:()=>L,minDate:()=>B,number:()=>z,object:()=>Z,oneOf:()=>U,parseArray:()=>w,parseBoolean:()=>h,parseDate:()=>c,parseNumber:()=>S,parseString:()=>A,required:()=>K,string:()=>Q,url:()=>J,uuid:()=>H,valid:()=>m});module.exports=re(me);function T(e){return Object.prototype.toString.call(e)==="[object Object]"}function x(e,r){return Object.prototype.hasOwnProperty.call(e,r)}var ae=/{(\w+)}/g;function D(e,r){return typeof e=="string"?e.replaceAll(ae,(t,a)=>String(r[a])):e(r)}async function m({value:e,field:r}){return{isValid:!0,state:"valid",value:e,field:r}}async function f({errors:e,field:r,message:t,value:a,extras:n}){return{isValid:!1,state:"invalid",message:D(t,{...n,value:a,field:r}),value:a,field:r,errors:e}}function w(e){if(Array.isArray(e)||e==null)return e;let r=e;return r[Symbol.iterator]?[...r]:[]}function C(e,r){let t=e.parser(r);return e.default!==void 0&&(t==null||t.length===0)&&(t=e.default),t}async function ne(e,r,t){for(let a of e){let n=await a(r,t);if(n.state==="invalid")return n}}async function oe(e,r,t){let a=!0,n=[];if(!r||!e)return{isValid:a,errors:n};for(let[s,i]of r.entries()){let o=await e(i,t?`${t}[${s}]`:`[${s}]`);o.state==="invalid"?(a=!1,n.push(o.message||o.errors)):n.push(null)}return{isValid:a,errors:n}}function I(e,...r){let t=r,a={parser:w};return e!==void 0&&(typeof e=="function"?t=[e,...r]:a={...a,...e}),async(n,s)=>{let i=C(a,n),[o,...l]=t,p=await ne(l,i,s),u=await oe(o,i,s);return!p&&u.isValid?m({value:i,field:s}):f({message:p?p.message:"",value:n,field:s,errors:u.errors})}}function g(e,r){return(t,...a)=>{let n=e,s=a;return t!==void 0&&(typeof t=="function"?s=[t,...a]:n={...e,...t}),async(i,o)=>{try{let l=r(i,n);for(let p of s){let u=await p(l,o);if(u.state==="invalid")return u}return await m({value:l,field:o})}catch(l){return f({message:l instanceof Error?l.message:String(l),value:i,field:o})}}}}function d(e,r,t){return async(a,n)=>e(a,n)?m({value:a,field:n}):f({message:r,value:a,field:n,extras:t?t(a):void 0})}function h(e){return e==null||typeof e=="boolean"?e:!!e}function E(e,r){let t=r.parser(e);return r.default!==void 0&&t==null&&(t=r.default),t}var R=g({parser:h},E);var b=new Date(""),se=/^(\d{4})(?:-([0-2]\d)(?:-([0-3]\d)(?:[ T]([0-2]\d):([0-5]\d)(?::([0-5]\d)(\.\d+)?(Z|[+-][0-2]\d:?[0-5]\d)?)?)?)?)?$/,ie=/^([+-])([0-2]\d):?([0-5]\d)$/;function de(e){let r=ie.exec(e);if(e==="Z"||!r)return 0;let[,t,a="0",n="0"]=r,s=t==="-"?-1:1,o=Number.parseInt(a,10)*60+Number.parseInt(n,10);return s*o}var V=10,le=[()=>0,(e="0")=>Number.parseInt(e,V),(e="1")=>Number.parseInt(e,V)-1,(e="1")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseFloat(e)*1e3];function c(e){return e==null||e instanceof Date?e:typeof e=="number"?new Date(e):typeof e=="string"?ue(e):b}function ue(e){let r=se.exec(e);if(r===null)return b;let[,t=0,a=0,n=0,s=0,i=0,o=0,l=0]=le.map((u,W)=>u(r[W])),p=r[8];return p?new Date(Date.UTC(t,a,n,s,i+de(p),o,l)):new Date(t,a,n,s,i,o,l)}function k(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||Number.isNaN(t.getTime()))&&(t=r.default),t}function B(e,r,t){let a=c(e);return d(n=>a!=null&&(n==null||n instanceof Date&&(t?n>a:n>=a)),r,()=>({min:a,limit:a,exclusive:t}))}function j(e,r,t){let a=c(e);return d(n=>a!=null&&(n==null||n instanceof Date&&(t?n<a:n<=a)),r,()=>({max:a,limit:a,exclusive:t}))}var F=g({parser:c},k);function S(e){return e==null||typeof e=="number"?e:e instanceof Date?e.getTime():typeof e=="string"?Number.parseFloat(e):Number.parseFloat(String(e))}function N(e,r){let t=r.parser(e);if(r.default!==void 0&&(t==null||Number.isNaN(t))&&(t=r.default),r.round&&typeof t=="number")switch(r.round){case"nearest":{t=Math.round(t);break}case"ceil":{t=Math.ceil(t);break}case"floor":{t=Math.floor(t);break}default:throw new Error(`Unknown round type: ${String(r.round)}`)}return t}function $(e){return async(r,t)=>r==null||typeof r=="number"&&Number.isFinite(r)&&Math.floor(r)===r?m({value:r,field:t}):f({message:e,value:r,field:t})}var z=g({parser:S},N);function Z(e){if(typeof e!="object"||e===null)throw new TypeError("`properties` must be a configuration object");return async(r,t)=>{let a=r??{},n={},s={},i=!0;for(let o in e)if(x(e,o)){let l=e[o],p=a[o],u=typeof l=="function"?await l(p,o):await f({field:o,message:"No validator set",value:p});s[o]=u.value,u.state==="invalid"&&(i=!1,n[o]=u.message||u.errors)}return i?m({value:s,field:t}):f({message:"",value:r,field:t,errors:n})}}function K(e,r){return d(t=>r&&t===null||t!=null&&!(typeof t=="string"&&t==="")&&!(typeof t=="number"&&Number.isNaN(t))&&!(t instanceof Date&&Number.isNaN(t.valueOf())),e)}function U(e,r){return d(t=>t==null||e.includes(t)||t instanceof Date&&e.some(a=>a.valueOf()===t.valueOf()),r,()=>({values:e}))}function y(e){return typeof e=="string"||Array.isArray(e)?e.length:e}function q(e,r,t){return d(a=>{let n=y(a);return n==null||a===""||(t?n<e:n<=e)},r,a=>({max:e,limit:e,amount:y(a),exclusive:t}))}function L(e,r,t){return d(a=>{let n=y(a);return n==null||a===""||(t?n>e:n>=e)},r,a=>({min:e,limit:e,amount:y(a),exclusive:t}))}function _(e,r){return d(t=>{let a=y(t);return a==null||t===""||a===e},r,t=>({amount:y(t),limit:e,exact:e}))}var fe=/^[\w!#$%&'*+./=?^`{|}~-]+@[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?(?:\.[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?)*$/,pe=/^(?:[\da-f]{8}-[\da-f]{4}-[1-8][\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}|0{8}-0{4}-0{4}-0{4}-0{12}|f{8}-f{4}-f{4}-f{4}-f{12})$/i;function A(e){if(e==null||typeof e=="string")return e;if(e instanceof Date)return e.toISOString();if(T(e))throw new TypeError("Failed to parse value to string.");return String(e)}function O(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||t==="")&&(t=r.default),r.trim&&typeof t=="string"&&(t=t.trim()),t}function P(e,r){let t=new RegExp(e);return d(a=>(t.lastIndex=0,a==null||a===""||typeof a=="string"&&t.test(a)),r,()=>({pattern:e}))}function G(e){return P(fe,e)}function H(e){return P(pe,e)}function J(e,r){return d(t=>{try{let a;if(t==null||t===""||typeof t=="string"&&(a=new URL(t)))return!(a&&r&&!r.includes(a.protocol))}catch{}return!1},e,()=>({protocols:r}))}var Q=g({parser:A},O);0&&(module.exports={applyArrayConfig,applyBooleanConfig,applyDateConfig,applyNumberConfig,applyStringConfig,array,boolean,createTypeValidatorTest,createValidatorTest,date,email,exact,formatMessage,hasOwnProperty,integer,invalid,invalidDate,isObject,matches,max,maxDate,min,minDate,number,object,oneOf,parseArray,parseBoolean,parseDate,parseNumber,parseString,required,string,url,uuid,valid});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/shared.ts","../src/arrays.ts","../src/booleans.ts","../src/dates.ts","../src/numbers.ts","../src/objects.ts","../src/strings.ts"],"sourcesContent":["/* istanbul ignore file */\nexport { applyArrayConfig, array, parseArray } from './arrays';\nexport type { ArrayConfig, ArrayItemValidatorResult } from './arrays';\nexport { applyBooleanConfig, boolean, parseBoolean } from './booleans';\nexport type { BooleanConfig } from './booleans';\nexport {\n applyDateConfig,\n date,\n invalidDate,\n maxDate,\n minDate,\n parseDate,\n} from './dates';\nexport type {\n DateConfig,\n MaxDateValidatorMessageParameters,\n MinDateValidatorMessageParameters,\n SharedDateValueType,\n} from './dates';\nexport { applyNumberConfig, integer, number, parseNumber } from './numbers';\nexport type { NumberConfig } from './numbers';\nexport { object } from './objects';\nexport type { ObjectParameter as ObjectParam } from './objects';\nexport {\n createTypeValidatorTest,\n createValidatorTest,\n exact,\n formatMessage,\n hasOwnProperty,\n invalid,\n isObject,\n max,\n min,\n oneOf,\n required,\n valid,\n} from './shared';\nexport type {\n ConfigBase,\n DeepPartial,\n ExactValidatorMessageParameters,\n ExtractError,\n ExtractValue,\n InvalidResult,\n MaxValidatorMessageParameters,\n MinValidatorMessageParameters,\n OneOfValidatorMessageParameters,\n SharedValueType,\n ValidatorFactory,\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorResult,\n ValidatorTest,\n ValidResult,\n} from './shared';\nexport {\n applyStringConfig,\n email,\n matches,\n parseString,\n string,\n url,\n} from './strings';\nexport type {\n MatchesValidatorMessageParameters,\n StringConfig,\n} from './strings';\n","export type ValidResult<T> = {\n /**\n * True if the original value is valid according to all validation tests\n * @deprecated Use `state` instead.\n */\n isValid: true;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'valid';\n /** The parsed value. Note that may be different than the original value. */\n value: T | null | undefined;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n};\n\nexport type InvalidResult<E> = {\n /**\n * True if the original value is valid according to all validation tests.\n * @deprecated Use `state` instead.\n */\n isValid: false;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'invalid';\n /** The parsed value. Note that may be different than the original value. */\n value: unknown;\n /** Error message if `state` is invalid. */\n message: string;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n /** Extra error details */\n errors?: E | undefined;\n};\n\n/**\n * The result of a validation.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorResult<T = any, E = any> =\n | ValidResult<T>\n | InvalidResult<E>;\n\n/**\n * Validation test function.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorTest<T = any, E = any> = (\n value?: unknown,\n field?: string,\n) => Promise<ValidatorResult<T, E>>;\n\n/**\n * Extracts the generic error type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractError<T extends ValidatorTest> =\n T extends ValidatorTest<any, infer E> ? E : unknown;\n\n/**\n * Extracts the generic value type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractValue<T extends ValidatorTest> =\n T extends ValidatorTest<infer V> ? V : unknown;\n\n/**\n * Make a deep partial type.\n * @typeParam T any object type\n * @category Types\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n\n/**\n * Validation factory function.\n * @typeParam C The configuration type\n * @category Types\n */\nexport type ValidatorFactory<C, T, E> = (\n config?: Partial<C> | ValidatorTest,\n ...tests: ValidatorTest[]\n) => ValidatorTest<T, E>;\n\n/**\n * Base configuration type.\n * @typeParam T The target type.\n * @category Types\n */\nexport interface ConfigBase<T> {\n /** Parser to convert value into the designated type. */\n parser: (value: unknown) => T | null | undefined;\n /** Provide a fallback value in case the original value is undefined. */\n default?: T;\n}\n\nexport interface ValidatorMessageParameters<T> {\n value: T | null | undefined;\n field: string | undefined;\n}\n\n/**\n * Validation message. May be a plain string or a function that accepts arguments.\n * While using a string, values in squiggly brackets `{}` are replaced.\n * @category Types\n */\nexport type ValidatorMessage<\n T,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n> = string | ((parameters: P) => string);\n\n/**\n * Simple check for objects.\n * @param value Value to test\n */\nexport function isObject(value: unknown): boolean {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/**\n * Safe hasOwnProperty check\n * @param object Object to check\n * @param property Property to look for\n */\nexport function hasOwnProperty(\n object: unknown,\n property: string | number | symbol,\n): boolean {\n return Object.prototype.hasOwnProperty.call(object, property);\n}\n\n/** @internal */\nconst formatPattern = /{(\\w+)}/g;\n\n/**\n * Formats a message using a squiggly bracket `{}` template.\n * @param template Message template as string or function\n * @param parameters Params to inject into template\n * @category Helpers\n */\nexport function formatMessage<T, P extends ValidatorMessageParameters<T>>(\n template: ValidatorMessage<T, P>,\n parameters: P,\n): string {\n if (typeof template === 'string') {\n return template.replaceAll(formatPattern, (_, key: string) =>\n String((parameters as Record<string, unknown>)[key]),\n );\n }\n\n return template(parameters);\n}\n\n/**\n * Creates a valid result\n * @param value Parsed value\n * @param field Field name\n * @category Helpers\n */\nexport async function valid<T, E = never>({\n value,\n field,\n}: {\n value: T | null | undefined;\n field: string | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: true,\n state: 'valid',\n value,\n field,\n };\n}\n\n/**\n * Creates an invalid result.\n * @param message Error message\n * @param value Parsed value\n * @param field Field name\n * @param extras Extra message params\n * @category Helpers\n */\nexport async function invalid<\n T,\n E,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>({\n errors,\n field,\n message,\n value,\n extras,\n}: {\n message: ValidatorMessage<T, P>;\n value: unknown;\n field: string | undefined;\n errors?: E | undefined;\n extras?: Omit<P, 'field' | 'value'> | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: false,\n state: 'invalid',\n message: formatMessage(message, { ...extras, value, field } as P),\n value,\n field,\n errors,\n };\n}\n\n/**\n * Creates a type validator.\n * @typeParam T The basic type for the final value to be validated.\n * @typeParam C The configuration type.\n * @param defaultParser Parser to convert value into type.\n * @param applyConfig Function that applies configuration to value.\n * @category Helpers\n */\nexport function createTypeValidatorTest<T, C extends ConfigBase<T>>(\n defaultConfig: C,\n applyConfig: (value: unknown, config: C) => T | null | undefined,\n): ValidatorFactory<C, T, string> {\n return (config, ...tests) => {\n let finalConfig = defaultConfig;\n let allTests = tests;\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...defaultConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n try {\n const parsedValue = applyConfig(value, finalConfig);\n for (const validatorTest of allTests) {\n const result = await validatorTest(parsedValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return await valid({ value: parsedValue, field });\n } catch (error) {\n return invalid({\n message: error instanceof Error ? error.message : String(error),\n value,\n field,\n });\n }\n };\n };\n}\n\n/**\n * Captures basic validator test pattern\n * @param test Test function\n * @param message Error message\n * @param getExtras Optional extra fields for error message\n */\nexport function createValidatorTest<\n T = any,\n E = any,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>(\n test: (value: unknown, field?: string) => boolean,\n message: ValidatorMessage<T, P>,\n getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>,\n): ValidatorTest<T, E> {\n return async (value, field) => {\n if (test(value, field)) {\n return valid({ value: value as T, field });\n }\n\n return invalid({\n message,\n value,\n field,\n extras: getExtras ? getExtras(value as T) : undefined,\n });\n };\n}\n\n/**\n * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.\n * @param message Error message\n * @param nullable Allow null values\n * @category Validation Tests\n */\nexport function required<T, P extends ValidatorMessageParameters<T>>(\n message: ValidatorMessage<T, P>,\n nullable?: boolean,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n (nullable && value === null) ||\n (value !== null &&\n value !== undefined &&\n !(typeof value === 'string' && value === '') &&\n !(typeof value === 'number' && Number.isNaN(value)) &&\n !(value instanceof Date && Number.isNaN(value.valueOf()))),\n message,\n );\n}\n\nexport type SharedValueType = string | number | unknown[];\n\n/**\n * Extracts a numeric amount from value, i.e. string length, array length, or number.\n * @internal\n */\nfunction getAmount(value: SharedValueType | null | undefined) {\n return typeof value === 'string' || Array.isArray(value)\n ? value.length\n : value;\n}\n\nexport interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n max: number;\n amount: number | null | undefined;\n limit: number;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function max(\n limit: number,\n message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount < limit : amount <= limit)\n );\n },\n message,\n (value) => ({\n max: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n min: number;\n limit: number;\n amount: number | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function min(\n limit: number,\n message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount > limit : amount >= limit)\n );\n },\n message,\n (value) => ({\n min: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n limit: number;\n amount: number | null | undefined;\n exact: number;\n}\n\n/**\n * Ensures a string, number, or array value is exactly a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @category Validation Tests\n */\nexport function exact(\n limit: number,\n message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n amount === limit\n );\n },\n message,\n (value) => ({\n amount: getAmount(value),\n limit,\n exact: limit,\n }),\n );\n}\n\nexport interface OneOfValidatorMessageParameters<\n T,\n> extends ValidatorMessageParameters<T> {\n values: readonly T[];\n}\n\n/**\n * Ensures a value is one in a predefined list.\n * @param values List of allowed values.\n * @param message Error message\n * @category Validation Tests\n */\nexport function oneOf<T extends string | number | boolean | Date>(\n values: readonly T[],\n message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n value === undefined ||\n value === null ||\n values.includes(value as T) ||\n (value instanceof Date &&\n values.some((x) => x.valueOf() === value.valueOf())),\n message,\n () => ({ values }),\n );\n}\n","import {\n invalid,\n valid,\n type ConfigBase,\n type ValidatorResult,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Invalid validation result for an item in the array\n * @category Types\n */\nexport type ArrayItemValidatorResult<E = unknown> = null | string | E;\n\n/**\n * Configuration for array validation.\n * @category Types\n */\nexport type ArrayConfig = ConfigBase<unknown[]>;\n\n/**\n * Parses a value into an array.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseArray(value: unknown): unknown[] | null | undefined {\n if (Array.isArray(value)) {\n return value as unknown[];\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n const iterable = value as Iterable<unknown>;\n\n if (iterable[Symbol.iterator]) {\n return [...iterable];\n }\n\n return [];\n}\n\n/**\n * Applies a configuration to the array value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyArrayConfig<T>(\n config: ArrayConfig,\n value: unknown,\n): T[] | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n parsedValue.length === 0)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue as T[];\n}\n\n/**\n * Validates an array. The first passed validator is used to validate individual\n * items. The remaining validators target the array itself.\n * @category Type Validators\n */\nexport function array<T, E>(\n config?: Partial<ArrayConfig> | ValidatorTest<T, E>,\n ...tests: ValidatorTest[]\n): ValidatorTest<T[], string | ArrayItemValidatorResult<E>[]> {\n let allTests = tests;\n let finalConfig: ArrayConfig = {\n parser: parseArray,\n };\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...finalConfig,\n ...config,\n };\n }\n }\n\n // oxlint-disable-next-line eslint/complexity -- array and item tests share one closure; split in #483\n return async (value, field) => {\n const arrayValue = applyArrayConfig<T>(finalConfig, value);\n let arrayInvalidResult: ValidatorResult | undefined;\n let isValid = true;\n const errors: ArrayItemValidatorResult[] = [];\n const [validateItem, ...arrayTests] = allTests;\n\n for (const validatorTest of arrayTests) {\n const result = await validatorTest(arrayValue, field);\n if (result.state === 'invalid') {\n isValid = false;\n arrayInvalidResult = result;\n break;\n }\n }\n\n if (arrayValue && validateItem) {\n for (const [index, item] of arrayValue.entries()) {\n const result = await validateItem(\n item,\n field ? `${field}[${index}]` : `[${index}]`,\n );\n\n if (result.state === 'invalid') {\n isValid = false;\n errors.push(result.message || result.errors);\n } else {\n errors.push(null);\n }\n }\n }\n\n if (isValid) {\n return valid({\n value: arrayValue,\n field,\n });\n }\n\n return invalid<T[], ArrayItemValidatorResult<E>[]>({\n message:\n arrayInvalidResult?.state === 'invalid'\n ? arrayInvalidResult.message\n : '',\n value,\n field,\n errors: errors as ArrayItemValidatorResult<E>[],\n });\n };\n}\n","import { type ConfigBase, createTypeValidatorTest } from './shared.js';\n\n/**\n * Parses a value into a boolean.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseBoolean(value: unknown): boolean | null | undefined {\n if (value === undefined || value === null) {\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n return Boolean(value);\n}\n\n/**\n * Applies a configuration to the boolean value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyBooleanConfig(\n value: unknown,\n config: BooleanConfig,\n): boolean | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\n/**\n * Configuration for boolean validation.\n * @category Types\n */\nexport type BooleanConfig = ConfigBase<boolean>;\n\n/**\n * Validates a boolean value.\n * @category Type Validators\n */\nexport const boolean = createTypeValidatorTest(\n { parser: parseBoolean },\n applyBooleanConfig,\n);\n","import {\n createTypeValidatorTest,\n createValidatorTest,\n type ConfigBase,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** Badly formatted date for internal use. */\nexport const invalidDate = new Date('');\n\n/** @internal */\nconst isoDatePattern =\n /^(\\d{4})(?:-([0-2]\\d)(?:-([0-3]\\d)(?:[ T]([0-2]\\d):([0-5]\\d)(?::([0-5]\\d)(\\.\\d+)?(Z|[+-][0-2]\\d:?[0-5]\\d)?)?)?)?)?$/;\n\n/** @internal */\nconst timezonePattern = /^([+-])([0-2]\\d):?([0-5]\\d)$/;\n\n/**\n * Parses a timezone string.\n * @param timezone Timezone to parse\n * @internal\n */\nfunction parseTimezone(timezone: string): number {\n const parts = timezonePattern.exec(timezone);\n\n if (timezone === 'Z' || !parts) {\n return 0;\n }\n\n const [, sign, hour = '0', minute = '0'] = parts;\n const multiplier = sign === '-' ? -1 : 1;\n const hoursInMinutes = Number.parseInt(hour, 10) * 60;\n const offset = hoursInMinutes + Number.parseInt(minute, 10);\n\n return multiplier * offset;\n}\n\nconst BASE = 10;\n\nconst dateParts = [\n // Skip\n () => 0,\n // Year\n (part = '0') => Number.parseInt(part, BASE),\n // Month\n (part = '1') => Number.parseInt(part, BASE) - 1,\n // Day\n (part = '1') => Number.parseInt(part, BASE),\n // Hour\n (part = '0') => Number.parseInt(part, BASE),\n // Minute\n (part = '0') => Number.parseInt(part, BASE),\n // Second\n (part = '0') => Number.parseInt(part, BASE),\n // Millisecond\n (part = '0') => Number.parseFloat(part) * 1e3,\n];\n\n/**\n * Parses a value into a date.\n * @param value Value to parse\n * @category Parsers\n */\n// oxlint-disable-next-line eslint/complexity -- one guard per input type plus ISO parsing; split in #483\nexport function parseDate(value: unknown): Date | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === 'number') {\n return new Date(value);\n }\n\n if (typeof value !== 'string') {\n return invalidDate;\n }\n\n const parts = isoDatePattern.exec(value);\n\n if (parts === null) {\n return invalidDate;\n }\n\n const [\n ,\n year = 0,\n month = 0,\n day = 0,\n hour = 0,\n minute = 0,\n second = 0,\n millisecond = 0,\n ] = dateParts.map((parse, index) => parse(parts[index]));\n\n const timezone = parts[8];\n\n if (!timezone) {\n return new Date(year, month, day, hour, minute, second, millisecond);\n }\n\n const minuteOffset = parseTimezone(timezone);\n\n return new Date(\n Date.UTC(\n year,\n month,\n day,\n hour,\n minute + minuteOffset,\n second,\n millisecond,\n ),\n );\n}\n\n/**\n * Applies a configuration to the date value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyDateConfig(\n value: unknown,\n config: DateConfig,\n): Date | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue.getTime()))\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\nexport type SharedDateValueType = Date | string | number;\n\nexport interface MinDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n min: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or after a date.\n * @param limit Minimum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function minDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MinDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date, null> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value > parsedDate : value >= parsedDate))),\n message,\n () => ({\n min: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\nexport interface MaxDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n max: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or before a date.\n * @param limit Maximum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function maxDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MaxDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value < parsedDate : value <= parsedDate))),\n message,\n () => ({\n max: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\n/**\n * Configuration for date validation.\n * @category Types\n */\nexport type DateConfig = ConfigBase<Date>;\n\n/**\n * Validates a date value.\n * @category Type Validators\n */\nexport const date = createTypeValidatorTest(\n { parser: parseDate },\n applyDateConfig,\n);\n","import {\n type ConfigBase,\n createTypeValidatorTest,\n invalid,\n valid,\n type ValidatorMessage,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Parses a value into a number.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseNumber(value: unknown): number | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.getTime();\n }\n\n if (typeof value === 'string') {\n return Number.parseFloat(value);\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- coerces all other input on purpose; #484 decides non-primitives\n return Number.parseFloat(String(value));\n}\n\n/**\n * Applies a configuration to the number value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyNumberConfig(\n value: unknown,\n config: NumberConfig,\n): number | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue))\n ) {\n parsedValue = config.default;\n }\n\n if (config.round && typeof parsedValue === 'number') {\n switch (config.round) {\n case 'nearest': {\n parsedValue = Math.round(parsedValue);\n break;\n }\n case 'ceil': {\n parsedValue = Math.ceil(parsedValue);\n break;\n }\n case 'floor': {\n parsedValue = Math.floor(parsedValue);\n break;\n }\n default: {\n throw new Error(`Unknown round type: ${String(config.round)}`);\n }\n }\n }\n\n return parsedValue;\n}\n\n/**\n * Ensures a number value is an integer.\n * @param message Error message\n * @category Validation Tests\n */\nexport function integer(\n message: ValidatorMessage<number>,\n): ValidatorTest<number> {\n return async (value, field) => {\n if (\n value === undefined ||\n value === null ||\n (typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.floor(value) === value)\n ) {\n return valid({ value, field });\n }\n\n return invalid({\n message,\n value,\n field,\n });\n };\n}\n\n/**\n * Configuration for number validation.\n * @category Types\n */\nexport interface NumberConfig extends ConfigBase<number> {\n /** Apply rounding mechanism before validation. */\n round?: 'nearest' | 'floor' | 'ceil';\n}\n\n/**\n * Validates a number value.\n * @category Type Validators\n */\nexport const number = createTypeValidatorTest(\n {\n parser: parseNumber,\n },\n applyNumberConfig,\n);\n","import {\n type ExtractError,\n type ExtractValue,\n hasOwnProperty,\n invalid,\n valid,\n type ValidatorTest,\n} from './shared.js';\n\nexport type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;\n\n/**\n * Validates an object.\n * @category Type Validators\n */\nexport function object<\n P extends ObjectParameter,\n V extends { [K in keyof P]?: ExtractValue<P[K]> },\n E extends { [K in keyof P]?: ExtractError<P[K]> },\n>(properties: P): ValidatorTest<V, E> {\n if (typeof properties !== 'object' || properties === null) {\n throw new TypeError('`properties` must be a configuration object');\n }\n\n return async (values, field) => {\n const definedValues = (values ?? {}) as V;\n const errors = {} as E;\n const resolvedValues = {} as V;\n let isValid = true;\n\n for (const key in properties) {\n if (hasOwnProperty(properties, key)) {\n const validator = properties[key];\n const value = definedValues[key];\n const result =\n typeof validator === 'function'\n ? await validator(value, key)\n : await invalid({ field: key, message: 'No validator set', value });\n\n resolvedValues[key] = result.value as V[Extract<keyof P, string>];\n\n if (result.state === 'invalid') {\n isValid = false;\n errors[key] = (result.message || result.errors) as E[Extract<\n keyof P,\n string\n >];\n }\n }\n }\n\n if (isValid) {\n return valid({ value: resolvedValues, field });\n }\n\n return invalid({\n message: '',\n value: values,\n field,\n errors,\n });\n };\n}\n","import {\n type ConfigBase,\n createTypeValidatorTest,\n createValidatorTest,\n isObject,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** @internal */\nconst emailPattern =\n /^[\\w!#$%&'*+./=?^`{|}~-]+@[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?(?:\\.[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?)*$/;\n\n/**\n * Configuration for string validation.\n * @category Types\n */\nexport interface StringConfig extends ConfigBase<string> {\n /** Apply trim to string before validation. */\n trim?: boolean;\n}\n\n/**\n * Parses a value into a string.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseString(value: unknown): string | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (isObject(value)) {\n throw new TypeError('Failed to parse value to string.');\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- only plain objects throw above; #484 decides other non-primitives\n return String(value);\n}\n\n/**\n * Applies a configuration to the string value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyStringConfig(\n value: unknown,\n config: StringConfig,\n): string | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null || parsedValue === '')\n ) {\n parsedValue = config.default;\n }\n\n if (config.trim && typeof parsedValue === 'string') {\n parsedValue = parsedValue.trim();\n }\n\n return parsedValue;\n}\n\nexport interface MatchesValidatorMessageParameters extends ValidatorMessageParameters<string> {\n pattern: RegExp;\n}\n\n/**\n * Ensures a string value matches a pattern\n * @param pattern Pattern to match\n * @param message Error message\n * @category Validation Tests\n */\nexport function matches(\n pattern: RegExp,\n message: ValidatorMessage<string, MatchesValidatorMessageParameters>,\n): ValidatorTest<string> {\n // A g or y pattern advances lastIndex on each test(), so a shared one would\n // fail matching values after a match. Test a private copy from index 0.\n const ownPattern = new RegExp(pattern);\n return createValidatorTest(\n (value) => {\n ownPattern.lastIndex = 0;\n return (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && ownPattern.test(value))\n );\n },\n message,\n () => ({ pattern }),\n );\n}\n\n/**\n * Ensures a string value matches an email pattern\n * @param message Error message\n * @category Validation Tests\n */\nexport function email(\n message: ValidatorMessage<string>,\n): ValidatorTest<string> {\n return matches(emailPattern, message);\n}\n\n/**\n * Ensures a string value is a valid URL\n * @param message Error message\n * @param protocols Optional list of protocols to allow. Without it, `javascript:`\n * and `data:` URLs are valid; use `['http:', 'https:']` for values rendered as links.\n * @category Validation Tests\n */\nexport function url(\n message: ValidatorMessage<string>,\n protocols?: string[],\n): ValidatorTest<string> {\n return createValidatorTest(\n (value) => {\n try {\n let url: URL | undefined;\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && (url = new URL(value)))\n ) {\n return !(url && protocols && !protocols.includes(url.protocol));\n }\n } catch {\n // Do nothing\n }\n\n return false;\n },\n message,\n () => ({ protocols }),\n );\n}\n\n/**\n * Validates a string value.\n * @category Type Validators\n */\nexport const string = createTypeValidatorTest(\n {\n parser: parseString,\n },\n applyStringConfig,\n);\n"],"mappings":"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","names":["src_exports","__export","applyArrayConfig","applyBooleanConfig","applyDateConfig","applyNumberConfig","applyStringConfig","array","boolean","createTypeValidatorTest","createValidatorTest","date","email","exact","formatMessage","hasOwnProperty","integer","invalid","invalidDate","isObject","matches","max","maxDate","min","minDate","number","object","oneOf","parseArray","parseBoolean","parseDate","parseNumber","parseString","required","string","url","valid","__toCommonJS","isObject","value","hasOwnProperty","object","property","formatPattern","formatMessage","template","parameters","_","key","valid","field","invalid","errors","message","extras","createTypeValidatorTest","defaultConfig","applyConfig","config","tests","finalConfig","allTests","parsedValue","validatorTest","result","error","createValidatorTest","test","getExtras","required","nullable","getAmount","max","limit","exclusive","amount","min","exact","oneOf","values","x","parseArray","value","iterable","applyArrayConfig","config","parsedValue","array","tests","allTests","finalConfig","field","arrayValue","arrayInvalidResult","isValid","errors","validateItem","arrayTests","validatorTest","result","index","item","valid","invalid","parseBoolean","value","applyBooleanConfig","config","parsedValue","boolean","createTypeValidatorTest","invalidDate","isoDatePattern","timezonePattern","parseTimezone","timezone","parts","sign","hour","minute","multiplier","offset","BASE","dateParts","part","parseDate","value","year","month","day","second","millisecond","parse","index","minuteOffset","applyDateConfig","config","parsedValue","minDate","limit","message","exclusive","parsedDate","createValidatorTest","maxDate","date","createTypeValidatorTest","parseNumber","value","applyNumberConfig","config","parsedValue","integer","message","field","valid","invalid","number","createTypeValidatorTest","object","properties","values","field","definedValues","errors","resolvedValues","isValid","key","hasOwnProperty","validator","value","result","invalid","valid","emailPattern","parseString","value","isObject","applyStringConfig","config","parsedValue","matches","pattern","message","ownPattern","createValidatorTest","email","url","protocols","string","createTypeValidatorTest"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/shared.ts","../src/arrays.ts","../src/factories.ts","../src/booleans.ts","../src/parse-date.ts","../src/dates.ts","../src/numbers.ts","../src/objects.ts","../src/common.ts","../src/limits.ts","../src/strings.ts"],"sourcesContent":["/* istanbul ignore file */\nexport { applyArrayConfig, array, parseArray } from './arrays';\nexport type { ArrayConfig, ArrayItemValidatorResult } from './arrays';\nexport { applyBooleanConfig, boolean, parseBoolean } from './booleans';\nexport type { BooleanConfig } from './booleans';\nexport { applyDateConfig, date, maxDate, minDate } from './dates';\nexport type {\n DateConfig,\n MaxDateValidatorMessageParameters,\n MinDateValidatorMessageParameters,\n SharedDateValueType,\n} from './dates';\nexport { applyNumberConfig, integer, number, parseNumber } from './numbers';\nexport { invalidDate, parseDate } from './parse-date';\nexport type { NumberConfig } from './numbers';\nexport { object } from './objects';\nexport type { ObjectParameter as ObjectParam } from './objects';\nexport { oneOf, required } from './common';\nexport type { OneOfValidatorMessageParameters } from './common';\nexport { createTypeValidatorTest, createValidatorTest } from './factories';\nexport { exact, max, min } from './limits';\nexport type {\n ExactValidatorMessageParameters,\n MaxValidatorMessageParameters,\n MinValidatorMessageParameters,\n SharedValueType,\n} from './limits';\nexport {\n formatMessage,\n hasOwnProperty,\n invalid,\n isObject,\n valid,\n} from './shared';\nexport type {\n ConfigBase,\n DeepPartial,\n ExtractError,\n ExtractValue,\n InvalidResult,\n ValidatorFactory,\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorResult,\n ValidatorTest,\n ValidResult,\n} from './shared';\nexport {\n applyStringConfig,\n email,\n matches,\n parseString,\n string,\n url,\n uuid,\n} from './strings';\nexport type {\n MatchesValidatorMessageParameters,\n StringConfig,\n} from './strings';\n","export type ValidResult<T> = {\n /**\n * True if the original value is valid according to all validation tests\n * @deprecated Use `state` instead.\n */\n isValid: true;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'valid';\n /** The parsed value. Note that may be different than the original value. */\n value: T | null | undefined;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n};\n\nexport type InvalidResult<E> = {\n /**\n * True if the original value is valid according to all validation tests.\n * @deprecated Use `state` instead.\n */\n isValid: false;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'invalid';\n /** The parsed value. Note that may be different than the original value. */\n value: unknown;\n /** Error message if `state` is invalid. */\n message: string;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n /** Extra error details */\n errors?: E | undefined;\n};\n\n/**\n * The result of a validation.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorResult<T = any, E = any> =\n | ValidResult<T>\n | InvalidResult<E>;\n\n/**\n * Validation test function.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorTest<T = any, E = any> = (\n value?: unknown,\n field?: string,\n) => Promise<ValidatorResult<T, E>>;\n\n/**\n * Extracts the generic error type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractError<T extends ValidatorTest> =\n T extends ValidatorTest<any, infer E> ? E : unknown;\n\n/**\n * Extracts the generic value type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractValue<T extends ValidatorTest> =\n T extends ValidatorTest<infer V> ? V : unknown;\n\n/**\n * Make a deep partial type.\n * @typeParam T any object type\n * @category Types\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n\n/**\n * Validation factory function.\n * @typeParam C The configuration type\n * @category Types\n */\nexport type ValidatorFactory<C, T, E> = (\n config?: Partial<C> | ValidatorTest,\n ...tests: ValidatorTest[]\n) => ValidatorTest<T, E>;\n\n/**\n * Base configuration type.\n * @typeParam T The target type.\n * @category Types\n */\nexport interface ConfigBase<T> {\n /** Parser to convert value into the designated type. */\n parser: (value: unknown) => T | null | undefined;\n /** Provide a fallback value in case the original value is undefined. */\n default?: T;\n}\n\nexport interface ValidatorMessageParameters<T> {\n value: T | null | undefined;\n field: string | undefined;\n}\n\n/**\n * Validation message. May be a plain string or a function that accepts arguments.\n * While using a string, values in squiggly brackets `{}` are replaced.\n * @category Types\n */\nexport type ValidatorMessage<\n T,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n> = string | ((parameters: P) => string);\n\n/**\n * Simple check for objects.\n * @param value Value to test\n */\nexport function isObject(value: unknown): boolean {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/**\n * Safe hasOwnProperty check\n * @param object Object to check\n * @param property Property to look for\n */\nexport function hasOwnProperty(\n object: unknown,\n property: string | number | symbol,\n): boolean {\n return Object.prototype.hasOwnProperty.call(object, property);\n}\n\n/** @internal */\nconst formatPattern = /{(\\w+)}/g;\n\n/**\n * Formats a message using a squiggly bracket `{}` template.\n * @param template Message template as string or function\n * @param parameters Params to inject into template\n * @category Helpers\n */\nexport function formatMessage<T, P extends ValidatorMessageParameters<T>>(\n template: ValidatorMessage<T, P>,\n parameters: P,\n): string {\n if (typeof template === 'string') {\n return template.replaceAll(formatPattern, (_, key: string) =>\n String((parameters as Record<string, unknown>)[key]),\n );\n }\n\n return template(parameters);\n}\n\n/**\n * Creates a valid result\n * @param result Result fields\n * @param result.value Parsed value\n * @param result.field Field name\n * @category Helpers\n */\nexport async function valid<T, E = never>({\n value,\n field,\n}: {\n value: T | null | undefined;\n field: string | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: true,\n state: 'valid',\n value,\n field,\n };\n}\n\n/**\n * Creates an invalid result.\n * @param result Result fields\n * @param result.message Error message, formatted with `formatMessage`\n * @param result.value Parsed value\n * @param result.field Field name\n * @param result.errors Extra error details, such as per-field errors from `object` and `array`\n * @param result.extras Extra message params\n * @category Helpers\n */\nexport async function invalid<\n T,\n E,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>({\n errors,\n field,\n message,\n value,\n extras,\n}: {\n message: ValidatorMessage<T, P>;\n value: unknown;\n field: string | undefined;\n errors?: E | undefined;\n extras?: Omit<P, 'field' | 'value'> | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: false,\n state: 'invalid',\n message: formatMessage(message, { ...extras, value, field } as P),\n value,\n field,\n errors,\n };\n}\n","import {\n invalid,\n valid,\n type ConfigBase,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Invalid validation result for an item in the array\n * @category Types\n */\nexport type ArrayItemValidatorResult<E = unknown> = null | string | E;\n\n/**\n * Configuration for array validation.\n * @category Types\n */\nexport type ArrayConfig = ConfigBase<unknown[]>;\n\n/**\n * Parses a value into an array.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseArray(value: unknown): unknown[] | null | undefined {\n if (Array.isArray(value)) {\n return value as unknown[];\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n const iterable = value as Iterable<unknown>;\n\n if (iterable[Symbol.iterator]) {\n return [...iterable];\n }\n\n return [];\n}\n\n/**\n * Applies a configuration to the array value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyArrayConfig<T>(\n config: ArrayConfig,\n value: unknown,\n): T[] | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n parsedValue.length === 0)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue as T[];\n}\n\n/**\n * Runs the tests that target the array itself, stopping at the first failure.\n * @param tests Array-level tests\n * @param arrayValue Parsed array\n * @param field Field name\n * @internal\n */\nasync function findArrayInvalidResult(\n tests: ValidatorTest[],\n arrayValue: unknown[] | null | undefined,\n field: string | undefined,\n) {\n for (const validatorTest of tests) {\n const result = await validatorTest(arrayValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return undefined;\n}\n\n/**\n * Runs the item test on every item, collecting `null` for valid items and the\n * message or errors for invalid ones. Without an array or an item test, there\n * is nothing to check.\n * @param validateItem Item test\n * @param arrayValue Parsed array\n * @param field Field name\n * @internal\n */\nasync function validateItems(\n validateItem: ValidatorTest | undefined,\n arrayValue: unknown[] | null | undefined,\n field: string | undefined,\n) {\n let isValid = true;\n const errors: ArrayItemValidatorResult[] = [];\n\n if (!arrayValue || !validateItem) {\n return { isValid, errors };\n }\n\n for (const [index, item] of arrayValue.entries()) {\n const result = await validateItem(\n item,\n field ? `${field}[${index}]` : `[${index}]`,\n );\n\n if (result.state === 'invalid') {\n isValid = false;\n errors.push(result.message || result.errors);\n } else {\n errors.push(null);\n }\n }\n\n return { isValid, errors };\n}\n\n/**\n * Validates an array. The first passed validator is used to validate individual\n * items. The remaining validators target the array itself.\n * @category Type Validators\n */\nexport function array<T, E>(\n config?: Partial<ArrayConfig> | ValidatorTest<T, E>,\n ...tests: ValidatorTest[]\n): ValidatorTest<T[], string | ArrayItemValidatorResult<E>[]> {\n let allTests = tests;\n let finalConfig: ArrayConfig = {\n parser: parseArray,\n };\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...finalConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n const arrayValue = applyArrayConfig<T>(finalConfig, value);\n const [validateItem, ...arrayTests] = allTests;\n\n const arrayInvalidResult = await findArrayInvalidResult(\n arrayTests,\n arrayValue,\n field,\n );\n const items = await validateItems(validateItem, arrayValue, field);\n\n if (!arrayInvalidResult && items.isValid) {\n return valid({\n value: arrayValue,\n field,\n });\n }\n\n return invalid<T[], ArrayItemValidatorResult<E>[]>({\n message: arrayInvalidResult ? arrayInvalidResult.message : '',\n value,\n field,\n errors: items.errors as ArrayItemValidatorResult<E>[],\n });\n };\n}\n","import {\n type ConfigBase,\n invalid,\n valid,\n type ValidatorFactory,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Creates a type validator.\n * @typeParam T The basic type for the final value to be validated.\n * @typeParam C The configuration type.\n * @param defaultParser Parser to convert value into type.\n * @param applyConfig Function that applies configuration to value.\n * @category Helpers\n */\nexport function createTypeValidatorTest<T, C extends ConfigBase<T>>(\n defaultConfig: C,\n applyConfig: (value: unknown, config: C) => T | null | undefined,\n): ValidatorFactory<C, T, string> {\n return (config, ...tests) => {\n let finalConfig = defaultConfig;\n let allTests = tests;\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...defaultConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n try {\n const parsedValue = applyConfig(value, finalConfig);\n for (const validatorTest of allTests) {\n const result = await validatorTest(parsedValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return await valid({ value: parsedValue, field });\n } catch (error) {\n return invalid({\n message: error instanceof Error ? error.message : String(error),\n value,\n field,\n });\n }\n };\n };\n}\n\n/**\n * Captures basic validator test pattern\n * @param test Test function\n * @param message Error message\n * @param getExtras Optional extra fields for error message\n */\nexport function createValidatorTest<\n T = any,\n E = any,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>(\n test: (value: unknown, field?: string) => boolean,\n message: ValidatorMessage<T, P>,\n getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>,\n): ValidatorTest<T, E> {\n return async (value, field) => {\n if (test(value, field)) {\n return valid({ value: value as T, field });\n }\n\n return invalid({\n message,\n value,\n field,\n extras: getExtras ? getExtras(value as T) : undefined,\n });\n };\n}\n","import { createTypeValidatorTest } from './factories.js';\nimport type { ConfigBase } from './shared.js';\n\n/**\n * Parses a value into a boolean.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseBoolean(value: unknown): boolean | null | undefined {\n if (value === undefined || value === null) {\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n return Boolean(value);\n}\n\n/**\n * Applies a configuration to the boolean value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyBooleanConfig(\n value: unknown,\n config: BooleanConfig,\n): boolean | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\n/**\n * Configuration for boolean validation.\n * @category Types\n */\nexport type BooleanConfig = ConfigBase<boolean>;\n\n/**\n * Validates a boolean value.\n * @category Type Validators\n */\nexport const boolean = createTypeValidatorTest<boolean, BooleanConfig>(\n { parser: parseBoolean },\n applyBooleanConfig,\n);\n","/** Badly formatted date for internal use. */\nexport const invalidDate = new Date('');\n\n/** @internal */\nconst isoDatePattern =\n /^(\\d{4})(?:-([0-2]\\d)(?:-([0-3]\\d)(?:[ T]([0-2]\\d):([0-5]\\d)(?::([0-5]\\d)(\\.\\d+)?(Z|[+-][0-2]\\d:?[0-5]\\d)?)?)?)?)?$/;\n\n/** @internal */\nconst timezonePattern = /^([+-])([0-2]\\d):?([0-5]\\d)$/;\n\n/**\n * Parses a timezone string.\n * @param timezone Timezone to parse\n * @internal\n */\nfunction parseTimezone(timezone: string): number {\n const parts = timezonePattern.exec(timezone);\n\n if (timezone === 'Z' || !parts) {\n return 0;\n }\n\n const [, sign, hour = '0', minute = '0'] = parts;\n const multiplier = sign === '-' ? -1 : 1;\n const hoursInMinutes = Number.parseInt(hour, 10) * 60;\n const offset = hoursInMinutes + Number.parseInt(minute, 10);\n\n return multiplier * offset;\n}\n\nconst BASE = 10;\n\nconst dateParts = [\n // Skip\n () => 0,\n // Year\n (part = '0') => Number.parseInt(part, BASE),\n // Month\n (part = '1') => Number.parseInt(part, BASE) - 1,\n // Day\n (part = '1') => Number.parseInt(part, BASE),\n // Hour\n (part = '0') => Number.parseInt(part, BASE),\n // Minute\n (part = '0') => Number.parseInt(part, BASE),\n // Second\n (part = '0') => Number.parseInt(part, BASE),\n // Millisecond\n (part = '0') => Number.parseFloat(part) * 1e3,\n];\n\n/**\n * Parses a value into a date.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseDate(value: unknown): Date | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === 'number') {\n return new Date(value);\n }\n\n return typeof value === 'string' ? parseIsoDate(value) : invalidDate;\n}\n\n/**\n * Parses an ISO 8601 string into a date. Without a timezone, the date is local.\n * @param value String to parse\n * @internal\n */\nfunction parseIsoDate(value: string): Date {\n const parts = isoDatePattern.exec(value);\n\n if (parts === null) {\n return invalidDate;\n }\n\n const [\n ,\n year = 0,\n month = 0,\n day = 0,\n hour = 0,\n minute = 0,\n second = 0,\n millisecond = 0,\n ] = dateParts.map((parse, index) => parse(parts[index]));\n\n const timezone = parts[8];\n\n if (!timezone) {\n return new Date(year, month, day, hour, minute, second, millisecond);\n }\n\n return new Date(\n Date.UTC(\n year,\n month,\n day,\n hour,\n minute + parseTimezone(timezone),\n second,\n millisecond,\n ),\n );\n}\n","import { createTypeValidatorTest, createValidatorTest } from './factories.js';\nimport type {\n ConfigBase,\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\nimport { parseDate } from './parse-date.js';\n\n/**\n * Applies a configuration to the date value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyDateConfig(\n value: unknown,\n config: DateConfig,\n): Date | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue.getTime()))\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\nexport type SharedDateValueType = Date | string | number;\n\nexport interface MinDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n min: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or after a date.\n * @param limit Minimum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function minDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MinDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date, null> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value > parsedDate : value >= parsedDate))),\n message,\n () => ({\n min: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\nexport interface MaxDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n max: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or before a date.\n * @param limit Maximum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function maxDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MaxDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value < parsedDate : value <= parsedDate))),\n message,\n () => ({\n max: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\n/**\n * Configuration for date validation.\n * @category Types\n */\nexport type DateConfig = ConfigBase<Date>;\n\n/**\n * Validates a date value.\n * @category Type Validators\n */\nexport const date = createTypeValidatorTest<Date, DateConfig>(\n { parser: parseDate },\n applyDateConfig,\n);\n","import { createTypeValidatorTest } from './factories.js';\nimport {\n type ConfigBase,\n invalid,\n valid,\n type ValidatorMessage,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Parses a value into a number.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseNumber(value: unknown): number | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.getTime();\n }\n\n if (typeof value === 'string') {\n return Number.parseFloat(value);\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- coerces all other input on purpose; #484 decides non-primitives\n return Number.parseFloat(String(value));\n}\n\n/**\n * Applies a configuration to the number value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyNumberConfig(\n value: unknown,\n config: NumberConfig,\n): number | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue))\n ) {\n parsedValue = config.default;\n }\n\n if (config.round && typeof parsedValue === 'number') {\n switch (config.round) {\n case 'nearest': {\n parsedValue = Math.round(parsedValue);\n break;\n }\n case 'ceil': {\n parsedValue = Math.ceil(parsedValue);\n break;\n }\n case 'floor': {\n parsedValue = Math.floor(parsedValue);\n break;\n }\n default: {\n throw new Error(`Unknown round type: ${String(config.round)}`);\n }\n }\n }\n\n return parsedValue;\n}\n\n/**\n * Ensures a number value is an integer.\n * @param message Error message\n * @category Validation Tests\n */\nexport function integer(\n message: ValidatorMessage<number>,\n): ValidatorTest<number> {\n return async (value, field) => {\n if (\n value === undefined ||\n value === null ||\n (typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.floor(value) === value)\n ) {\n return valid({ value, field });\n }\n\n return invalid({\n message,\n value,\n field,\n });\n };\n}\n\n/**\n * Configuration for number validation.\n * @category Types\n */\nexport interface NumberConfig extends ConfigBase<number> {\n /** Apply rounding mechanism before validation. */\n round?: 'nearest' | 'floor' | 'ceil';\n}\n\n/**\n * Validates a number value.\n * @category Type Validators\n */\nexport const number = createTypeValidatorTest<number, NumberConfig>(\n {\n parser: parseNumber,\n },\n applyNumberConfig,\n);\n","import {\n type ExtractError,\n type ExtractValue,\n hasOwnProperty,\n invalid,\n valid,\n type ValidatorTest,\n} from './shared.js';\n\nexport type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;\n\n/**\n * Validates an object.\n * @category Type Validators\n */\nexport function object<\n P extends ObjectParameter,\n V extends { [K in keyof P]?: ExtractValue<P[K]> },\n E extends { [K in keyof P]?: ExtractError<P[K]> },\n>(properties: P): ValidatorTest<V, E> {\n if (typeof properties !== 'object' || properties === null) {\n throw new TypeError('`properties` must be a configuration object');\n }\n\n return async (values, field) => {\n const definedValues = (values ?? {}) as V;\n const errors = {} as E;\n const resolvedValues = {} as V;\n let isValid = true;\n\n for (const key in properties) {\n if (hasOwnProperty(properties, key)) {\n const validator = properties[key];\n const value = definedValues[key];\n const result =\n typeof validator === 'function'\n ? await validator(value, key)\n : await invalid({ field: key, message: 'No validator set', value });\n\n resolvedValues[key] = result.value as V[Extract<keyof P, string>];\n\n if (result.state === 'invalid') {\n isValid = false;\n errors[key] = (result.message || result.errors) as E[Extract<\n keyof P,\n string\n >];\n }\n }\n }\n\n if (isValid) {\n return valid({ value: resolvedValues, field });\n }\n\n return invalid({\n message: '',\n value: values,\n field,\n errors,\n });\n };\n}\n","import { createValidatorTest } from './factories.js';\nimport type {\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\n\n/**\n * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.\n * @param message Error message\n * @param nullable Allow null values\n * @category Validation Tests\n */\nexport function required<T, P extends ValidatorMessageParameters<T>>(\n message: ValidatorMessage<T, P>,\n nullable?: boolean,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n (nullable && value === null) ||\n (value !== null &&\n value !== undefined &&\n !(typeof value === 'string' && value === '') &&\n !(typeof value === 'number' && Number.isNaN(value)) &&\n !(value instanceof Date && Number.isNaN(value.valueOf()))),\n message,\n );\n}\n\nexport interface OneOfValidatorMessageParameters<\n T,\n> extends ValidatorMessageParameters<T> {\n values: readonly T[];\n}\n\n/**\n * Ensures a value is one in a predefined list.\n * @param values List of allowed values.\n * @param message Error message\n * @category Validation Tests\n */\nexport function oneOf<T extends string | number | boolean | Date>(\n values: readonly T[],\n message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n value === undefined ||\n value === null ||\n values.includes(value as T) ||\n (value instanceof Date &&\n values.some((x) => x.valueOf() === value.valueOf())),\n message,\n () => ({ values }),\n );\n}\n","import { createValidatorTest } from './factories.js';\nimport type {\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\n\nexport type SharedValueType = string | number | unknown[];\n\n/**\n * Extracts a numeric amount from value, i.e. string length, array length, or number.\n * @internal\n */\nfunction getAmount(value: SharedValueType | null | undefined) {\n return typeof value === 'string' || Array.isArray(value)\n ? value.length\n : value;\n}\n\nexport interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n max: number;\n amount: number | null | undefined;\n limit: number;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function max(\n limit: number,\n message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount < limit : amount <= limit)\n );\n },\n message,\n (value) => ({\n max: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n min: number;\n limit: number;\n amount: number | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function min(\n limit: number,\n message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount > limit : amount >= limit)\n );\n },\n message,\n (value) => ({\n min: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n limit: number;\n amount: number | null | undefined;\n exact: number;\n}\n\n/**\n * Ensures a string, number, or array value is exactly a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @category Validation Tests\n */\nexport function exact(\n limit: number,\n message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n amount === limit\n );\n },\n message,\n (value) => ({\n amount: getAmount(value),\n limit,\n exact: limit,\n }),\n );\n}\n","import { createTypeValidatorTest, createValidatorTest } from './factories.js';\nimport {\n type ConfigBase,\n isObject,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** @internal */\nconst emailPattern =\n /^[\\w!#$%&'*+./=?^`{|}~-]+@[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?(?:\\.[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?)*$/;\n\n/**\n * RFC 9562 UUIDs: versions 1 to 8 with the RFC's variant (10xx), plus the nil\n * and max UUIDs.\n * @internal\n */\nconst uuidPattern =\n /^(?:[\\da-f]{8}-[\\da-f]{4}-[1-8][\\da-f]{3}-[89ab][\\da-f]{3}-[\\da-f]{12}|0{8}-0{4}-0{4}-0{4}-0{12}|f{8}-f{4}-f{4}-f{4}-f{12})$/i;\n\n/**\n * Configuration for string validation.\n * @category Types\n */\nexport interface StringConfig extends ConfigBase<string> {\n /** Apply trim to string before validation. */\n trim?: boolean;\n}\n\n/**\n * Parses a value into a string.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseString(value: unknown): string | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (isObject(value)) {\n throw new TypeError('Failed to parse value to string.');\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- only plain objects throw above; #484 decides other non-primitives\n return String(value);\n}\n\n/**\n * Applies a configuration to the string value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyStringConfig(\n value: unknown,\n config: StringConfig,\n): string | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null || parsedValue === '')\n ) {\n parsedValue = config.default;\n }\n\n if (config.trim && typeof parsedValue === 'string') {\n parsedValue = parsedValue.trim();\n }\n\n return parsedValue;\n}\n\nexport interface MatchesValidatorMessageParameters extends ValidatorMessageParameters<string> {\n pattern: RegExp;\n}\n\n/**\n * Ensures a string value matches a pattern\n * @param pattern Pattern to match\n * @param message Error message\n * @category Validation Tests\n */\nexport function matches(\n pattern: RegExp,\n message: ValidatorMessage<string, MatchesValidatorMessageParameters>,\n): ValidatorTest<string> {\n // A g or y pattern advances lastIndex on each test(), so a shared one would\n // fail matching values after a match. Test a private copy from index 0.\n const ownPattern = new RegExp(pattern);\n return createValidatorTest(\n (value) => {\n ownPattern.lastIndex = 0;\n return (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && ownPattern.test(value))\n );\n },\n message,\n () => ({ pattern }),\n );\n}\n\n/**\n * Ensures a string value matches an email pattern\n * @param message Error message\n * @category Validation Tests\n */\nexport function email(\n message: ValidatorMessage<string>,\n): ValidatorTest<string> {\n return matches(emailPattern, message);\n}\n\n/**\n * Ensures a string value is an RFC 9562 UUID, any version from 1 to 8, or the\n * nil or max UUID. Case-insensitive, without braces or a `urn:uuid:` prefix.\n * @param message Error message\n * @category Validation Tests\n */\nexport function uuid(message: ValidatorMessage<string>): ValidatorTest<string> {\n return matches(uuidPattern, message);\n}\n\n/**\n * Ensures a string value is a valid URL\n * @param message Error message\n * @param protocols Optional list of protocols to allow. Without it, `javascript:`\n * and `data:` URLs are valid; use `['http:', 'https:']` for values rendered as links.\n * @category Validation Tests\n */\nexport function url(\n message: ValidatorMessage<string>,\n protocols?: string[],\n): ValidatorTest<string> {\n return createValidatorTest(\n (value) => {\n try {\n let url: URL | undefined;\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && (url = new URL(value)))\n ) {\n return !(url && protocols && !protocols.includes(url.protocol));\n }\n } catch {\n // Do nothing\n }\n\n return false;\n },\n message,\n () => ({ protocols }),\n );\n}\n\n/**\n * Validates a string value.\n * @category Type Validators\n */\nexport const string = createTypeValidatorTest<string, StringConfig>(\n {\n parser: parseString,\n },\n applyStringConfig,\n);\n"],"mappings":"6aAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,sBAAAE,EAAA,uBAAAC,EAAA,oBAAAC,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,UAAAC,EAAA,YAAAC,EAAA,4BAAAC,EAAA,wBAAAC,EAAA,SAAAC,EAAA,UAAAC,EAAA,UAAAC,EAAA,kBAAAC,EAAA,mBAAAC,EAAA,YAAAC,EAAA,YAAAC,EAAA,gBAAAC,EAAA,aAAAC,EAAA,YAAAC,EAAA,QAAAC,EAAA,YAAAC,EAAA,QAAAC,EAAA,YAAAC,EAAA,WAAAC,EAAA,WAAAC,EAAA,UAAAC,EAAA,eAAAC,EAAA,iBAAAC,EAAA,cAAAC,EAAA,gBAAAC,EAAA,gBAAAC,EAAA,aAAAC,EAAA,WAAAC,EAAA,QAAAC,EAAA,SAAAC,EAAA,UAAAC,IAAA,eAAAC,GAAAtC,ICqHO,SAASuC,EAASC,EAAyB,CAChD,OAAO,OAAO,UAAU,SAAS,KAAKA,CAAK,IAAM,iBACnD,CAOO,SAASC,EACdC,EACAC,EACS,CACT,OAAO,OAAO,UAAU,eAAe,KAAKD,EAAQC,CAAQ,CAC9D,CAGA,IAAMC,GAAgB,WAQf,SAASC,EACdC,EACAC,EACQ,CACR,OAAI,OAAOD,GAAa,SACfA,EAAS,WAAWF,GAAe,CAACI,EAAGC,IAC5C,OAAQF,EAAuCE,CAAG,CAAC,CACrD,EAGKH,EAASC,CAAU,CAC5B,CASA,eAAsBG,EAAoB,CACxC,MAAAV,EACA,MAAAW,CACF,EAGmC,CACjC,MAAO,CACL,QAAS,GACT,MAAO,QACP,MAAAX,EACA,MAAAW,CACF,CACF,CAYA,eAAsBC,EAIpB,CACA,OAAAC,EACA,MAAAF,EACA,QAAAG,EACA,MAAAd,EACA,OAAAe,CACF,EAMmC,CACjC,MAAO,CACL,QAAS,GACT,MAAO,UACP,QAASV,EAAcS,EAAS,CAAE,GAAGC,EAAQ,MAAAf,EAAO,MAAAW,CAAM,CAAM,EAChE,MAAAX,EACA,MAAAW,EACA,OAAAE,CACF,CACF,CC5LO,SAASG,EAAWC,EAA8C,CAKvE,GAJI,MAAM,QAAQA,CAAK,GAInBA,GAAU,KACZ,OAAOA,EAGT,IAAMC,EAAWD,EAEjB,OAAIC,EAAS,OAAO,QAAQ,EACnB,CAAC,GAAGA,CAAQ,EAGd,CAAC,CACV,CAQO,SAASC,EACdC,EACAH,EACwB,CACxB,IAAII,EAAcD,EAAO,OAAOH,CAAK,EACrC,OACEG,EAAO,UAAY,SAEjBC,GAAgB,MAChBA,EAAY,SAAW,KAEzBA,EAAcD,EAAO,SAGhBC,CACT,CASA,eAAeC,GACbC,EACAC,EACAC,EACA,CACA,QAAWC,KAAiBH,EAAO,CACjC,IAAMI,EAAS,MAAMD,EAAcF,EAAYC,CAAK,EACpD,GAAIE,EAAO,QAAU,UACnB,OAAOA,CAEX,CAGF,CAWA,eAAeC,GACbC,EACAL,EACAC,EACA,CACA,IAAIK,EAAU,GACRC,EAAqC,CAAC,EAE5C,GAAI,CAACP,GAAc,CAACK,EAClB,MAAO,CAAE,QAAAC,EAAS,OAAAC,CAAO,EAG3B,OAAW,CAACC,EAAOC,CAAI,IAAKT,EAAW,QAAQ,EAAG,CAChD,IAAMG,EAAS,MAAME,EACnBI,EACAR,EAAQ,GAAGA,CAAK,IAAIO,CAAK,IAAM,IAAIA,CAAK,GAC1C,EAEIL,EAAO,QAAU,WACnBG,EAAU,GACVC,EAAO,KAAKJ,EAAO,SAAWA,EAAO,MAAM,GAE3CI,EAAO,KAAK,IAAI,CAEpB,CAEA,MAAO,CAAE,QAAAD,EAAS,OAAAC,CAAO,CAC3B,CAOO,SAASG,EACdd,KACGG,EACyD,CAC5D,IAAIY,EAAWZ,EACXa,EAA2B,CAC7B,OAAQpB,CACV,EAEA,OAAII,IAAW,SACT,OAAOA,GAAW,WACpBe,EAAW,CAACf,EAAQ,GAAGG,CAAK,EAE5Ba,EAAc,CACZ,GAAGA,EACH,GAAGhB,CACL,GAIG,MAAOH,EAAOQ,IAAU,CAC7B,IAAMD,EAAaL,EAAoBiB,EAAanB,CAAK,EACnD,CAACY,EAAc,GAAGQ,CAAU,EAAIF,EAEhCG,EAAqB,MAAMhB,GAC/Be,EACAb,EACAC,CACF,EACMc,EAAQ,MAAMX,GAAcC,EAAcL,EAAYC,CAAK,EAEjE,MAAI,CAACa,GAAsBC,EAAM,QACxBC,EAAM,CACX,MAAOhB,EACP,MAAAC,CACF,CAAC,EAGIgB,EAA4C,CACjD,QAASH,EAAqBA,EAAmB,QAAU,GAC3D,MAAArB,EACA,MAAAQ,EACA,OAAQc,EAAM,MAChB,CAAC,CACH,CACF,CC7JO,SAASG,EACdC,EACAC,EACgC,CAChC,MAAO,CAACC,KAAWC,IAAU,CAC3B,IAAIC,EAAcJ,EACdK,EAAWF,EAEf,OAAID,IAAW,SACT,OAAOA,GAAW,WACpBG,EAAW,CAACH,EAAQ,GAAGC,CAAK,EAE5BC,EAAc,CACZ,GAAGJ,EACH,GAAGE,CACL,GAIG,MAAOI,EAAOC,IAAU,CAC7B,GAAI,CACF,IAAMC,EAAcP,EAAYK,EAAOF,CAAW,EAClD,QAAWK,KAAiBJ,EAAU,CACpC,IAAMK,EAAS,MAAMD,EAAcD,EAAaD,CAAK,EACrD,GAAIG,EAAO,QAAU,UACnB,OAAOA,CAEX,CAEA,OAAO,MAAMC,EAAM,CAAE,MAAOH,EAAa,MAAAD,CAAM,CAAC,CAClD,OAASK,EAAO,CACd,OAAOC,EAAQ,CACb,QAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EAC9D,MAAAN,EACA,MAAAC,CACF,CAAC,CACH,CACF,CACF,CACF,CAQO,SAASO,EAKdC,EACAC,EACAC,EACqB,CACrB,MAAO,OAAOX,EAAOC,IACfQ,EAAKT,EAAOC,CAAK,EACZI,EAAM,CAAE,MAAOL,EAAY,MAAAC,CAAM,CAAC,EAGpCM,EAAQ,CACb,QAAAG,EACA,MAAAV,EACA,MAAAC,EACA,OAAQU,EAAYA,EAAUX,CAAU,EAAI,MAC9C,CAAC,CAEL,CC9EO,SAASY,EAAaC,EAA4C,CAKvE,OAJ2BA,GAAU,MAIjC,OAAOA,GAAU,UACZA,EAGF,EAAQA,CACjB,CAQO,SAASC,EACdD,EACAE,EAC4B,CAC5B,IAAIC,EAAcD,EAAO,OAAOF,CAAK,EACrC,OACEE,EAAO,UAAY,QACWC,GAAgB,OAE9CA,EAAcD,EAAO,SAGhBC,CACT,CAYO,IAAMC,EAAUC,EACrB,CAAE,OAAQN,CAAa,EACvBE,CACF,ECrDO,IAAMK,EAAc,IAAI,KAAK,EAAE,EAGhCC,GACJ,sHAGIC,GAAkB,+BAOxB,SAASC,GAAcC,EAA0B,CAC/C,IAAMC,EAAQH,GAAgB,KAAKE,CAAQ,EAE3C,GAAIA,IAAa,KAAO,CAACC,EACvB,MAAO,GAGT,GAAM,CAAC,CAAEC,EAAMC,EAAO,IAAKC,EAAS,GAAG,EAAIH,EACrCI,EAAaH,IAAS,IAAM,GAAK,EAEjCI,EADiB,OAAO,SAASH,EAAM,EAAE,EAAI,GACnB,OAAO,SAASC,EAAQ,EAAE,EAE1D,OAAOC,EAAaC,CACtB,CAEA,IAAMC,EAAO,GAEPC,GAAY,CAEhB,IAAM,EAEN,CAACC,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAE1C,CAACE,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAAI,EAE9C,CAACE,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAE1C,CAACE,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAE1C,CAACE,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAE1C,CAACE,EAAO,MAAQ,OAAO,SAASA,EAAMF,CAAI,EAE1C,CAACE,EAAO,MAAQ,OAAO,WAAWA,CAAI,EAAI,GAC5C,EAOO,SAASC,EAAUC,EAAyC,CAKjE,OAJIA,GAAU,MAIVA,aAAiB,KACZA,EAGL,OAAOA,GAAU,SACZ,IAAI,KAAKA,CAAK,EAGhB,OAAOA,GAAU,SAAWC,GAAaD,CAAK,EAAIf,CAC3D,CAOA,SAASgB,GAAaD,EAAqB,CACzC,IAAMV,EAAQJ,GAAe,KAAKc,CAAK,EAEvC,GAAIV,IAAU,KACZ,OAAOL,EAGT,GAAM,CACJ,CACAiB,EAAO,EACPC,EAAQ,EACRC,EAAM,EACNZ,EAAO,EACPC,EAAS,EACTY,EAAS,EACTC,EAAc,CAChB,EAAIT,GAAU,IAAI,CAACU,EAAOC,IAAUD,EAAMjB,EAAMkB,CAAK,CAAC,CAAC,EAEjDnB,EAAWC,EAAM,CAAC,EAExB,OAAKD,EAIE,IAAI,KACT,KAAK,IACHa,EACAC,EACAC,EACAZ,EACAC,EAASL,GAAcC,CAAQ,EAC/BgB,EACAC,CACF,CACF,EAbS,IAAI,KAAKJ,EAAMC,EAAOC,EAAKZ,EAAMC,EAAQY,EAAQC,CAAW,CAcvE,CCjGO,SAASG,EACdC,EACAC,EACyB,CACzB,IAAIC,EAAcD,EAAO,OAAOD,CAAK,EACrC,OACEC,EAAO,UAAY,SAEjBC,GAAgB,MAChB,OAAO,MAAMA,EAAY,QAAQ,CAAC,KAEpCA,EAAcD,EAAO,SAGhBC,CACT,CAiBO,SAASC,EACdC,EACAC,EACAC,EAC2B,CAC3B,IAAMC,EAAaC,EAAUJ,CAAK,EAClC,OAAOK,EACJT,GACCO,GAAe,OAEdP,GAAU,MAERA,aAAiB,OACfM,EAAYN,EAAQO,EAAaP,GAASO,IACjDF,EACA,KAAO,CACL,IAAKE,EACL,MAAOA,EACP,UAAAD,CACF,EACF,CACF,CAeO,SAASI,EACdN,EACAC,EACAC,EACqB,CACrB,IAAMC,EAAaC,EAAUJ,CAAK,EAClC,OAAOK,EACJT,GACCO,GAAe,OAEdP,GAAU,MAERA,aAAiB,OACfM,EAAYN,EAAQO,EAAaP,GAASO,IACjDF,EACA,KAAO,CACL,IAAKE,EACL,MAAOA,EACP,UAAAD,CACF,EACF,CACF,CAYO,IAAMK,EAAOC,EAClB,CAAE,OAAQJ,CAAU,EACpBT,CACF,ECzGO,SAASc,EAAYC,EAA2C,CAKrE,OAJIA,GAAU,MAIV,OAAOA,GAAU,SACZA,EAGLA,aAAiB,KACZA,EAAM,QAAQ,EAGnB,OAAOA,GAAU,SACZ,OAAO,WAAWA,CAAK,EAIzB,OAAO,WAAW,OAAOA,CAAK,CAAC,CACxC,CAQO,SAASC,EACdD,EACAE,EAC2B,CAC3B,IAAIC,EAAcD,EAAO,OAAOF,CAAK,EAUrC,GAREE,EAAO,UAAY,SAEjBC,GAAgB,MAChB,OAAO,MAAMA,CAAW,KAE1BA,EAAcD,EAAO,SAGnBA,EAAO,OAAS,OAAOC,GAAgB,SACzC,OAAQD,EAAO,MAAO,CACpB,IAAK,UAAW,CACdC,EAAc,KAAK,MAAMA,CAAW,EACpC,KACF,CACA,IAAK,OAAQ,CACXA,EAAc,KAAK,KAAKA,CAAW,EACnC,KACF,CACA,IAAK,QAAS,CACZA,EAAc,KAAK,MAAMA,CAAW,EACpC,KACF,CACA,QACE,MAAM,IAAI,MAAM,uBAAuB,OAAOD,EAAO,KAAK,CAAC,EAAE,CAEjE,CAGF,OAAOC,CACT,CAOO,SAASC,EACdC,EACuB,CACvB,MAAO,OAAOL,EAAOM,IAGjBN,GAAU,MACT,OAAOA,GAAU,UAChB,OAAO,SAASA,CAAK,GACrB,KAAK,MAAMA,CAAK,IAAMA,EAEjBO,EAAM,CAAE,MAAAP,EAAO,MAAAM,CAAM,CAAC,EAGxBE,EAAQ,CACb,QAAAH,EACA,MAAAL,EACA,MAAAM,CACF,CAAC,CAEL,CAeO,IAAMG,EAASC,EACpB,CACE,OAAQX,CACV,EACAE,CACF,EC5GO,SAASU,EAIdC,EAAoC,CACpC,GAAI,OAAOA,GAAe,UAAYA,IAAe,KACnD,MAAM,IAAI,UAAU,6CAA6C,EAGnE,MAAO,OAAOC,EAAQC,IAAU,CAC9B,IAAMC,EAAiBF,GAAU,CAAC,EAC5BG,EAAS,CAAC,EACVC,EAAiB,CAAC,EACpBC,EAAU,GAEd,QAAWC,KAAOP,EAChB,GAAIQ,EAAeR,EAAYO,CAAG,EAAG,CACnC,IAAME,EAAYT,EAAWO,CAAG,EAC1BG,EAAQP,EAAcI,CAAG,EACzBI,EACJ,OAAOF,GAAc,WACjB,MAAMA,EAAUC,EAAOH,CAAG,EAC1B,MAAMK,EAAQ,CAAE,MAAOL,EAAK,QAAS,mBAAoB,MAAAG,CAAM,CAAC,EAEtEL,EAAeE,CAAG,EAAII,EAAO,MAEzBA,EAAO,QAAU,YACnBL,EAAU,GACVF,EAAOG,CAAG,EAAKI,EAAO,SAAWA,EAAO,OAK5C,CAGF,OAAIL,EACKO,EAAM,CAAE,MAAOR,EAAgB,MAAAH,CAAM,CAAC,EAGxCU,EAAQ,CACb,QAAS,GACT,MAAOX,EACP,MAAAC,EACA,OAAAE,CACF,CAAC,CACH,CACF,CCjDO,SAASU,EACdC,EACAC,EACkB,CAClB,OAAOC,EACJC,GACEF,GAAYE,IAAU,MACtBA,GAAU,MAET,EAAE,OAAOA,GAAU,UAAYA,IAAU,KACzC,EAAE,OAAOA,GAAU,UAAY,OAAO,MAAMA,CAAK,IACjD,EAAEA,aAAiB,MAAQ,OAAO,MAAMA,EAAM,QAAQ,CAAC,GAC3DH,CACF,CACF,CAcO,SAASI,EACdC,EACAL,EACkB,CAClB,OAAOE,EACJC,GAECA,GAAU,MACVE,EAAO,SAASF,CAAU,GACzBA,aAAiB,MAChBE,EAAO,KAAMC,GAAMA,EAAE,QAAQ,IAAMH,EAAM,QAAQ,CAAC,EACtDH,EACA,KAAO,CAAE,OAAAK,CAAO,EAClB,CACF,CC1CA,SAASE,EAAUC,EAA2C,CAC5D,OAAO,OAAOA,GAAU,UAAY,MAAM,QAAQA,CAAK,EACnDA,EAAM,OACNA,CACN,CAgBO,SAASC,EACdC,EACAC,EACAC,EACgC,CAChC,OAAOC,EACJL,GAAU,CACT,IAAMM,EAASP,EAAUC,CAAwB,EACjD,OAEEM,GAAW,MACXN,IAAU,KACTI,EAAYE,EAASJ,EAAQI,GAAUJ,EAE5C,EACAC,EACCH,IAAW,CACV,IAAKE,EACL,MAAAA,EACA,OAAQH,EAAUC,CAAK,EACvB,UAAAI,CACF,EACF,CACF,CAgBO,SAASG,EACdL,EACAC,EACAC,EACgC,CAChC,OAAOC,EACJL,GAAU,CACT,IAAMM,EAASP,EAAUC,CAAwB,EACjD,OAEEM,GAAW,MACXN,IAAU,KACTI,EAAYE,EAASJ,EAAQI,GAAUJ,EAE5C,EACAC,EACCH,IAAW,CACV,IAAKE,EACL,MAAAA,EACA,OAAQH,EAAUC,CAAK,EACvB,UAAAI,CACF,EACF,CACF,CAcO,SAASI,EACdN,EACAC,EACgC,CAChC,OAAOE,EACJL,GAAU,CACT,IAAMM,EAASP,EAAUC,CAAwB,EACjD,OAEEM,GAAW,MACXN,IAAU,IACVM,IAAWJ,CAEf,EACAC,EACCH,IAAW,CACV,OAAQD,EAAUC,CAAK,EACvB,MAAAE,EACA,MAAOA,CACT,EACF,CACF,CCxHA,IAAMO,GACJ,yHAOIC,GACJ,gIAgBK,SAASC,EAAYC,EAA2C,CAKrE,GAJIA,GAAU,MAIV,OAAOA,GAAU,SACnB,OAAOA,EAGT,GAAIA,aAAiB,KACnB,OAAOA,EAAM,YAAY,EAG3B,GAAIC,EAASD,CAAK,EAChB,MAAM,IAAI,UAAU,kCAAkC,EAIxD,OAAO,OAAOA,CAAK,CACrB,CAQO,SAASE,EACdF,EACAG,EAC2B,CAC3B,IAAIC,EAAcD,EAAO,OAAOH,CAAK,EACrC,OACEG,EAAO,UAAY,SACWC,GAAgB,MAAQA,IAAgB,MAEtEA,EAAcD,EAAO,SAGnBA,EAAO,MAAQ,OAAOC,GAAgB,WACxCA,EAAcA,EAAY,KAAK,GAG1BA,CACT,CAYO,SAASC,EACdC,EACAC,EACuB,CAGvB,IAAMC,EAAa,IAAI,OAAOF,CAAO,EACrC,OAAOG,EACJT,IACCQ,EAAW,UAAY,EAGrBR,GAAU,MACVA,IAAU,IACT,OAAOA,GAAU,UAAYQ,EAAW,KAAKR,CAAK,GAGvDO,EACA,KAAO,CAAE,QAAAD,CAAQ,EACnB,CACF,CAOO,SAASI,EACdH,EACuB,CACvB,OAAOF,EAAQR,GAAcU,CAAO,CACtC,CAQO,SAASI,EAAKJ,EAA0D,CAC7E,OAAOF,EAAQP,GAAaS,CAAO,CACrC,CASO,SAASK,EACdL,EACAM,EACuB,CACvB,OAAOJ,EACJT,GAAU,CACT,GAAI,CACF,IAAIY,EACJ,GAEEZ,GAAU,MACVA,IAAU,IACT,OAAOA,GAAU,WAAaY,EAAM,IAAI,IAAIZ,CAAK,GAElD,MAAO,EAAEY,GAAOC,GAAa,CAACA,EAAU,SAASD,EAAI,QAAQ,EAEjE,MAAQ,CAER,CAEA,MAAO,EACT,EACAL,EACA,KAAO,CAAE,UAAAM,CAAU,EACrB,CACF,CAMO,IAAMC,EAASC,EACpB,CACE,OAAQhB,CACV,EACAG,CACF","names":["index_exports","__export","applyArrayConfig","applyBooleanConfig","applyDateConfig","applyNumberConfig","applyStringConfig","array","boolean","createTypeValidatorTest","createValidatorTest","date","email","exact","formatMessage","hasOwnProperty","integer","invalid","invalidDate","isObject","matches","max","maxDate","min","minDate","number","object","oneOf","parseArray","parseBoolean","parseDate","parseNumber","parseString","required","string","url","uuid","valid","__toCommonJS","isObject","value","hasOwnProperty","object","property","formatPattern","formatMessage","template","parameters","_","key","valid","field","invalid","errors","message","extras","parseArray","value","iterable","applyArrayConfig","config","parsedValue","findArrayInvalidResult","tests","arrayValue","field","validatorTest","result","validateItems","validateItem","isValid","errors","index","item","array","allTests","finalConfig","arrayTests","arrayInvalidResult","items","valid","invalid","createTypeValidatorTest","defaultConfig","applyConfig","config","tests","finalConfig","allTests","value","field","parsedValue","validatorTest","result","valid","error","invalid","createValidatorTest","test","message","getExtras","parseBoolean","value","applyBooleanConfig","config","parsedValue","boolean","createTypeValidatorTest","invalidDate","isoDatePattern","timezonePattern","parseTimezone","timezone","parts","sign","hour","minute","multiplier","offset","BASE","dateParts","part","parseDate","value","parseIsoDate","year","month","day","second","millisecond","parse","index","applyDateConfig","value","config","parsedValue","minDate","limit","message","exclusive","parsedDate","parseDate","createValidatorTest","maxDate","date","createTypeValidatorTest","parseNumber","value","applyNumberConfig","config","parsedValue","integer","message","field","valid","invalid","number","createTypeValidatorTest","object","properties","values","field","definedValues","errors","resolvedValues","isValid","key","hasOwnProperty","validator","value","result","invalid","valid","required","message","nullable","createValidatorTest","value","oneOf","values","x","getAmount","value","max","limit","message","exclusive","createValidatorTest","amount","min","exact","emailPattern","uuidPattern","parseString","value","isObject","applyStringConfig","config","parsedValue","matches","pattern","message","ownPattern","createValidatorTest","email","uuid","url","protocols","string","createTypeValidatorTest"]}
package/dist/index.d.cts CHANGED
@@ -107,8 +107,9 @@ declare function hasOwnProperty(object: unknown, property: string | number | sym
107
107
  declare function formatMessage<T, P extends ValidatorMessageParameters<T>>(template: ValidatorMessage<T, P>, parameters: P): string;
108
108
  /**
109
109
  * Creates a valid result
110
- * @param value Parsed value
111
- * @param field Field name
110
+ * @param result Result fields
111
+ * @param result.value Parsed value
112
+ * @param result.field Field name
112
113
  * @category Helpers
113
114
  */
114
115
  declare function valid<T, E = never>({ value, field, }: {
@@ -117,10 +118,12 @@ declare function valid<T, E = never>({ value, field, }: {
117
118
  }): Promise<ValidatorResult<T, E>>;
118
119
  /**
119
120
  * Creates an invalid result.
120
- * @param message Error message
121
- * @param value Parsed value
122
- * @param field Field name
123
- * @param extras Extra message params
121
+ * @param result Result fields
122
+ * @param result.message Error message, formatted with `formatMessage`
123
+ * @param result.value Parsed value
124
+ * @param result.field Field name
125
+ * @param result.errors Extra error details, such as per-field errors from `object` and `array`
126
+ * @param result.extras Extra message params
124
127
  * @category Helpers
125
128
  */
126
129
  declare function invalid<T, E, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>({ errors, field, message, value, extras, }: {
@@ -130,80 +133,6 @@ declare function invalid<T, E, P extends ValidatorMessageParameters<T> = Validat
130
133
  errors?: E | undefined;
131
134
  extras?: Omit<P, 'field' | 'value'> | undefined;
132
135
  }): Promise<ValidatorResult<T, E>>;
133
- /**
134
- * Creates a type validator.
135
- * @typeParam T The basic type for the final value to be validated.
136
- * @typeParam C The configuration type.
137
- * @param defaultParser Parser to convert value into type.
138
- * @param applyConfig Function that applies configuration to value.
139
- * @category Helpers
140
- */
141
- declare function createTypeValidatorTest<T, C extends ConfigBase<T>>(defaultConfig: C, applyConfig: (value: unknown, config: C) => T | null | undefined): ValidatorFactory<C, T, string>;
142
- /**
143
- * Captures basic validator test pattern
144
- * @param test Test function
145
- * @param message Error message
146
- * @param getExtras Optional extra fields for error message
147
- */
148
- declare function createValidatorTest<T = any, E = any, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>(test: (value: unknown, field?: string) => boolean, message: ValidatorMessage<T, P>, getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>): ValidatorTest<T, E>;
149
- /**
150
- * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.
151
- * @param message Error message
152
- * @param nullable Allow null values
153
- * @category Validation Tests
154
- */
155
- declare function required<T, P extends ValidatorMessageParameters<T>>(message: ValidatorMessage<T, P>, nullable?: boolean): ValidatorTest<T>;
156
- type SharedValueType = string | number | unknown[];
157
- interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
158
- max: number;
159
- amount: number | null | undefined;
160
- limit: number;
161
- exclusive?: boolean | undefined;
162
- }
163
- /**
164
- * Ensures a string, number, or array value is at most a certain amount.
165
- * @param limit Size or value limit
166
- * @param message Error message
167
- * @param exclusive Use exclusive comparison instead of inclusive
168
- * @category Validation Tests
169
- */
170
- declare function max(limit: number, message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
171
- interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
172
- min: number;
173
- limit: number;
174
- amount: number | null | undefined;
175
- exclusive?: boolean | undefined;
176
- }
177
- /**
178
- * Ensures a string, number, or array value is at most a certain amount.
179
- * @param limit Size or value limit
180
- * @param message Error message
181
- * @param exclusive Use exclusive comparison instead of inclusive
182
- * @category Validation Tests
183
- */
184
- declare function min(limit: number, message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
185
- interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
186
- limit: number;
187
- amount: number | null | undefined;
188
- exact: number;
189
- }
190
- /**
191
- * Ensures a string, number, or array value is exactly a certain amount.
192
- * @param limit Size or value limit
193
- * @param message Error message
194
- * @category Validation Tests
195
- */
196
- declare function exact(limit: number, message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>): ValidatorTest<SharedValueType>;
197
- interface OneOfValidatorMessageParameters<T> extends ValidatorMessageParameters<T> {
198
- values: readonly T[];
199
- }
200
- /**
201
- * Ensures a value is one in a predefined list.
202
- * @param values List of allowed values.
203
- * @param message Error message
204
- * @category Validation Tests
205
- */
206
- declare function oneOf<T extends string | number | boolean | Date>(values: readonly T[], message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>): ValidatorTest<T>;
207
136
 
208
137
  /**
209
138
  * Invalid validation result for an item in the array
@@ -259,14 +188,6 @@ type BooleanConfig = ConfigBase<boolean>;
259
188
  */
260
189
  declare const boolean: ValidatorFactory<BooleanConfig, boolean, string>;
261
190
 
262
- /** Badly formatted date for internal use. */
263
- declare const invalidDate: Date;
264
- /**
265
- * Parses a value into a date.
266
- * @param value Value to parse
267
- * @category Parsers
268
- */
269
- declare function parseDate(value: unknown): Date | null | undefined;
270
191
  /**
271
192
  * Applies a configuration to the date value.
272
193
  * @param value Value to modify
@@ -345,6 +266,15 @@ interface NumberConfig extends ConfigBase<number> {
345
266
  */
346
267
  declare const number: ValidatorFactory<NumberConfig, number, string>;
347
268
 
269
+ /** Badly formatted date for internal use. */
270
+ declare const invalidDate: Date;
271
+ /**
272
+ * Parses a value into a date.
273
+ * @param value Value to parse
274
+ * @category Parsers
275
+ */
276
+ declare function parseDate(value: unknown): Date | null | undefined;
277
+
348
278
  type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;
349
279
  /**
350
280
  * Validates an object.
@@ -356,6 +286,83 @@ declare function object<P extends ObjectParameter, V extends {
356
286
  [K in keyof P]?: ExtractError<P[K]>;
357
287
  }>(properties: P): ValidatorTest<V, E>;
358
288
 
289
+ /**
290
+ * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.
291
+ * @param message Error message
292
+ * @param nullable Allow null values
293
+ * @category Validation Tests
294
+ */
295
+ declare function required<T, P extends ValidatorMessageParameters<T>>(message: ValidatorMessage<T, P>, nullable?: boolean): ValidatorTest<T>;
296
+ interface OneOfValidatorMessageParameters<T> extends ValidatorMessageParameters<T> {
297
+ values: readonly T[];
298
+ }
299
+ /**
300
+ * Ensures a value is one in a predefined list.
301
+ * @param values List of allowed values.
302
+ * @param message Error message
303
+ * @category Validation Tests
304
+ */
305
+ declare function oneOf<T extends string | number | boolean | Date>(values: readonly T[], message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>): ValidatorTest<T>;
306
+
307
+ /**
308
+ * Creates a type validator.
309
+ * @typeParam T The basic type for the final value to be validated.
310
+ * @typeParam C The configuration type.
311
+ * @param defaultParser Parser to convert value into type.
312
+ * @param applyConfig Function that applies configuration to value.
313
+ * @category Helpers
314
+ */
315
+ declare function createTypeValidatorTest<T, C extends ConfigBase<T>>(defaultConfig: C, applyConfig: (value: unknown, config: C) => T | null | undefined): ValidatorFactory<C, T, string>;
316
+ /**
317
+ * Captures basic validator test pattern
318
+ * @param test Test function
319
+ * @param message Error message
320
+ * @param getExtras Optional extra fields for error message
321
+ */
322
+ declare function createValidatorTest<T = any, E = any, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>(test: (value: unknown, field?: string) => boolean, message: ValidatorMessage<T, P>, getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>): ValidatorTest<T, E>;
323
+
324
+ type SharedValueType = string | number | unknown[];
325
+ interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
326
+ max: number;
327
+ amount: number | null | undefined;
328
+ limit: number;
329
+ exclusive?: boolean | undefined;
330
+ }
331
+ /**
332
+ * Ensures a string, number, or array value is at most a certain amount.
333
+ * @param limit Size or value limit
334
+ * @param message Error message
335
+ * @param exclusive Use exclusive comparison instead of inclusive
336
+ * @category Validation Tests
337
+ */
338
+ declare function max(limit: number, message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
339
+ interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
340
+ min: number;
341
+ limit: number;
342
+ amount: number | null | undefined;
343
+ exclusive?: boolean | undefined;
344
+ }
345
+ /**
346
+ * Ensures a string, number, or array value is at most a certain amount.
347
+ * @param limit Size or value limit
348
+ * @param message Error message
349
+ * @param exclusive Use exclusive comparison instead of inclusive
350
+ * @category Validation Tests
351
+ */
352
+ declare function min(limit: number, message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
353
+ interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
354
+ limit: number;
355
+ amount: number | null | undefined;
356
+ exact: number;
357
+ }
358
+ /**
359
+ * Ensures a string, number, or array value is exactly a certain amount.
360
+ * @param limit Size or value limit
361
+ * @param message Error message
362
+ * @category Validation Tests
363
+ */
364
+ declare function exact(limit: number, message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>): ValidatorTest<SharedValueType>;
365
+
359
366
  /**
360
367
  * Configuration for string validation.
361
368
  * @category Types
@@ -393,6 +400,13 @@ declare function matches(pattern: RegExp, message: ValidatorMessage<string, Matc
393
400
  * @category Validation Tests
394
401
  */
395
402
  declare function email(message: ValidatorMessage<string>): ValidatorTest<string>;
403
+ /**
404
+ * Ensures a string value is an RFC 9562 UUID, any version from 1 to 8, or the
405
+ * nil or max UUID. Case-insensitive, without braces or a `urn:uuid:` prefix.
406
+ * @param message Error message
407
+ * @category Validation Tests
408
+ */
409
+ declare function uuid(message: ValidatorMessage<string>): ValidatorTest<string>;
396
410
  /**
397
411
  * Ensures a string value is a valid URL
398
412
  * @param message Error message
@@ -407,4 +421,4 @@ declare function url(message: ValidatorMessage<string>, protocols?: string[]): V
407
421
  */
408
422
  declare const string: ValidatorFactory<StringConfig, string, string>;
409
423
 
410
- export { type ArrayConfig, type ArrayItemValidatorResult, type BooleanConfig, type ConfigBase, type DateConfig, type DeepPartial, type ExactValidatorMessageParameters, type ExtractError, type ExtractValue, type InvalidResult, type MatchesValidatorMessageParameters, type MaxDateValidatorMessageParameters, type MaxValidatorMessageParameters, type MinDateValidatorMessageParameters, type MinValidatorMessageParameters, type NumberConfig, type ObjectParameter as ObjectParam, type OneOfValidatorMessageParameters, type SharedDateValueType, type SharedValueType, type StringConfig, type ValidResult, type ValidatorFactory, type ValidatorMessage, type ValidatorMessageParameters, type ValidatorResult, type ValidatorTest, applyArrayConfig, applyBooleanConfig, applyDateConfig, applyNumberConfig, applyStringConfig, array, boolean, createTypeValidatorTest, createValidatorTest, date, email, exact, formatMessage, hasOwnProperty, integer, invalid, invalidDate, isObject, matches, max, maxDate, min, minDate, number, object, oneOf, parseArray, parseBoolean, parseDate, parseNumber, parseString, required, string, url, valid };
424
+ export { type ArrayConfig, type ArrayItemValidatorResult, type BooleanConfig, type ConfigBase, type DateConfig, type DeepPartial, type ExactValidatorMessageParameters, type ExtractError, type ExtractValue, type InvalidResult, type MatchesValidatorMessageParameters, type MaxDateValidatorMessageParameters, type MaxValidatorMessageParameters, type MinDateValidatorMessageParameters, type MinValidatorMessageParameters, type NumberConfig, type ObjectParameter as ObjectParam, type OneOfValidatorMessageParameters, type SharedDateValueType, type SharedValueType, type StringConfig, type ValidResult, type ValidatorFactory, type ValidatorMessage, type ValidatorMessageParameters, type ValidatorResult, type ValidatorTest, applyArrayConfig, applyBooleanConfig, applyDateConfig, applyNumberConfig, applyStringConfig, array, boolean, createTypeValidatorTest, createValidatorTest, date, email, exact, formatMessage, hasOwnProperty, integer, invalid, invalidDate, isObject, matches, max, maxDate, min, minDate, number, object, oneOf, parseArray, parseBoolean, parseDate, parseNumber, parseString, required, string, url, uuid, valid };
package/dist/index.d.ts CHANGED
@@ -107,8 +107,9 @@ declare function hasOwnProperty(object: unknown, property: string | number | sym
107
107
  declare function formatMessage<T, P extends ValidatorMessageParameters<T>>(template: ValidatorMessage<T, P>, parameters: P): string;
108
108
  /**
109
109
  * Creates a valid result
110
- * @param value Parsed value
111
- * @param field Field name
110
+ * @param result Result fields
111
+ * @param result.value Parsed value
112
+ * @param result.field Field name
112
113
  * @category Helpers
113
114
  */
114
115
  declare function valid<T, E = never>({ value, field, }: {
@@ -117,10 +118,12 @@ declare function valid<T, E = never>({ value, field, }: {
117
118
  }): Promise<ValidatorResult<T, E>>;
118
119
  /**
119
120
  * Creates an invalid result.
120
- * @param message Error message
121
- * @param value Parsed value
122
- * @param field Field name
123
- * @param extras Extra message params
121
+ * @param result Result fields
122
+ * @param result.message Error message, formatted with `formatMessage`
123
+ * @param result.value Parsed value
124
+ * @param result.field Field name
125
+ * @param result.errors Extra error details, such as per-field errors from `object` and `array`
126
+ * @param result.extras Extra message params
124
127
  * @category Helpers
125
128
  */
126
129
  declare function invalid<T, E, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>({ errors, field, message, value, extras, }: {
@@ -130,80 +133,6 @@ declare function invalid<T, E, P extends ValidatorMessageParameters<T> = Validat
130
133
  errors?: E | undefined;
131
134
  extras?: Omit<P, 'field' | 'value'> | undefined;
132
135
  }): Promise<ValidatorResult<T, E>>;
133
- /**
134
- * Creates a type validator.
135
- * @typeParam T The basic type for the final value to be validated.
136
- * @typeParam C The configuration type.
137
- * @param defaultParser Parser to convert value into type.
138
- * @param applyConfig Function that applies configuration to value.
139
- * @category Helpers
140
- */
141
- declare function createTypeValidatorTest<T, C extends ConfigBase<T>>(defaultConfig: C, applyConfig: (value: unknown, config: C) => T | null | undefined): ValidatorFactory<C, T, string>;
142
- /**
143
- * Captures basic validator test pattern
144
- * @param test Test function
145
- * @param message Error message
146
- * @param getExtras Optional extra fields for error message
147
- */
148
- declare function createValidatorTest<T = any, E = any, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>(test: (value: unknown, field?: string) => boolean, message: ValidatorMessage<T, P>, getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>): ValidatorTest<T, E>;
149
- /**
150
- * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.
151
- * @param message Error message
152
- * @param nullable Allow null values
153
- * @category Validation Tests
154
- */
155
- declare function required<T, P extends ValidatorMessageParameters<T>>(message: ValidatorMessage<T, P>, nullable?: boolean): ValidatorTest<T>;
156
- type SharedValueType = string | number | unknown[];
157
- interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
158
- max: number;
159
- amount: number | null | undefined;
160
- limit: number;
161
- exclusive?: boolean | undefined;
162
- }
163
- /**
164
- * Ensures a string, number, or array value is at most a certain amount.
165
- * @param limit Size or value limit
166
- * @param message Error message
167
- * @param exclusive Use exclusive comparison instead of inclusive
168
- * @category Validation Tests
169
- */
170
- declare function max(limit: number, message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
171
- interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
172
- min: number;
173
- limit: number;
174
- amount: number | null | undefined;
175
- exclusive?: boolean | undefined;
176
- }
177
- /**
178
- * Ensures a string, number, or array value is at most a certain amount.
179
- * @param limit Size or value limit
180
- * @param message Error message
181
- * @param exclusive Use exclusive comparison instead of inclusive
182
- * @category Validation Tests
183
- */
184
- declare function min(limit: number, message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
185
- interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
186
- limit: number;
187
- amount: number | null | undefined;
188
- exact: number;
189
- }
190
- /**
191
- * Ensures a string, number, or array value is exactly a certain amount.
192
- * @param limit Size or value limit
193
- * @param message Error message
194
- * @category Validation Tests
195
- */
196
- declare function exact(limit: number, message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>): ValidatorTest<SharedValueType>;
197
- interface OneOfValidatorMessageParameters<T> extends ValidatorMessageParameters<T> {
198
- values: readonly T[];
199
- }
200
- /**
201
- * Ensures a value is one in a predefined list.
202
- * @param values List of allowed values.
203
- * @param message Error message
204
- * @category Validation Tests
205
- */
206
- declare function oneOf<T extends string | number | boolean | Date>(values: readonly T[], message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>): ValidatorTest<T>;
207
136
 
208
137
  /**
209
138
  * Invalid validation result for an item in the array
@@ -259,14 +188,6 @@ type BooleanConfig = ConfigBase<boolean>;
259
188
  */
260
189
  declare const boolean: ValidatorFactory<BooleanConfig, boolean, string>;
261
190
 
262
- /** Badly formatted date for internal use. */
263
- declare const invalidDate: Date;
264
- /**
265
- * Parses a value into a date.
266
- * @param value Value to parse
267
- * @category Parsers
268
- */
269
- declare function parseDate(value: unknown): Date | null | undefined;
270
191
  /**
271
192
  * Applies a configuration to the date value.
272
193
  * @param value Value to modify
@@ -345,6 +266,15 @@ interface NumberConfig extends ConfigBase<number> {
345
266
  */
346
267
  declare const number: ValidatorFactory<NumberConfig, number, string>;
347
268
 
269
+ /** Badly formatted date for internal use. */
270
+ declare const invalidDate: Date;
271
+ /**
272
+ * Parses a value into a date.
273
+ * @param value Value to parse
274
+ * @category Parsers
275
+ */
276
+ declare function parseDate(value: unknown): Date | null | undefined;
277
+
348
278
  type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;
349
279
  /**
350
280
  * Validates an object.
@@ -356,6 +286,83 @@ declare function object<P extends ObjectParameter, V extends {
356
286
  [K in keyof P]?: ExtractError<P[K]>;
357
287
  }>(properties: P): ValidatorTest<V, E>;
358
288
 
289
+ /**
290
+ * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.
291
+ * @param message Error message
292
+ * @param nullable Allow null values
293
+ * @category Validation Tests
294
+ */
295
+ declare function required<T, P extends ValidatorMessageParameters<T>>(message: ValidatorMessage<T, P>, nullable?: boolean): ValidatorTest<T>;
296
+ interface OneOfValidatorMessageParameters<T> extends ValidatorMessageParameters<T> {
297
+ values: readonly T[];
298
+ }
299
+ /**
300
+ * Ensures a value is one in a predefined list.
301
+ * @param values List of allowed values.
302
+ * @param message Error message
303
+ * @category Validation Tests
304
+ */
305
+ declare function oneOf<T extends string | number | boolean | Date>(values: readonly T[], message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>): ValidatorTest<T>;
306
+
307
+ /**
308
+ * Creates a type validator.
309
+ * @typeParam T The basic type for the final value to be validated.
310
+ * @typeParam C The configuration type.
311
+ * @param defaultParser Parser to convert value into type.
312
+ * @param applyConfig Function that applies configuration to value.
313
+ * @category Helpers
314
+ */
315
+ declare function createTypeValidatorTest<T, C extends ConfigBase<T>>(defaultConfig: C, applyConfig: (value: unknown, config: C) => T | null | undefined): ValidatorFactory<C, T, string>;
316
+ /**
317
+ * Captures basic validator test pattern
318
+ * @param test Test function
319
+ * @param message Error message
320
+ * @param getExtras Optional extra fields for error message
321
+ */
322
+ declare function createValidatorTest<T = any, E = any, P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>>(test: (value: unknown, field?: string) => boolean, message: ValidatorMessage<T, P>, getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>): ValidatorTest<T, E>;
323
+
324
+ type SharedValueType = string | number | unknown[];
325
+ interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
326
+ max: number;
327
+ amount: number | null | undefined;
328
+ limit: number;
329
+ exclusive?: boolean | undefined;
330
+ }
331
+ /**
332
+ * Ensures a string, number, or array value is at most a certain amount.
333
+ * @param limit Size or value limit
334
+ * @param message Error message
335
+ * @param exclusive Use exclusive comparison instead of inclusive
336
+ * @category Validation Tests
337
+ */
338
+ declare function max(limit: number, message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
339
+ interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
340
+ min: number;
341
+ limit: number;
342
+ amount: number | null | undefined;
343
+ exclusive?: boolean | undefined;
344
+ }
345
+ /**
346
+ * Ensures a string, number, or array value is at most a certain amount.
347
+ * @param limit Size or value limit
348
+ * @param message Error message
349
+ * @param exclusive Use exclusive comparison instead of inclusive
350
+ * @category Validation Tests
351
+ */
352
+ declare function min(limit: number, message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>, exclusive?: boolean): ValidatorTest<SharedValueType>;
353
+ interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {
354
+ limit: number;
355
+ amount: number | null | undefined;
356
+ exact: number;
357
+ }
358
+ /**
359
+ * Ensures a string, number, or array value is exactly a certain amount.
360
+ * @param limit Size or value limit
361
+ * @param message Error message
362
+ * @category Validation Tests
363
+ */
364
+ declare function exact(limit: number, message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>): ValidatorTest<SharedValueType>;
365
+
359
366
  /**
360
367
  * Configuration for string validation.
361
368
  * @category Types
@@ -393,6 +400,13 @@ declare function matches(pattern: RegExp, message: ValidatorMessage<string, Matc
393
400
  * @category Validation Tests
394
401
  */
395
402
  declare function email(message: ValidatorMessage<string>): ValidatorTest<string>;
403
+ /**
404
+ * Ensures a string value is an RFC 9562 UUID, any version from 1 to 8, or the
405
+ * nil or max UUID. Case-insensitive, without braces or a `urn:uuid:` prefix.
406
+ * @param message Error message
407
+ * @category Validation Tests
408
+ */
409
+ declare function uuid(message: ValidatorMessage<string>): ValidatorTest<string>;
396
410
  /**
397
411
  * Ensures a string value is a valid URL
398
412
  * @param message Error message
@@ -407,4 +421,4 @@ declare function url(message: ValidatorMessage<string>, protocols?: string[]): V
407
421
  */
408
422
  declare const string: ValidatorFactory<StringConfig, string, string>;
409
423
 
410
- export { type ArrayConfig, type ArrayItemValidatorResult, type BooleanConfig, type ConfigBase, type DateConfig, type DeepPartial, type ExactValidatorMessageParameters, type ExtractError, type ExtractValue, type InvalidResult, type MatchesValidatorMessageParameters, type MaxDateValidatorMessageParameters, type MaxValidatorMessageParameters, type MinDateValidatorMessageParameters, type MinValidatorMessageParameters, type NumberConfig, type ObjectParameter as ObjectParam, type OneOfValidatorMessageParameters, type SharedDateValueType, type SharedValueType, type StringConfig, type ValidResult, type ValidatorFactory, type ValidatorMessage, type ValidatorMessageParameters, type ValidatorResult, type ValidatorTest, applyArrayConfig, applyBooleanConfig, applyDateConfig, applyNumberConfig, applyStringConfig, array, boolean, createTypeValidatorTest, createValidatorTest, date, email, exact, formatMessage, hasOwnProperty, integer, invalid, invalidDate, isObject, matches, max, maxDate, min, minDate, number, object, oneOf, parseArray, parseBoolean, parseDate, parseNumber, parseString, required, string, url, valid };
424
+ export { type ArrayConfig, type ArrayItemValidatorResult, type BooleanConfig, type ConfigBase, type DateConfig, type DeepPartial, type ExactValidatorMessageParameters, type ExtractError, type ExtractValue, type InvalidResult, type MatchesValidatorMessageParameters, type MaxDateValidatorMessageParameters, type MaxValidatorMessageParameters, type MinDateValidatorMessageParameters, type MinValidatorMessageParameters, type NumberConfig, type ObjectParameter as ObjectParam, type OneOfValidatorMessageParameters, type SharedDateValueType, type SharedValueType, type StringConfig, type ValidResult, type ValidatorFactory, type ValidatorMessage, type ValidatorMessageParameters, type ValidatorResult, type ValidatorTest, applyArrayConfig, applyBooleanConfig, applyDateConfig, applyNumberConfig, applyStringConfig, array, boolean, createTypeValidatorTest, createValidatorTest, date, email, exact, formatMessage, hasOwnProperty, integer, invalid, invalidDate, isObject, matches, max, maxDate, min, minDate, number, object, oneOf, parseArray, parseBoolean, parseDate, parseNumber, parseString, required, string, url, uuid, valid };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- function M(e){return Object.prototype.toString.call(e)==="[object Object]"}function w(e,r){return Object.prototype.hasOwnProperty.call(e,r)}var j=/{(\w+)}/g;function E(e,r){return typeof e=="string"?e.replaceAll(j,(t,a)=>String(r[a])):e(r)}async function m({value:e,field:r}){return{isValid:!0,state:"valid",value:e,field:r}}async function p({errors:e,field:r,message:t,value:a,extras:n}){return{isValid:!1,state:"invalid",message:E(t,{...n,value:a,field:r}),value:a,field:r,errors:e}}function g(e,r){return(t,...a)=>{let n=e,o=a;return t!==void 0&&(typeof t=="function"?o=[t,...a]:n={...e,...t}),async(d,s)=>{try{let i=r(d,n);for(let f of o){let l=await f(i,s);if(l.state==="invalid")return l}return await m({value:i,field:s})}catch(i){return p({message:i instanceof Error?i.message:String(i),value:d,field:s})}}}}function u(e,r,t){return async(a,n)=>e(a,n)?m({value:a,field:n}):p({message:r,value:a,field:n,extras:t?t(a):void 0})}function z(e,r){return u(t=>r&&t===null||t!=null&&!(typeof t=="string"&&t==="")&&!(typeof t=="number"&&Number.isNaN(t))&&!(t instanceof Date&&Number.isNaN(t.valueOf())),e)}function c(e){return typeof e=="string"||Array.isArray(e)?e.length:e}function F(e,r,t){return u(a=>{let n=c(a);return n==null||a===""||(t?n<e:n<=e)},r,a=>({max:e,limit:e,amount:c(a),exclusive:t}))}function Z(e,r,t){return u(a=>{let n=c(a);return n==null||a===""||(t?n>e:n>=e)},r,a=>({min:e,limit:e,amount:c(a),exclusive:t}))}function $(e,r){return u(t=>{let a=c(t);return a==null||t===""||a===e},r,t=>({amount:c(t),limit:e,exact:e}))}function K(e,r){return u(t=>t==null||e.includes(t)||t instanceof Date&&e.some(a=>a.valueOf()===t.valueOf()),r,()=>({values:e}))}function h(e){if(Array.isArray(e)||e==null)return e;let r=e;return r[Symbol.iterator]?[...r]:[]}function C(e,r){let t=e.parser(r);return e.default!==void 0&&(t==null||t.length===0)&&(t=e.default),t}function U(e,...r){let t=r,a={parser:h};return e!==void 0&&(typeof e=="function"?t=[e,...r]:a={...a,...e}),async(n,o)=>{let d=C(a,n),s,i=!0,f=[],[l,...b]=t;for(let V of b){let T=await V(d,o);if(T.state==="invalid"){i=!1,s=T;break}}if(d&&l)for(let[V,T]of d.entries()){let P=await l(T,o?`${o}[${V}]`:`[${V}]`);P.state==="invalid"?(i=!1,f.push(P.message||P.errors)):f.push(null)}return i?m({value:d,field:o}):p({message:s?.state==="invalid"?s.message:"",value:n,field:o,errors:f})}}function k(e){return e==null||typeof e=="boolean"?e:!!e}function S(e,r){let t=r.parser(e);return r.default!==void 0&&t==null&&(t=r.default),t}var q=g({parser:k},S);var D=new Date(""),L=/^(\d{4})(?:-([0-2]\d)(?:-([0-3]\d)(?:[ T]([0-2]\d):([0-5]\d)(?::([0-5]\d)(\.\d+)?(Z|[+-][0-2]\d:?[0-5]\d)?)?)?)?)?$/,_=/^([+-])([0-2]\d):?([0-5]\d)$/;function G(e){let r=_.exec(e);if(e==="Z"||!r)return 0;let[,t,a="0",n="0"]=r,o=t==="-"?-1:1,s=Number.parseInt(a,10)*60+Number.parseInt(n,10);return o*s}var y=10,H=[()=>0,(e="0")=>Number.parseInt(e,y),(e="1")=>Number.parseInt(e,y)-1,(e="1")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseInt(e,y),(e="0")=>Number.parseFloat(e)*1e3];function x(e){if(e==null||e instanceof Date)return e;if(typeof e=="number")return new Date(e);if(typeof e!="string")return D;let r=L.exec(e);if(r===null)return D;let[,t=0,a=0,n=0,o=0,d=0,s=0,i=0]=H.map((b,V)=>b(r[V])),f=r[8];if(!f)return new Date(t,a,n,o,d,s,i);let l=G(f);return new Date(Date.UTC(t,a,n,o,d+l,s,i))}function N(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||Number.isNaN(t.getTime()))&&(t=r.default),t}function J(e,r,t){let a=x(e);return u(n=>a!=null&&(n==null||n instanceof Date&&(t?n>a:n>=a)),r,()=>({min:a,limit:a,exclusive:t}))}function Q(e,r,t){let a=x(e);return u(n=>a!=null&&(n==null||n instanceof Date&&(t?n<a:n<=a)),r,()=>({max:a,limit:a,exclusive:t}))}var W=g({parser:x},N);function O(e){return e==null||typeof e=="number"?e:e instanceof Date?e.getTime():typeof e=="string"?Number.parseFloat(e):Number.parseFloat(String(e))}function A(e,r){let t=r.parser(e);if(r.default!==void 0&&(t==null||Number.isNaN(t))&&(t=r.default),r.round&&typeof t=="number")switch(r.round){case"nearest":{t=Math.round(t);break}case"ceil":{t=Math.ceil(t);break}case"floor":{t=Math.floor(t);break}default:throw new Error(`Unknown round type: ${String(r.round)}`)}return t}function X(e){return async(r,t)=>r==null||typeof r=="number"&&Number.isFinite(r)&&Math.floor(r)===r?m({value:r,field:t}):p({message:e,value:r,field:t})}var Y=g({parser:O},A);function v(e){if(typeof e!="object"||e===null)throw new TypeError("`properties` must be a configuration object");return async(r,t)=>{let a=r??{},n={},o={},d=!0;for(let s in e)if(w(e,s)){let i=e[s],f=a[s],l=typeof i=="function"?await i(f,s):await p({field:s,message:"No validator set",value:f});o[s]=l.value,l.state==="invalid"&&(d=!1,n[s]=l.message||l.errors)}return d?m({value:o,field:t}):p({message:"",value:r,field:t,errors:n})}}var ee=/^[\w!#$%&'*+./=?^`{|}~-]+@[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?(?:\.[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?)*$/;function R(e){if(e==null||typeof e=="string")return e;if(e instanceof Date)return e.toISOString();if(M(e))throw new TypeError("Failed to parse value to string.");return String(e)}function I(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||t==="")&&(t=r.default),r.trim&&typeof t=="string"&&(t=t.trim()),t}function B(e,r){let t=new RegExp(e);return u(a=>(t.lastIndex=0,a==null||a===""||typeof a=="string"&&t.test(a)),r,()=>({pattern:e}))}function te(e){return B(ee,e)}function re(e,r){return u(t=>{try{let a;if(t==null||t===""||typeof t=="string"&&(a=new URL(t)))return!(a&&r&&!r.includes(a.protocol))}catch{}return!1},e,()=>({protocols:r}))}var ae=g({parser:R},I);export{C as applyArrayConfig,S as applyBooleanConfig,N as applyDateConfig,A as applyNumberConfig,I as applyStringConfig,U as array,q as boolean,g as createTypeValidatorTest,u as createValidatorTest,W as date,te as email,$ as exact,E as formatMessage,w as hasOwnProperty,X as integer,p as invalid,D as invalidDate,M as isObject,B as matches,F as max,Q as maxDate,Z as min,J as minDate,Y as number,v as object,K as oneOf,h as parseArray,k as parseBoolean,x as parseDate,O as parseNumber,R as parseString,z as required,ae as string,re as url,m as valid};
1
+ function T(e){return Object.prototype.toString.call(e)==="[object Object]"}function x(e,r){return Object.prototype.hasOwnProperty.call(e,r)}var I=/{(\w+)}/g;function M(e,r){return typeof e=="string"?e.replaceAll(I,(t,a)=>String(r[a])):e(r)}async function m({value:e,field:r}){return{isValid:!0,state:"valid",value:e,field:r}}async function p({errors:e,field:r,message:t,value:a,extras:n}){return{isValid:!1,state:"invalid",message:M(t,{...n,value:a,field:r}),value:a,field:r,errors:e}}function D(e){if(Array.isArray(e)||e==null)return e;let r=e;return r[Symbol.iterator]?[...r]:[]}function w(e,r){let t=e.parser(r);return e.default!==void 0&&(t==null||t.length===0)&&(t=e.default),t}async function R(e,r,t){for(let a of e){let n=await a(r,t);if(n.state==="invalid")return n}}async function B(e,r,t){let a=!0,n=[];if(!r||!e)return{isValid:a,errors:n};for(let[s,i]of r.entries()){let o=await e(i,t?`${t}[${s}]`:`[${s}]`);o.state==="invalid"?(a=!1,n.push(o.message||o.errors)):n.push(null)}return{isValid:a,errors:n}}function j(e,...r){let t=r,a={parser:D};return e!==void 0&&(typeof e=="function"?t=[e,...r]:a={...a,...e}),async(n,s)=>{let i=w(a,n),[o,...d]=t,f=await R(d,i,s),u=await B(o,i,s);return!f&&u.isValid?m({value:i,field:s}):p({message:f?f.message:"",value:n,field:s,errors:u.errors})}}function g(e,r){return(t,...a)=>{let n=e,s=a;return t!==void 0&&(typeof t=="function"?s=[t,...a]:n={...e,...t}),async(i,o)=>{try{let d=r(i,n);for(let f of s){let u=await f(d,o);if(u.state==="invalid")return u}return await m({value:d,field:o})}catch(d){return p({message:d instanceof Error?d.message:String(d),value:i,field:o})}}}}function l(e,r,t){return async(a,n)=>e(a,n)?m({value:a,field:n}):p({message:r,value:a,field:n,extras:t?t(a):void 0})}function C(e){return e==null||typeof e=="boolean"?e:!!e}function h(e,r){let t=r.parser(e);return r.default!==void 0&&t==null&&(t=r.default),t}var F=g({parser:C},h);var b=new Date(""),$=/^(\d{4})(?:-([0-2]\d)(?:-([0-3]\d)(?:[ T]([0-2]\d):([0-5]\d)(?::([0-5]\d)(\.\d+)?(Z|[+-][0-2]\d:?[0-5]\d)?)?)?)?)?$/,z=/^([+-])([0-2]\d):?([0-5]\d)$/;function Z(e){let r=z.exec(e);if(e==="Z"||!r)return 0;let[,t,a="0",n="0"]=r,s=t==="-"?-1:1,o=Number.parseInt(a,10)*60+Number.parseInt(n,10);return s*o}var V=10,K=[()=>0,(e="0")=>Number.parseInt(e,V),(e="1")=>Number.parseInt(e,V)-1,(e="1")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseInt(e,V),(e="0")=>Number.parseFloat(e)*1e3];function y(e){return e==null||e instanceof Date?e:typeof e=="number"?new Date(e):typeof e=="string"?U(e):b}function U(e){let r=$.exec(e);if(r===null)return b;let[,t=0,a=0,n=0,s=0,i=0,o=0,d=0]=K.map((u,O)=>u(r[O])),f=r[8];return f?new Date(Date.UTC(t,a,n,s,i+Z(f),o,d)):new Date(t,a,n,s,i,o,d)}function E(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||Number.isNaN(t.getTime()))&&(t=r.default),t}function q(e,r,t){let a=y(e);return l(n=>a!=null&&(n==null||n instanceof Date&&(t?n>a:n>=a)),r,()=>({min:a,limit:a,exclusive:t}))}function L(e,r,t){let a=y(e);return l(n=>a!=null&&(n==null||n instanceof Date&&(t?n<a:n<=a)),r,()=>({max:a,limit:a,exclusive:t}))}var _=g({parser:y},E);function k(e){return e==null||typeof e=="number"?e:e instanceof Date?e.getTime():typeof e=="string"?Number.parseFloat(e):Number.parseFloat(String(e))}function S(e,r){let t=r.parser(e);if(r.default!==void 0&&(t==null||Number.isNaN(t))&&(t=r.default),r.round&&typeof t=="number")switch(r.round){case"nearest":{t=Math.round(t);break}case"ceil":{t=Math.ceil(t);break}case"floor":{t=Math.floor(t);break}default:throw new Error(`Unknown round type: ${String(r.round)}`)}return t}function G(e){return async(r,t)=>r==null||typeof r=="number"&&Number.isFinite(r)&&Math.floor(r)===r?m({value:r,field:t}):p({message:e,value:r,field:t})}var H=g({parser:k},S);function J(e){if(typeof e!="object"||e===null)throw new TypeError("`properties` must be a configuration object");return async(r,t)=>{let a=r??{},n={},s={},i=!0;for(let o in e)if(x(e,o)){let d=e[o],f=a[o],u=typeof d=="function"?await d(f,o):await p({field:o,message:"No validator set",value:f});s[o]=u.value,u.state==="invalid"&&(i=!1,n[o]=u.message||u.errors)}return i?m({value:s,field:t}):p({message:"",value:r,field:t,errors:n})}}function Q(e,r){return l(t=>r&&t===null||t!=null&&!(typeof t=="string"&&t==="")&&!(typeof t=="number"&&Number.isNaN(t))&&!(t instanceof Date&&Number.isNaN(t.valueOf())),e)}function W(e,r){return l(t=>t==null||e.includes(t)||t instanceof Date&&e.some(a=>a.valueOf()===t.valueOf()),r,()=>({values:e}))}function c(e){return typeof e=="string"||Array.isArray(e)?e.length:e}function X(e,r,t){return l(a=>{let n=c(a);return n==null||a===""||(t?n<e:n<=e)},r,a=>({max:e,limit:e,amount:c(a),exclusive:t}))}function Y(e,r,t){return l(a=>{let n=c(a);return n==null||a===""||(t?n>e:n>=e)},r,a=>({min:e,limit:e,amount:c(a),exclusive:t}))}function v(e,r){return l(t=>{let a=c(t);return a==null||t===""||a===e},r,t=>({amount:c(t),limit:e,exact:e}))}var ee=/^[\w!#$%&'*+./=?^`{|}~-]+@[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?(?:\.[\dA-Za-z](?:[\dA-Za-z-]{0,61}[\dA-Za-z])?)*$/,te=/^(?:[\da-f]{8}-[\da-f]{4}-[1-8][\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}|0{8}-0{4}-0{4}-0{4}-0{12}|f{8}-f{4}-f{4}-f{4}-f{12})$/i;function N(e){if(e==null||typeof e=="string")return e;if(e instanceof Date)return e.toISOString();if(T(e))throw new TypeError("Failed to parse value to string.");return String(e)}function A(e,r){let t=r.parser(e);return r.default!==void 0&&(t==null||t==="")&&(t=r.default),r.trim&&typeof t=="string"&&(t=t.trim()),t}function P(e,r){let t=new RegExp(e);return l(a=>(t.lastIndex=0,a==null||a===""||typeof a=="string"&&t.test(a)),r,()=>({pattern:e}))}function re(e){return P(ee,e)}function ae(e){return P(te,e)}function ne(e,r){return l(t=>{try{let a;if(t==null||t===""||typeof t=="string"&&(a=new URL(t)))return!(a&&r&&!r.includes(a.protocol))}catch{}return!1},e,()=>({protocols:r}))}var oe=g({parser:N},A);export{w as applyArrayConfig,h as applyBooleanConfig,E as applyDateConfig,S as applyNumberConfig,A as applyStringConfig,j as array,F as boolean,g as createTypeValidatorTest,l as createValidatorTest,_ as date,re as email,v as exact,M as formatMessage,x as hasOwnProperty,G as integer,p as invalid,b as invalidDate,T as isObject,P as matches,X as max,L as maxDate,Y as min,q as minDate,H as number,J as object,W as oneOf,D as parseArray,C as parseBoolean,y as parseDate,k as parseNumber,N as parseString,Q as required,oe as string,ne as url,ae as uuid,m as valid};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared.ts","../src/arrays.ts","../src/booleans.ts","../src/dates.ts","../src/numbers.ts","../src/objects.ts","../src/strings.ts"],"sourcesContent":["export type ValidResult<T> = {\n /**\n * True if the original value is valid according to all validation tests\n * @deprecated Use `state` instead.\n */\n isValid: true;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'valid';\n /** The parsed value. Note that may be different than the original value. */\n value: T | null | undefined;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n};\n\nexport type InvalidResult<E> = {\n /**\n * True if the original value is valid according to all validation tests.\n * @deprecated Use `state` instead.\n */\n isValid: false;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'invalid';\n /** The parsed value. Note that may be different than the original value. */\n value: unknown;\n /** Error message if `state` is invalid. */\n message: string;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n /** Extra error details */\n errors?: E | undefined;\n};\n\n/**\n * The result of a validation.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorResult<T = any, E = any> =\n | ValidResult<T>\n | InvalidResult<E>;\n\n/**\n * Validation test function.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorTest<T = any, E = any> = (\n value?: unknown,\n field?: string,\n) => Promise<ValidatorResult<T, E>>;\n\n/**\n * Extracts the generic error type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractError<T extends ValidatorTest> =\n T extends ValidatorTest<any, infer E> ? E : unknown;\n\n/**\n * Extracts the generic value type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractValue<T extends ValidatorTest> =\n T extends ValidatorTest<infer V> ? V : unknown;\n\n/**\n * Make a deep partial type.\n * @typeParam T any object type\n * @category Types\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n\n/**\n * Validation factory function.\n * @typeParam C The configuration type\n * @category Types\n */\nexport type ValidatorFactory<C, T, E> = (\n config?: Partial<C> | ValidatorTest,\n ...tests: ValidatorTest[]\n) => ValidatorTest<T, E>;\n\n/**\n * Base configuration type.\n * @typeParam T The target type.\n * @category Types\n */\nexport interface ConfigBase<T> {\n /** Parser to convert value into the designated type. */\n parser: (value: unknown) => T | null | undefined;\n /** Provide a fallback value in case the original value is undefined. */\n default?: T;\n}\n\nexport interface ValidatorMessageParameters<T> {\n value: T | null | undefined;\n field: string | undefined;\n}\n\n/**\n * Validation message. May be a plain string or a function that accepts arguments.\n * While using a string, values in squiggly brackets `{}` are replaced.\n * @category Types\n */\nexport type ValidatorMessage<\n T,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n> = string | ((parameters: P) => string);\n\n/**\n * Simple check for objects.\n * @param value Value to test\n */\nexport function isObject(value: unknown): boolean {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/**\n * Safe hasOwnProperty check\n * @param object Object to check\n * @param property Property to look for\n */\nexport function hasOwnProperty(\n object: unknown,\n property: string | number | symbol,\n): boolean {\n return Object.prototype.hasOwnProperty.call(object, property);\n}\n\n/** @internal */\nconst formatPattern = /{(\\w+)}/g;\n\n/**\n * Formats a message using a squiggly bracket `{}` template.\n * @param template Message template as string or function\n * @param parameters Params to inject into template\n * @category Helpers\n */\nexport function formatMessage<T, P extends ValidatorMessageParameters<T>>(\n template: ValidatorMessage<T, P>,\n parameters: P,\n): string {\n if (typeof template === 'string') {\n return template.replaceAll(formatPattern, (_, key: string) =>\n String((parameters as Record<string, unknown>)[key]),\n );\n }\n\n return template(parameters);\n}\n\n/**\n * Creates a valid result\n * @param value Parsed value\n * @param field Field name\n * @category Helpers\n */\nexport async function valid<T, E = never>({\n value,\n field,\n}: {\n value: T | null | undefined;\n field: string | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: true,\n state: 'valid',\n value,\n field,\n };\n}\n\n/**\n * Creates an invalid result.\n * @param message Error message\n * @param value Parsed value\n * @param field Field name\n * @param extras Extra message params\n * @category Helpers\n */\nexport async function invalid<\n T,\n E,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>({\n errors,\n field,\n message,\n value,\n extras,\n}: {\n message: ValidatorMessage<T, P>;\n value: unknown;\n field: string | undefined;\n errors?: E | undefined;\n extras?: Omit<P, 'field' | 'value'> | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: false,\n state: 'invalid',\n message: formatMessage(message, { ...extras, value, field } as P),\n value,\n field,\n errors,\n };\n}\n\n/**\n * Creates a type validator.\n * @typeParam T The basic type for the final value to be validated.\n * @typeParam C The configuration type.\n * @param defaultParser Parser to convert value into type.\n * @param applyConfig Function that applies configuration to value.\n * @category Helpers\n */\nexport function createTypeValidatorTest<T, C extends ConfigBase<T>>(\n defaultConfig: C,\n applyConfig: (value: unknown, config: C) => T | null | undefined,\n): ValidatorFactory<C, T, string> {\n return (config, ...tests) => {\n let finalConfig = defaultConfig;\n let allTests = tests;\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...defaultConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n try {\n const parsedValue = applyConfig(value, finalConfig);\n for (const validatorTest of allTests) {\n const result = await validatorTest(parsedValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return await valid({ value: parsedValue, field });\n } catch (error) {\n return invalid({\n message: error instanceof Error ? error.message : String(error),\n value,\n field,\n });\n }\n };\n };\n}\n\n/**\n * Captures basic validator test pattern\n * @param test Test function\n * @param message Error message\n * @param getExtras Optional extra fields for error message\n */\nexport function createValidatorTest<\n T = any,\n E = any,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>(\n test: (value: unknown, field?: string) => boolean,\n message: ValidatorMessage<T, P>,\n getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>,\n): ValidatorTest<T, E> {\n return async (value, field) => {\n if (test(value, field)) {\n return valid({ value: value as T, field });\n }\n\n return invalid({\n message,\n value,\n field,\n extras: getExtras ? getExtras(value as T) : undefined,\n });\n };\n}\n\n/**\n * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.\n * @param message Error message\n * @param nullable Allow null values\n * @category Validation Tests\n */\nexport function required<T, P extends ValidatorMessageParameters<T>>(\n message: ValidatorMessage<T, P>,\n nullable?: boolean,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n (nullable && value === null) ||\n (value !== null &&\n value !== undefined &&\n !(typeof value === 'string' && value === '') &&\n !(typeof value === 'number' && Number.isNaN(value)) &&\n !(value instanceof Date && Number.isNaN(value.valueOf()))),\n message,\n );\n}\n\nexport type SharedValueType = string | number | unknown[];\n\n/**\n * Extracts a numeric amount from value, i.e. string length, array length, or number.\n * @internal\n */\nfunction getAmount(value: SharedValueType | null | undefined) {\n return typeof value === 'string' || Array.isArray(value)\n ? value.length\n : value;\n}\n\nexport interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n max: number;\n amount: number | null | undefined;\n limit: number;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function max(\n limit: number,\n message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount < limit : amount <= limit)\n );\n },\n message,\n (value) => ({\n max: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n min: number;\n limit: number;\n amount: number | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function min(\n limit: number,\n message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount > limit : amount >= limit)\n );\n },\n message,\n (value) => ({\n min: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n limit: number;\n amount: number | null | undefined;\n exact: number;\n}\n\n/**\n * Ensures a string, number, or array value is exactly a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @category Validation Tests\n */\nexport function exact(\n limit: number,\n message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n amount === limit\n );\n },\n message,\n (value) => ({\n amount: getAmount(value),\n limit,\n exact: limit,\n }),\n );\n}\n\nexport interface OneOfValidatorMessageParameters<\n T,\n> extends ValidatorMessageParameters<T> {\n values: readonly T[];\n}\n\n/**\n * Ensures a value is one in a predefined list.\n * @param values List of allowed values.\n * @param message Error message\n * @category Validation Tests\n */\nexport function oneOf<T extends string | number | boolean | Date>(\n values: readonly T[],\n message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n value === undefined ||\n value === null ||\n values.includes(value as T) ||\n (value instanceof Date &&\n values.some((x) => x.valueOf() === value.valueOf())),\n message,\n () => ({ values }),\n );\n}\n","import {\n invalid,\n valid,\n type ConfigBase,\n type ValidatorResult,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Invalid validation result for an item in the array\n * @category Types\n */\nexport type ArrayItemValidatorResult<E = unknown> = null | string | E;\n\n/**\n * Configuration for array validation.\n * @category Types\n */\nexport type ArrayConfig = ConfigBase<unknown[]>;\n\n/**\n * Parses a value into an array.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseArray(value: unknown): unknown[] | null | undefined {\n if (Array.isArray(value)) {\n return value as unknown[];\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n const iterable = value as Iterable<unknown>;\n\n if (iterable[Symbol.iterator]) {\n return [...iterable];\n }\n\n return [];\n}\n\n/**\n * Applies a configuration to the array value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyArrayConfig<T>(\n config: ArrayConfig,\n value: unknown,\n): T[] | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n parsedValue.length === 0)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue as T[];\n}\n\n/**\n * Validates an array. The first passed validator is used to validate individual\n * items. The remaining validators target the array itself.\n * @category Type Validators\n */\nexport function array<T, E>(\n config?: Partial<ArrayConfig> | ValidatorTest<T, E>,\n ...tests: ValidatorTest[]\n): ValidatorTest<T[], string | ArrayItemValidatorResult<E>[]> {\n let allTests = tests;\n let finalConfig: ArrayConfig = {\n parser: parseArray,\n };\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...finalConfig,\n ...config,\n };\n }\n }\n\n // oxlint-disable-next-line eslint/complexity -- array and item tests share one closure; split in #483\n return async (value, field) => {\n const arrayValue = applyArrayConfig<T>(finalConfig, value);\n let arrayInvalidResult: ValidatorResult | undefined;\n let isValid = true;\n const errors: ArrayItemValidatorResult[] = [];\n const [validateItem, ...arrayTests] = allTests;\n\n for (const validatorTest of arrayTests) {\n const result = await validatorTest(arrayValue, field);\n if (result.state === 'invalid') {\n isValid = false;\n arrayInvalidResult = result;\n break;\n }\n }\n\n if (arrayValue && validateItem) {\n for (const [index, item] of arrayValue.entries()) {\n const result = await validateItem(\n item,\n field ? `${field}[${index}]` : `[${index}]`,\n );\n\n if (result.state === 'invalid') {\n isValid = false;\n errors.push(result.message || result.errors);\n } else {\n errors.push(null);\n }\n }\n }\n\n if (isValid) {\n return valid({\n value: arrayValue,\n field,\n });\n }\n\n return invalid<T[], ArrayItemValidatorResult<E>[]>({\n message:\n arrayInvalidResult?.state === 'invalid'\n ? arrayInvalidResult.message\n : '',\n value,\n field,\n errors: errors as ArrayItemValidatorResult<E>[],\n });\n };\n}\n","import { type ConfigBase, createTypeValidatorTest } from './shared.js';\n\n/**\n * Parses a value into a boolean.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseBoolean(value: unknown): boolean | null | undefined {\n if (value === undefined || value === null) {\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n return Boolean(value);\n}\n\n/**\n * Applies a configuration to the boolean value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyBooleanConfig(\n value: unknown,\n config: BooleanConfig,\n): boolean | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\n/**\n * Configuration for boolean validation.\n * @category Types\n */\nexport type BooleanConfig = ConfigBase<boolean>;\n\n/**\n * Validates a boolean value.\n * @category Type Validators\n */\nexport const boolean = createTypeValidatorTest(\n { parser: parseBoolean },\n applyBooleanConfig,\n);\n","import {\n createTypeValidatorTest,\n createValidatorTest,\n type ConfigBase,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** Badly formatted date for internal use. */\nexport const invalidDate = new Date('');\n\n/** @internal */\nconst isoDatePattern =\n /^(\\d{4})(?:-([0-2]\\d)(?:-([0-3]\\d)(?:[ T]([0-2]\\d):([0-5]\\d)(?::([0-5]\\d)(\\.\\d+)?(Z|[+-][0-2]\\d:?[0-5]\\d)?)?)?)?)?$/;\n\n/** @internal */\nconst timezonePattern = /^([+-])([0-2]\\d):?([0-5]\\d)$/;\n\n/**\n * Parses a timezone string.\n * @param timezone Timezone to parse\n * @internal\n */\nfunction parseTimezone(timezone: string): number {\n const parts = timezonePattern.exec(timezone);\n\n if (timezone === 'Z' || !parts) {\n return 0;\n }\n\n const [, sign, hour = '0', minute = '0'] = parts;\n const multiplier = sign === '-' ? -1 : 1;\n const hoursInMinutes = Number.parseInt(hour, 10) * 60;\n const offset = hoursInMinutes + Number.parseInt(minute, 10);\n\n return multiplier * offset;\n}\n\nconst BASE = 10;\n\nconst dateParts = [\n // Skip\n () => 0,\n // Year\n (part = '0') => Number.parseInt(part, BASE),\n // Month\n (part = '1') => Number.parseInt(part, BASE) - 1,\n // Day\n (part = '1') => Number.parseInt(part, BASE),\n // Hour\n (part = '0') => Number.parseInt(part, BASE),\n // Minute\n (part = '0') => Number.parseInt(part, BASE),\n // Second\n (part = '0') => Number.parseInt(part, BASE),\n // Millisecond\n (part = '0') => Number.parseFloat(part) * 1e3,\n];\n\n/**\n * Parses a value into a date.\n * @param value Value to parse\n * @category Parsers\n */\n// oxlint-disable-next-line eslint/complexity -- one guard per input type plus ISO parsing; split in #483\nexport function parseDate(value: unknown): Date | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === 'number') {\n return new Date(value);\n }\n\n if (typeof value !== 'string') {\n return invalidDate;\n }\n\n const parts = isoDatePattern.exec(value);\n\n if (parts === null) {\n return invalidDate;\n }\n\n const [\n ,\n year = 0,\n month = 0,\n day = 0,\n hour = 0,\n minute = 0,\n second = 0,\n millisecond = 0,\n ] = dateParts.map((parse, index) => parse(parts[index]));\n\n const timezone = parts[8];\n\n if (!timezone) {\n return new Date(year, month, day, hour, minute, second, millisecond);\n }\n\n const minuteOffset = parseTimezone(timezone);\n\n return new Date(\n Date.UTC(\n year,\n month,\n day,\n hour,\n minute + minuteOffset,\n second,\n millisecond,\n ),\n );\n}\n\n/**\n * Applies a configuration to the date value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyDateConfig(\n value: unknown,\n config: DateConfig,\n): Date | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue.getTime()))\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\nexport type SharedDateValueType = Date | string | number;\n\nexport interface MinDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n min: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or after a date.\n * @param limit Minimum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function minDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MinDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date, null> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value > parsedDate : value >= parsedDate))),\n message,\n () => ({\n min: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\nexport interface MaxDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n max: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or before a date.\n * @param limit Maximum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function maxDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MaxDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value < parsedDate : value <= parsedDate))),\n message,\n () => ({\n max: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\n/**\n * Configuration for date validation.\n * @category Types\n */\nexport type DateConfig = ConfigBase<Date>;\n\n/**\n * Validates a date value.\n * @category Type Validators\n */\nexport const date = createTypeValidatorTest(\n { parser: parseDate },\n applyDateConfig,\n);\n","import {\n type ConfigBase,\n createTypeValidatorTest,\n invalid,\n valid,\n type ValidatorMessage,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Parses a value into a number.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseNumber(value: unknown): number | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.getTime();\n }\n\n if (typeof value === 'string') {\n return Number.parseFloat(value);\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- coerces all other input on purpose; #484 decides non-primitives\n return Number.parseFloat(String(value));\n}\n\n/**\n * Applies a configuration to the number value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyNumberConfig(\n value: unknown,\n config: NumberConfig,\n): number | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue))\n ) {\n parsedValue = config.default;\n }\n\n if (config.round && typeof parsedValue === 'number') {\n switch (config.round) {\n case 'nearest': {\n parsedValue = Math.round(parsedValue);\n break;\n }\n case 'ceil': {\n parsedValue = Math.ceil(parsedValue);\n break;\n }\n case 'floor': {\n parsedValue = Math.floor(parsedValue);\n break;\n }\n default: {\n throw new Error(`Unknown round type: ${String(config.round)}`);\n }\n }\n }\n\n return parsedValue;\n}\n\n/**\n * Ensures a number value is an integer.\n * @param message Error message\n * @category Validation Tests\n */\nexport function integer(\n message: ValidatorMessage<number>,\n): ValidatorTest<number> {\n return async (value, field) => {\n if (\n value === undefined ||\n value === null ||\n (typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.floor(value) === value)\n ) {\n return valid({ value, field });\n }\n\n return invalid({\n message,\n value,\n field,\n });\n };\n}\n\n/**\n * Configuration for number validation.\n * @category Types\n */\nexport interface NumberConfig extends ConfigBase<number> {\n /** Apply rounding mechanism before validation. */\n round?: 'nearest' | 'floor' | 'ceil';\n}\n\n/**\n * Validates a number value.\n * @category Type Validators\n */\nexport const number = createTypeValidatorTest(\n {\n parser: parseNumber,\n },\n applyNumberConfig,\n);\n","import {\n type ExtractError,\n type ExtractValue,\n hasOwnProperty,\n invalid,\n valid,\n type ValidatorTest,\n} from './shared.js';\n\nexport type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;\n\n/**\n * Validates an object.\n * @category Type Validators\n */\nexport function object<\n P extends ObjectParameter,\n V extends { [K in keyof P]?: ExtractValue<P[K]> },\n E extends { [K in keyof P]?: ExtractError<P[K]> },\n>(properties: P): ValidatorTest<V, E> {\n if (typeof properties !== 'object' || properties === null) {\n throw new TypeError('`properties` must be a configuration object');\n }\n\n return async (values, field) => {\n const definedValues = (values ?? {}) as V;\n const errors = {} as E;\n const resolvedValues = {} as V;\n let isValid = true;\n\n for (const key in properties) {\n if (hasOwnProperty(properties, key)) {\n const validator = properties[key];\n const value = definedValues[key];\n const result =\n typeof validator === 'function'\n ? await validator(value, key)\n : await invalid({ field: key, message: 'No validator set', value });\n\n resolvedValues[key] = result.value as V[Extract<keyof P, string>];\n\n if (result.state === 'invalid') {\n isValid = false;\n errors[key] = (result.message || result.errors) as E[Extract<\n keyof P,\n string\n >];\n }\n }\n }\n\n if (isValid) {\n return valid({ value: resolvedValues, field });\n }\n\n return invalid({\n message: '',\n value: values,\n field,\n errors,\n });\n };\n}\n","import {\n type ConfigBase,\n createTypeValidatorTest,\n createValidatorTest,\n isObject,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** @internal */\nconst emailPattern =\n /^[\\w!#$%&'*+./=?^`{|}~-]+@[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?(?:\\.[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?)*$/;\n\n/**\n * Configuration for string validation.\n * @category Types\n */\nexport interface StringConfig extends ConfigBase<string> {\n /** Apply trim to string before validation. */\n trim?: boolean;\n}\n\n/**\n * Parses a value into a string.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseString(value: unknown): string | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (isObject(value)) {\n throw new TypeError('Failed to parse value to string.');\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- only plain objects throw above; #484 decides other non-primitives\n return String(value);\n}\n\n/**\n * Applies a configuration to the string value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyStringConfig(\n value: unknown,\n config: StringConfig,\n): string | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null || parsedValue === '')\n ) {\n parsedValue = config.default;\n }\n\n if (config.trim && typeof parsedValue === 'string') {\n parsedValue = parsedValue.trim();\n }\n\n return parsedValue;\n}\n\nexport interface MatchesValidatorMessageParameters extends ValidatorMessageParameters<string> {\n pattern: RegExp;\n}\n\n/**\n * Ensures a string value matches a pattern\n * @param pattern Pattern to match\n * @param message Error message\n * @category Validation Tests\n */\nexport function matches(\n pattern: RegExp,\n message: ValidatorMessage<string, MatchesValidatorMessageParameters>,\n): ValidatorTest<string> {\n // A g or y pattern advances lastIndex on each test(), so a shared one would\n // fail matching values after a match. Test a private copy from index 0.\n const ownPattern = new RegExp(pattern);\n return createValidatorTest(\n (value) => {\n ownPattern.lastIndex = 0;\n return (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && ownPattern.test(value))\n );\n },\n message,\n () => ({ pattern }),\n );\n}\n\n/**\n * Ensures a string value matches an email pattern\n * @param message Error message\n * @category Validation Tests\n */\nexport function email(\n message: ValidatorMessage<string>,\n): ValidatorTest<string> {\n return matches(emailPattern, message);\n}\n\n/**\n * Ensures a string value is a valid URL\n * @param message Error message\n * @param protocols Optional list of protocols to allow. Without it, `javascript:`\n * and `data:` URLs are valid; use `['http:', 'https:']` for values rendered as links.\n * @category Validation Tests\n */\nexport function url(\n message: ValidatorMessage<string>,\n protocols?: string[],\n): ValidatorTest<string> {\n return createValidatorTest(\n (value) => {\n try {\n let url: URL | undefined;\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && (url = new URL(value)))\n ) {\n return !(url && protocols && !protocols.includes(url.protocol));\n }\n } catch {\n // Do nothing\n }\n\n return false;\n },\n message,\n () => ({ protocols }),\n );\n}\n\n/**\n * Validates a string value.\n * @category Type Validators\n */\nexport const string = createTypeValidatorTest(\n {\n parser: parseString,\n },\n applyStringConfig,\n);\n"],"mappings":"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","names":["isObject","value","hasOwnProperty","object","property","formatPattern","formatMessage","template","parameters","_","key","valid","field","invalid","errors","message","extras","createTypeValidatorTest","defaultConfig","applyConfig","config","tests","finalConfig","allTests","parsedValue","validatorTest","result","error","createValidatorTest","test","getExtras","required","nullable","getAmount","max","limit","exclusive","amount","min","exact","oneOf","values","x","parseArray","value","iterable","applyArrayConfig","config","parsedValue","array","tests","allTests","finalConfig","field","arrayValue","arrayInvalidResult","isValid","errors","validateItem","arrayTests","validatorTest","result","index","item","valid","invalid","parseBoolean","value","applyBooleanConfig","config","parsedValue","boolean","createTypeValidatorTest","invalidDate","isoDatePattern","timezonePattern","parseTimezone","timezone","parts","sign","hour","minute","multiplier","offset","BASE","dateParts","part","parseDate","value","year","month","day","second","millisecond","parse","index","minuteOffset","applyDateConfig","config","parsedValue","minDate","limit","message","exclusive","parsedDate","createValidatorTest","maxDate","date","createTypeValidatorTest","parseNumber","value","applyNumberConfig","config","parsedValue","integer","message","field","valid","invalid","number","createTypeValidatorTest","object","properties","values","field","definedValues","errors","resolvedValues","isValid","key","hasOwnProperty","validator","value","result","invalid","valid","emailPattern","parseString","value","isObject","applyStringConfig","config","parsedValue","matches","pattern","message","ownPattern","createValidatorTest","email","url","protocols","string","createTypeValidatorTest"]}
1
+ {"version":3,"sources":["../src/shared.ts","../src/arrays.ts","../src/factories.ts","../src/booleans.ts","../src/parse-date.ts","../src/dates.ts","../src/numbers.ts","../src/objects.ts","../src/common.ts","../src/limits.ts","../src/strings.ts"],"sourcesContent":["export type ValidResult<T> = {\n /**\n * True if the original value is valid according to all validation tests\n * @deprecated Use `state` instead.\n */\n isValid: true;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'valid';\n /** The parsed value. Note that may be different than the original value. */\n value: T | null | undefined;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n};\n\nexport type InvalidResult<E> = {\n /**\n * True if the original value is valid according to all validation tests.\n * @deprecated Use `state` instead.\n */\n isValid: false;\n /** This is preferred to use over `isValid` as it works better for type guards. */\n state: 'invalid';\n /** The parsed value. Note that may be different than the original value. */\n value: unknown;\n /** Error message if `state` is invalid. */\n message: string;\n /** Field name if provided. Automatically provided if using object validation. */\n field?: string | undefined;\n /** Extra error details */\n errors?: E | undefined;\n};\n\n/**\n * The result of a validation.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorResult<T = any, E = any> =\n | ValidResult<T>\n | InvalidResult<E>;\n\n/**\n * Validation test function.\n * @typeParam T The value type\n * @category Types\n */\nexport type ValidatorTest<T = any, E = any> = (\n value?: unknown,\n field?: string,\n) => Promise<ValidatorResult<T, E>>;\n\n/**\n * Extracts the generic error type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractError<T extends ValidatorTest> =\n T extends ValidatorTest<any, infer E> ? E : unknown;\n\n/**\n * Extracts the generic value type from a ValidatorTest.\n * @typeParam T a ValidatorTest\n * @category Types\n */\nexport type ExtractValue<T extends ValidatorTest> =\n T extends ValidatorTest<infer V> ? V : unknown;\n\n/**\n * Make a deep partial type.\n * @typeParam T any object type\n * @category Types\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n\n/**\n * Validation factory function.\n * @typeParam C The configuration type\n * @category Types\n */\nexport type ValidatorFactory<C, T, E> = (\n config?: Partial<C> | ValidatorTest,\n ...tests: ValidatorTest[]\n) => ValidatorTest<T, E>;\n\n/**\n * Base configuration type.\n * @typeParam T The target type.\n * @category Types\n */\nexport interface ConfigBase<T> {\n /** Parser to convert value into the designated type. */\n parser: (value: unknown) => T | null | undefined;\n /** Provide a fallback value in case the original value is undefined. */\n default?: T;\n}\n\nexport interface ValidatorMessageParameters<T> {\n value: T | null | undefined;\n field: string | undefined;\n}\n\n/**\n * Validation message. May be a plain string or a function that accepts arguments.\n * While using a string, values in squiggly brackets `{}` are replaced.\n * @category Types\n */\nexport type ValidatorMessage<\n T,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n> = string | ((parameters: P) => string);\n\n/**\n * Simple check for objects.\n * @param value Value to test\n */\nexport function isObject(value: unknown): boolean {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/**\n * Safe hasOwnProperty check\n * @param object Object to check\n * @param property Property to look for\n */\nexport function hasOwnProperty(\n object: unknown,\n property: string | number | symbol,\n): boolean {\n return Object.prototype.hasOwnProperty.call(object, property);\n}\n\n/** @internal */\nconst formatPattern = /{(\\w+)}/g;\n\n/**\n * Formats a message using a squiggly bracket `{}` template.\n * @param template Message template as string or function\n * @param parameters Params to inject into template\n * @category Helpers\n */\nexport function formatMessage<T, P extends ValidatorMessageParameters<T>>(\n template: ValidatorMessage<T, P>,\n parameters: P,\n): string {\n if (typeof template === 'string') {\n return template.replaceAll(formatPattern, (_, key: string) =>\n String((parameters as Record<string, unknown>)[key]),\n );\n }\n\n return template(parameters);\n}\n\n/**\n * Creates a valid result\n * @param result Result fields\n * @param result.value Parsed value\n * @param result.field Field name\n * @category Helpers\n */\nexport async function valid<T, E = never>({\n value,\n field,\n}: {\n value: T | null | undefined;\n field: string | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: true,\n state: 'valid',\n value,\n field,\n };\n}\n\n/**\n * Creates an invalid result.\n * @param result Result fields\n * @param result.message Error message, formatted with `formatMessage`\n * @param result.value Parsed value\n * @param result.field Field name\n * @param result.errors Extra error details, such as per-field errors from `object` and `array`\n * @param result.extras Extra message params\n * @category Helpers\n */\nexport async function invalid<\n T,\n E,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>({\n errors,\n field,\n message,\n value,\n extras,\n}: {\n message: ValidatorMessage<T, P>;\n value: unknown;\n field: string | undefined;\n errors?: E | undefined;\n extras?: Omit<P, 'field' | 'value'> | undefined;\n}): Promise<ValidatorResult<T, E>> {\n return {\n isValid: false,\n state: 'invalid',\n message: formatMessage(message, { ...extras, value, field } as P),\n value,\n field,\n errors,\n };\n}\n","import {\n invalid,\n valid,\n type ConfigBase,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Invalid validation result for an item in the array\n * @category Types\n */\nexport type ArrayItemValidatorResult<E = unknown> = null | string | E;\n\n/**\n * Configuration for array validation.\n * @category Types\n */\nexport type ArrayConfig = ConfigBase<unknown[]>;\n\n/**\n * Parses a value into an array.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseArray(value: unknown): unknown[] | null | undefined {\n if (Array.isArray(value)) {\n return value as unknown[];\n }\n\n if (value === null || value === undefined) {\n return value;\n }\n\n const iterable = value as Iterable<unknown>;\n\n if (iterable[Symbol.iterator]) {\n return [...iterable];\n }\n\n return [];\n}\n\n/**\n * Applies a configuration to the array value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyArrayConfig<T>(\n config: ArrayConfig,\n value: unknown,\n): T[] | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n parsedValue.length === 0)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue as T[];\n}\n\n/**\n * Runs the tests that target the array itself, stopping at the first failure.\n * @param tests Array-level tests\n * @param arrayValue Parsed array\n * @param field Field name\n * @internal\n */\nasync function findArrayInvalidResult(\n tests: ValidatorTest[],\n arrayValue: unknown[] | null | undefined,\n field: string | undefined,\n) {\n for (const validatorTest of tests) {\n const result = await validatorTest(arrayValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return undefined;\n}\n\n/**\n * Runs the item test on every item, collecting `null` for valid items and the\n * message or errors for invalid ones. Without an array or an item test, there\n * is nothing to check.\n * @param validateItem Item test\n * @param arrayValue Parsed array\n * @param field Field name\n * @internal\n */\nasync function validateItems(\n validateItem: ValidatorTest | undefined,\n arrayValue: unknown[] | null | undefined,\n field: string | undefined,\n) {\n let isValid = true;\n const errors: ArrayItemValidatorResult[] = [];\n\n if (!arrayValue || !validateItem) {\n return { isValid, errors };\n }\n\n for (const [index, item] of arrayValue.entries()) {\n const result = await validateItem(\n item,\n field ? `${field}[${index}]` : `[${index}]`,\n );\n\n if (result.state === 'invalid') {\n isValid = false;\n errors.push(result.message || result.errors);\n } else {\n errors.push(null);\n }\n }\n\n return { isValid, errors };\n}\n\n/**\n * Validates an array. The first passed validator is used to validate individual\n * items. The remaining validators target the array itself.\n * @category Type Validators\n */\nexport function array<T, E>(\n config?: Partial<ArrayConfig> | ValidatorTest<T, E>,\n ...tests: ValidatorTest[]\n): ValidatorTest<T[], string | ArrayItemValidatorResult<E>[]> {\n let allTests = tests;\n let finalConfig: ArrayConfig = {\n parser: parseArray,\n };\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...finalConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n const arrayValue = applyArrayConfig<T>(finalConfig, value);\n const [validateItem, ...arrayTests] = allTests;\n\n const arrayInvalidResult = await findArrayInvalidResult(\n arrayTests,\n arrayValue,\n field,\n );\n const items = await validateItems(validateItem, arrayValue, field);\n\n if (!arrayInvalidResult && items.isValid) {\n return valid({\n value: arrayValue,\n field,\n });\n }\n\n return invalid<T[], ArrayItemValidatorResult<E>[]>({\n message: arrayInvalidResult ? arrayInvalidResult.message : '',\n value,\n field,\n errors: items.errors as ArrayItemValidatorResult<E>[],\n });\n };\n}\n","import {\n type ConfigBase,\n invalid,\n valid,\n type ValidatorFactory,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Creates a type validator.\n * @typeParam T The basic type for the final value to be validated.\n * @typeParam C The configuration type.\n * @param defaultParser Parser to convert value into type.\n * @param applyConfig Function that applies configuration to value.\n * @category Helpers\n */\nexport function createTypeValidatorTest<T, C extends ConfigBase<T>>(\n defaultConfig: C,\n applyConfig: (value: unknown, config: C) => T | null | undefined,\n): ValidatorFactory<C, T, string> {\n return (config, ...tests) => {\n let finalConfig = defaultConfig;\n let allTests = tests;\n\n if (config !== undefined) {\n if (typeof config === 'function') {\n allTests = [config, ...tests];\n } else {\n finalConfig = {\n ...defaultConfig,\n ...config,\n };\n }\n }\n\n return async (value, field) => {\n try {\n const parsedValue = applyConfig(value, finalConfig);\n for (const validatorTest of allTests) {\n const result = await validatorTest(parsedValue, field);\n if (result.state === 'invalid') {\n return result;\n }\n }\n\n return await valid({ value: parsedValue, field });\n } catch (error) {\n return invalid({\n message: error instanceof Error ? error.message : String(error),\n value,\n field,\n });\n }\n };\n };\n}\n\n/**\n * Captures basic validator test pattern\n * @param test Test function\n * @param message Error message\n * @param getExtras Optional extra fields for error message\n */\nexport function createValidatorTest<\n T = any,\n E = any,\n P extends ValidatorMessageParameters<T> = ValidatorMessageParameters<T>,\n>(\n test: (value: unknown, field?: string) => boolean,\n message: ValidatorMessage<T, P>,\n getExtras?: (value: T | null | undefined) => Omit<P, 'value' | 'field'>,\n): ValidatorTest<T, E> {\n return async (value, field) => {\n if (test(value, field)) {\n return valid({ value: value as T, field });\n }\n\n return invalid({\n message,\n value,\n field,\n extras: getExtras ? getExtras(value as T) : undefined,\n });\n };\n}\n","import { createTypeValidatorTest } from './factories.js';\nimport type { ConfigBase } from './shared.js';\n\n/**\n * Parses a value into a boolean.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseBoolean(value: unknown): boolean | null | undefined {\n if (value === undefined || value === null) {\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n return Boolean(value);\n}\n\n/**\n * Applies a configuration to the boolean value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyBooleanConfig(\n value: unknown,\n config: BooleanConfig,\n): boolean | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null)\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\n/**\n * Configuration for boolean validation.\n * @category Types\n */\nexport type BooleanConfig = ConfigBase<boolean>;\n\n/**\n * Validates a boolean value.\n * @category Type Validators\n */\nexport const boolean = createTypeValidatorTest<boolean, BooleanConfig>(\n { parser: parseBoolean },\n applyBooleanConfig,\n);\n","/** Badly formatted date for internal use. */\nexport const invalidDate = new Date('');\n\n/** @internal */\nconst isoDatePattern =\n /^(\\d{4})(?:-([0-2]\\d)(?:-([0-3]\\d)(?:[ T]([0-2]\\d):([0-5]\\d)(?::([0-5]\\d)(\\.\\d+)?(Z|[+-][0-2]\\d:?[0-5]\\d)?)?)?)?)?$/;\n\n/** @internal */\nconst timezonePattern = /^([+-])([0-2]\\d):?([0-5]\\d)$/;\n\n/**\n * Parses a timezone string.\n * @param timezone Timezone to parse\n * @internal\n */\nfunction parseTimezone(timezone: string): number {\n const parts = timezonePattern.exec(timezone);\n\n if (timezone === 'Z' || !parts) {\n return 0;\n }\n\n const [, sign, hour = '0', minute = '0'] = parts;\n const multiplier = sign === '-' ? -1 : 1;\n const hoursInMinutes = Number.parseInt(hour, 10) * 60;\n const offset = hoursInMinutes + Number.parseInt(minute, 10);\n\n return multiplier * offset;\n}\n\nconst BASE = 10;\n\nconst dateParts = [\n // Skip\n () => 0,\n // Year\n (part = '0') => Number.parseInt(part, BASE),\n // Month\n (part = '1') => Number.parseInt(part, BASE) - 1,\n // Day\n (part = '1') => Number.parseInt(part, BASE),\n // Hour\n (part = '0') => Number.parseInt(part, BASE),\n // Minute\n (part = '0') => Number.parseInt(part, BASE),\n // Second\n (part = '0') => Number.parseInt(part, BASE),\n // Millisecond\n (part = '0') => Number.parseFloat(part) * 1e3,\n];\n\n/**\n * Parses a value into a date.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseDate(value: unknown): Date | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === 'number') {\n return new Date(value);\n }\n\n return typeof value === 'string' ? parseIsoDate(value) : invalidDate;\n}\n\n/**\n * Parses an ISO 8601 string into a date. Without a timezone, the date is local.\n * @param value String to parse\n * @internal\n */\nfunction parseIsoDate(value: string): Date {\n const parts = isoDatePattern.exec(value);\n\n if (parts === null) {\n return invalidDate;\n }\n\n const [\n ,\n year = 0,\n month = 0,\n day = 0,\n hour = 0,\n minute = 0,\n second = 0,\n millisecond = 0,\n ] = dateParts.map((parse, index) => parse(parts[index]));\n\n const timezone = parts[8];\n\n if (!timezone) {\n return new Date(year, month, day, hour, minute, second, millisecond);\n }\n\n return new Date(\n Date.UTC(\n year,\n month,\n day,\n hour,\n minute + parseTimezone(timezone),\n second,\n millisecond,\n ),\n );\n}\n","import { createTypeValidatorTest, createValidatorTest } from './factories.js';\nimport type {\n ConfigBase,\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\nimport { parseDate } from './parse-date.js';\n\n/**\n * Applies a configuration to the date value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyDateConfig(\n value: unknown,\n config: DateConfig,\n): Date | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue.getTime()))\n ) {\n parsedValue = config.default;\n }\n\n return parsedValue;\n}\n\nexport type SharedDateValueType = Date | string | number;\n\nexport interface MinDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n min: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or after a date.\n * @param limit Minimum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function minDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MinDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date, null> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value > parsedDate : value >= parsedDate))),\n message,\n () => ({\n min: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\nexport interface MaxDateValidatorMessageParameters extends ValidatorMessageParameters<Date> {\n max: Date | null | undefined;\n limit: Date | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a date value is on or before a date.\n * @param limit Maximum date\n * @param message Error message\n * @param exclusive Makes comparison exclusive instead of inclusive\n * @category Validation Tests\n */\nexport function maxDate(\n limit: SharedDateValueType,\n message: ValidatorMessage<Date, MaxDateValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<Date> {\n const parsedDate = parseDate(limit);\n return createValidatorTest(\n (value) =>\n parsedDate !== null &&\n parsedDate !== undefined &&\n (value === null ||\n value === undefined ||\n (value instanceof Date &&\n (exclusive ? value < parsedDate : value <= parsedDate))),\n message,\n () => ({\n max: parsedDate,\n limit: parsedDate,\n exclusive,\n }),\n );\n}\n\n/**\n * Configuration for date validation.\n * @category Types\n */\nexport type DateConfig = ConfigBase<Date>;\n\n/**\n * Validates a date value.\n * @category Type Validators\n */\nexport const date = createTypeValidatorTest<Date, DateConfig>(\n { parser: parseDate },\n applyDateConfig,\n);\n","import { createTypeValidatorTest } from './factories.js';\nimport {\n type ConfigBase,\n invalid,\n valid,\n type ValidatorMessage,\n type ValidatorTest,\n} from './shared.js';\n\n/**\n * Parses a value into a number.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseNumber(value: unknown): number | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.getTime();\n }\n\n if (typeof value === 'string') {\n return Number.parseFloat(value);\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- coerces all other input on purpose; #484 decides non-primitives\n return Number.parseFloat(String(value));\n}\n\n/**\n * Applies a configuration to the number value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyNumberConfig(\n value: unknown,\n config: NumberConfig,\n): number | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined ||\n parsedValue === null ||\n Number.isNaN(parsedValue))\n ) {\n parsedValue = config.default;\n }\n\n if (config.round && typeof parsedValue === 'number') {\n switch (config.round) {\n case 'nearest': {\n parsedValue = Math.round(parsedValue);\n break;\n }\n case 'ceil': {\n parsedValue = Math.ceil(parsedValue);\n break;\n }\n case 'floor': {\n parsedValue = Math.floor(parsedValue);\n break;\n }\n default: {\n throw new Error(`Unknown round type: ${String(config.round)}`);\n }\n }\n }\n\n return parsedValue;\n}\n\n/**\n * Ensures a number value is an integer.\n * @param message Error message\n * @category Validation Tests\n */\nexport function integer(\n message: ValidatorMessage<number>,\n): ValidatorTest<number> {\n return async (value, field) => {\n if (\n value === undefined ||\n value === null ||\n (typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.floor(value) === value)\n ) {\n return valid({ value, field });\n }\n\n return invalid({\n message,\n value,\n field,\n });\n };\n}\n\n/**\n * Configuration for number validation.\n * @category Types\n */\nexport interface NumberConfig extends ConfigBase<number> {\n /** Apply rounding mechanism before validation. */\n round?: 'nearest' | 'floor' | 'ceil';\n}\n\n/**\n * Validates a number value.\n * @category Type Validators\n */\nexport const number = createTypeValidatorTest<number, NumberConfig>(\n {\n parser: parseNumber,\n },\n applyNumberConfig,\n);\n","import {\n type ExtractError,\n type ExtractValue,\n hasOwnProperty,\n invalid,\n valid,\n type ValidatorTest,\n} from './shared.js';\n\nexport type ObjectParameter = Record<string, ValidatorTest<unknown, unknown>>;\n\n/**\n * Validates an object.\n * @category Type Validators\n */\nexport function object<\n P extends ObjectParameter,\n V extends { [K in keyof P]?: ExtractValue<P[K]> },\n E extends { [K in keyof P]?: ExtractError<P[K]> },\n>(properties: P): ValidatorTest<V, E> {\n if (typeof properties !== 'object' || properties === null) {\n throw new TypeError('`properties` must be a configuration object');\n }\n\n return async (values, field) => {\n const definedValues = (values ?? {}) as V;\n const errors = {} as E;\n const resolvedValues = {} as V;\n let isValid = true;\n\n for (const key in properties) {\n if (hasOwnProperty(properties, key)) {\n const validator = properties[key];\n const value = definedValues[key];\n const result =\n typeof validator === 'function'\n ? await validator(value, key)\n : await invalid({ field: key, message: 'No validator set', value });\n\n resolvedValues[key] = result.value as V[Extract<keyof P, string>];\n\n if (result.state === 'invalid') {\n isValid = false;\n errors[key] = (result.message || result.errors) as E[Extract<\n keyof P,\n string\n >];\n }\n }\n }\n\n if (isValid) {\n return valid({ value: resolvedValues, field });\n }\n\n return invalid({\n message: '',\n value: values,\n field,\n errors,\n });\n };\n}\n","import { createValidatorTest } from './factories.js';\nimport type {\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\n\n/**\n * Ensures a value is not undefined, null, empty string, NaN, nor invalid date.\n * @param message Error message\n * @param nullable Allow null values\n * @category Validation Tests\n */\nexport function required<T, P extends ValidatorMessageParameters<T>>(\n message: ValidatorMessage<T, P>,\n nullable?: boolean,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n (nullable && value === null) ||\n (value !== null &&\n value !== undefined &&\n !(typeof value === 'string' && value === '') &&\n !(typeof value === 'number' && Number.isNaN(value)) &&\n !(value instanceof Date && Number.isNaN(value.valueOf()))),\n message,\n );\n}\n\nexport interface OneOfValidatorMessageParameters<\n T,\n> extends ValidatorMessageParameters<T> {\n values: readonly T[];\n}\n\n/**\n * Ensures a value is one in a predefined list.\n * @param values List of allowed values.\n * @param message Error message\n * @category Validation Tests\n */\nexport function oneOf<T extends string | number | boolean | Date>(\n values: readonly T[],\n message: ValidatorMessage<T, OneOfValidatorMessageParameters<T>>,\n): ValidatorTest<T> {\n return createValidatorTest(\n (value) =>\n value === undefined ||\n value === null ||\n values.includes(value as T) ||\n (value instanceof Date &&\n values.some((x) => x.valueOf() === value.valueOf())),\n message,\n () => ({ values }),\n );\n}\n","import { createValidatorTest } from './factories.js';\nimport type {\n ValidatorMessage,\n ValidatorMessageParameters,\n ValidatorTest,\n} from './shared.js';\n\nexport type SharedValueType = string | number | unknown[];\n\n/**\n * Extracts a numeric amount from value, i.e. string length, array length, or number.\n * @internal\n */\nfunction getAmount(value: SharedValueType | null | undefined) {\n return typeof value === 'string' || Array.isArray(value)\n ? value.length\n : value;\n}\n\nexport interface MaxValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n max: number;\n amount: number | null | undefined;\n limit: number;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function max(\n limit: number,\n message: ValidatorMessage<SharedValueType, MaxValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount < limit : amount <= limit)\n );\n },\n message,\n (value) => ({\n max: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface MinValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n min: number;\n limit: number;\n amount: number | null | undefined;\n exclusive?: boolean | undefined;\n}\n\n/**\n * Ensures a string, number, or array value is at most a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @param exclusive Use exclusive comparison instead of inclusive\n * @category Validation Tests\n */\nexport function min(\n limit: number,\n message: ValidatorMessage<SharedValueType, MinValidatorMessageParameters>,\n exclusive?: boolean,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n (exclusive ? amount > limit : amount >= limit)\n );\n },\n message,\n (value) => ({\n min: limit,\n limit,\n amount: getAmount(value),\n exclusive,\n }),\n );\n}\n\nexport interface ExactValidatorMessageParameters extends ValidatorMessageParameters<SharedValueType> {\n limit: number;\n amount: number | null | undefined;\n exact: number;\n}\n\n/**\n * Ensures a string, number, or array value is exactly a certain amount.\n * @param limit Size or value limit\n * @param message Error message\n * @category Validation Tests\n */\nexport function exact(\n limit: number,\n message: ValidatorMessage<SharedValueType, ExactValidatorMessageParameters>,\n): ValidatorTest<SharedValueType> {\n return createValidatorTest(\n (value) => {\n const amount = getAmount(value as SharedValueType);\n return (\n amount === undefined ||\n amount === null ||\n value === '' ||\n amount === limit\n );\n },\n message,\n (value) => ({\n amount: getAmount(value),\n limit,\n exact: limit,\n }),\n );\n}\n","import { createTypeValidatorTest, createValidatorTest } from './factories.js';\nimport {\n type ConfigBase,\n isObject,\n type ValidatorMessage,\n type ValidatorMessageParameters,\n type ValidatorTest,\n} from './shared.js';\n\n/** @internal */\nconst emailPattern =\n /^[\\w!#$%&'*+./=?^`{|}~-]+@[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?(?:\\.[\\dA-Za-z](?:[\\dA-Za-z-]{0,61}[\\dA-Za-z])?)*$/;\n\n/**\n * RFC 9562 UUIDs: versions 1 to 8 with the RFC's variant (10xx), plus the nil\n * and max UUIDs.\n * @internal\n */\nconst uuidPattern =\n /^(?:[\\da-f]{8}-[\\da-f]{4}-[1-8][\\da-f]{3}-[89ab][\\da-f]{3}-[\\da-f]{12}|0{8}-0{4}-0{4}-0{4}-0{12}|f{8}-f{4}-f{4}-f{4}-f{12})$/i;\n\n/**\n * Configuration for string validation.\n * @category Types\n */\nexport interface StringConfig extends ConfigBase<string> {\n /** Apply trim to string before validation. */\n trim?: boolean;\n}\n\n/**\n * Parses a value into a string.\n * @param value Value to parse\n * @category Parsers\n */\nexport function parseString(value: unknown): string | null | undefined {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (isObject(value)) {\n throw new TypeError('Failed to parse value to string.');\n }\n\n // oxlint-disable-next-line typescript/no-base-to-string -- only plain objects throw above; #484 decides other non-primitives\n return String(value);\n}\n\n/**\n * Applies a configuration to the string value.\n * @param value Value to modify\n * @param config Configuration to apply\n * @category Helpers\n */\nexport function applyStringConfig(\n value: unknown,\n config: StringConfig,\n): string | null | undefined {\n let parsedValue = config.parser(value);\n if (\n config.default !== undefined &&\n (parsedValue === undefined || parsedValue === null || parsedValue === '')\n ) {\n parsedValue = config.default;\n }\n\n if (config.trim && typeof parsedValue === 'string') {\n parsedValue = parsedValue.trim();\n }\n\n return parsedValue;\n}\n\nexport interface MatchesValidatorMessageParameters extends ValidatorMessageParameters<string> {\n pattern: RegExp;\n}\n\n/**\n * Ensures a string value matches a pattern\n * @param pattern Pattern to match\n * @param message Error message\n * @category Validation Tests\n */\nexport function matches(\n pattern: RegExp,\n message: ValidatorMessage<string, MatchesValidatorMessageParameters>,\n): ValidatorTest<string> {\n // A g or y pattern advances lastIndex on each test(), so a shared one would\n // fail matching values after a match. Test a private copy from index 0.\n const ownPattern = new RegExp(pattern);\n return createValidatorTest(\n (value) => {\n ownPattern.lastIndex = 0;\n return (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && ownPattern.test(value))\n );\n },\n message,\n () => ({ pattern }),\n );\n}\n\n/**\n * Ensures a string value matches an email pattern\n * @param message Error message\n * @category Validation Tests\n */\nexport function email(\n message: ValidatorMessage<string>,\n): ValidatorTest<string> {\n return matches(emailPattern, message);\n}\n\n/**\n * Ensures a string value is an RFC 9562 UUID, any version from 1 to 8, or the\n * nil or max UUID. Case-insensitive, without braces or a `urn:uuid:` prefix.\n * @param message Error message\n * @category Validation Tests\n */\nexport function uuid(message: ValidatorMessage<string>): ValidatorTest<string> {\n return matches(uuidPattern, message);\n}\n\n/**\n * Ensures a string value is a valid URL\n * @param message Error message\n * @param protocols Optional list of protocols to allow. Without it, `javascript:`\n * and `data:` URLs are valid; use `['http:', 'https:']` for values rendered as links.\n * @category Validation Tests\n */\nexport function url(\n message: ValidatorMessage<string>,\n protocols?: string[],\n): ValidatorTest<string> {\n return createValidatorTest(\n (value) => {\n try {\n let url: URL | undefined;\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (typeof value === 'string' && (url = new URL(value)))\n ) {\n return !(url && protocols && !protocols.includes(url.protocol));\n }\n } catch {\n // Do nothing\n }\n\n return false;\n },\n message,\n () => ({ protocols }),\n );\n}\n\n/**\n * Validates a string value.\n * @category Type Validators\n */\nexport const string = createTypeValidatorTest<string, StringConfig>(\n {\n parser: parseString,\n },\n applyStringConfig,\n);\n"],"mappings":"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","names":["isObject","value","hasOwnProperty","object","property","formatPattern","formatMessage","template","parameters","_","key","valid","field","invalid","errors","message","extras","parseArray","value","iterable","applyArrayConfig","config","parsedValue","findArrayInvalidResult","tests","arrayValue","field","validatorTest","result","validateItems","validateItem","isValid","errors","index","item","array","allTests","finalConfig","arrayTests","arrayInvalidResult","items","valid","invalid","createTypeValidatorTest","defaultConfig","applyConfig","config","tests","finalConfig","allTests","value","field","parsedValue","validatorTest","result","valid","error","invalid","createValidatorTest","test","message","getExtras","parseBoolean","value","applyBooleanConfig","config","parsedValue","boolean","createTypeValidatorTest","invalidDate","isoDatePattern","timezonePattern","parseTimezone","timezone","parts","sign","hour","minute","multiplier","offset","BASE","dateParts","part","parseDate","value","parseIsoDate","year","month","day","second","millisecond","parse","index","applyDateConfig","value","config","parsedValue","minDate","limit","message","exclusive","parsedDate","parseDate","createValidatorTest","maxDate","date","createTypeValidatorTest","parseNumber","value","applyNumberConfig","config","parsedValue","integer","message","field","valid","invalid","number","createTypeValidatorTest","object","properties","values","field","definedValues","errors","resolvedValues","isValid","key","hasOwnProperty","validator","value","result","invalid","valid","required","message","nullable","createValidatorTest","value","oneOf","values","x","getAmount","value","max","limit","message","exclusive","createValidatorTest","amount","min","exact","emailPattern","uuidPattern","parseString","value","isObject","applyStringConfig","config","parsedValue","matches","pattern","message","ownPattern","createValidatorTest","email","uuid","url","protocols","string","createTypeValidatorTest"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "validator-fns",
3
- "version": "2.0.4",
3
+ "version": "2.1.0",
4
4
  "description": "Small asynchronous validation library",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "dist",
8
- "runkit.js"
8
+ "runkit.cjs"
9
9
  ],
10
10
  "author": {
11
11
  "name": "Simon Ingeson",
@@ -48,22 +48,29 @@
48
48
  "engines": {
49
49
  "node": ">=18"
50
50
  },
51
+ "devEngines": {
52
+ "runtime": {
53
+ "name": "node",
54
+ "version": "^22.11.0",
55
+ "onFail": "error"
56
+ }
57
+ },
51
58
  "devDependencies": {
52
59
  "@arethetypeswrong/cli": "0.18.5",
53
60
  "@changesets/cli": "3.0.3",
54
- "@types/node": "20.12.12",
61
+ "@types/node": "26.6.5",
55
62
  "@vitest/coverage-v8": "1.6.0",
56
63
  "fta-cli": "3.0.1",
57
- "husky": "9.0.11",
58
- "lint-staged": "15.2.2",
64
+ "husky": "9.1.7",
65
+ "lint-staged": "17.6.0",
59
66
  "npm-run-all": "4.1.5",
60
67
  "oxfmt": "0.70.0",
61
68
  "oxlint": "1.85.0",
62
69
  "oxlint-tsgolint": "7.0.2003",
63
70
  "publint": "0.3.25",
64
71
  "rev-dep": "3.1.0",
65
- "tsup": "8.0.2",
66
- "typescript": "5.4.5",
72
+ "tsup": "8.5.1",
73
+ "typescript": "6.0.3",
67
74
  "vitest": "1.6.0"
68
75
  },
69
76
  "repository": {
@@ -71,7 +78,7 @@
71
78
  "url": "github:smonn/validator-fns"
72
79
  },
73
80
  "homepage": "https://validator-fns.smonn.se/",
74
- "runkitExampleFilename": "runkit.js",
81
+ "runkitExampleFilename": "runkit.cjs",
75
82
  "lint-staged": {
76
83
  "*.ts": "oxlint --fix --deny-warnings",
77
84
  "*.{ts,js,json,jsonc,md,yml,yaml}": "oxfmt --no-error-on-unmatched-pattern"
@@ -79,17 +86,20 @@
79
86
  "scripts": {
80
87
  "build": "tsup",
81
88
  "check": "run-s changeset:status check:code",
82
- "check:code": "run-s format:check lint typecheck deps fta coverage build publint attw smoke",
83
- "changeset:status": "changeset status --since=origin/main",
89
+ "check:code": "run-s ignores format:check lint typecheck deps fta coverage build publint attw smoke bench:smoke",
90
+ "changeset:status": "node scripts/changeset-status.mjs",
84
91
  "format": "oxfmt",
85
92
  "format:check": "oxfmt --check",
93
+ "ignores": "node scripts/check-ignores.mjs",
86
94
  "lint": "oxlint --deny-warnings",
87
95
  "typecheck": "tsc --noEmit",
88
96
  "deps": "rev-dep config run",
89
- "fta": "fta src --score-cap 62",
97
+ "fta": "node scripts/fta-check.mjs",
98
+ "fta:update": "node scripts/fta-check.mjs --update",
90
99
  "publint": "publint --strict",
91
100
  "attw": "attw --pack .",
92
101
  "smoke": "node scripts/smoke-test.mjs",
102
+ "bench:smoke": "pnpm --dir benchmark install --frozen-lockfile && node benchmark/index.mjs --smoke",
93
103
  "test": "vitest",
94
104
  "coverage": "vitest run --coverage"
95
105
  }
@@ -120,4 +120,7 @@ const validate = object({
120
120
  // Handle and display errors
121
121
  console.error(result.errors);
122
122
  }
123
- })();
123
+ })().catch((error) => {
124
+ console.error(error);
125
+ process.exitCode = 1;
126
+ });