@esmj/schema 0.3.3 → 0.3.5

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
@@ -21,9 +21,9 @@ npm install @esmj/schema
21
21
 
22
22
  ### Performance Highlights
23
23
 
24
- - **Schema Creation**: Create schemas in as little as `0.02 ms`, even for complex structures.
25
- - **Parsing**: Parse data with blazing-fast speeds, handling 1,000,000 iterations in under `300 ms`.
26
- - **Error Handling**: Efficiently manage errors with minimal performance impact, processing 1,000,000 iterations in under `400 ms`.
24
+ - **Schema Creation**: Create schemas at up to 4 370 618 ops/s (0.23 μs latency) with @sinclair/typebox, or 736 810 ops/s (1.36 μs latency) with @esmj/schema. Superstruct and @esmj/schema are also among the fastest for schema creation.
25
+ - **Parsing**: Parse data at up to 4 627 714 ops/s (0.22 μs latency) with @zod/mini (note: @zod/mini was observed to consume 200% CPU, while other libraries used only 100% CPU), or 3 142 587 ops/s (0.32 μs latency) with @esmj/schema. ArkType and effect/Schema also show strong parsing throughput.
26
+ - **Error Handling**: Efficiently manage errors at up to 2 428 049 ops/s (0.41 μs latency) with @esmj/schema, or 1 386 616 ops/s (0.72 μs latency) with @zod/mini.
27
27
 
28
28
  These performance metrics make `@esmj/schema` an excellent choice for both frontend and backend applications where speed and efficiency are critical.
29
29
 
@@ -31,54 +31,64 @@ These performance metrics make `@esmj/schema` an excellent choice for both front
31
31
 
32
32
  When choosing a schema validation library, bundle size can be an important factor, especially for frontend applications where minimizing JavaScript size is critical. Here's how `@esmj/schema` compares to other popular libraries:
33
33
 
34
- | Library | Bundle Size (minified + gzipped) |
35
- |------------------|---------------------------------|
36
- | `@esmj/schema` | `~1,1 KB` |
37
- | Superstruct | ~3.2 KB |
38
- | Yup | ~12.2 KB |
39
- | Zod@3 | ~13 KB |
40
- | @zod/mini | ~20,5 KB |
41
- | Joi | ~40,4 KB |
42
- | Zod@4 | ~40,8 KB |
43
- | ArkType | ~41,8 KB |
34
+ | Library | Bundle Size (minified + gzipped) |
35
+ |-------------------|---------------------------------|
36
+ | `@esmj/schema` | `~1,2 KB` |
37
+ | Superstruct | ~3.2 KB |
38
+ | @sinclair/typebox | ~11.7 KB |
39
+ | Yup | ~12.2 KB |
40
+ | Zod@3 | ~13 KB |
41
+ | @zod/mini | ~20,5 KB |
42
+ | Joi | ~40,4 KB |
43
+ | Zod@4 | ~40,8 KB |
44
+ | ArkType | ~41,8 KB |
45
+ | Effect/Schema | ~115.5 KB |
44
46
 
45
47
  ### Performance Comparison
46
48
 
49
+ *All benchmarks were measured on Node.js v24.1.0.*
50
+
47
51
  #### Schema Creation Performance
48
52
 
49
- | Library | 1 Schema | 1,000 Schema | 1,000,000 Schema |
50
- |-----------------|-------------|------------------|----------------------|
51
- | `@esmj/schema` | `0.02 ms` | 4.93 ms | `1.13 s` |
52
- | zod@3 | 0.08 ms | 9.68 ms | 8.53 s |
53
- | @zod/mini | 0.22 ms | 39.77 ms | 34.51 s |
54
- | Yup | 0.54 ms | 14.03 ms | 12.34 s |
55
- | Superstruct | 0.13 ms | `3.67 ms` | 1.74 s |
56
- | Joi | 0.62 ms | 31.60 ms | 23.06 s |
57
- | ArkType | 0.37 ms | 54.60 ms | Infinity |
53
+ | Library | Throughput average (ops/s) | Latency average (μs) |
54
+ |-------------------|-------------------------------:|-------------------------:|
55
+ | @esmj/schema | 736 810.12 ± 3.03% | 1.36 ± 3.24% |
56
+ | Zod@3 | 112 575.50 ± 0.86% | 8.88 ± 0.87% |
57
+ | @zod/mini | 23 456.07 ± 1.26% | 42.64 ± 1.28% |
58
+ | Yup | 75 051.06 ± 4.38% | 13.36 ± 4.41% |
59
+ | Superstruct | 509 401.06 ± 0.80% | 1.96 ± 0.80% |
60
+ | Joi | 42 455.28 ± 1.27% | 23.56 ± 1.30% |
61
+ | `@sinclair/typebox` | `4 370 618.49 ± 1.23%` | `0.23 ± 1.23%` |
62
+ | ArkType | 16 282.69 ± 4.14% | 61.61 ± 4.38% |
63
+ | effect/Schema | 24 919.15 ± 4.31% | 40.31 ± 4.78% |
58
64
 
59
65
  #### Parsing Performance
60
66
 
61
- | Library | 1 Iteration | 1,000 Iterations | 1,000,000 Iterations |
62
- |-----------------|-------------|------------------|----------------------|
63
- | `@esmj/schema` | `0.05 ms` | 0.46 ms | 267.93 ms |
64
- | zod@3 | 0.14 ms | 1.44 ms | 897.89 ms |
65
- | @zod/mini | 0.23 ms | `0.42 ms` | `199.08 ms` |
66
- | Yup | 0.30 ms | 9.49 ms | 8.69 s |
67
- | Superstruct | 0.08 ms | 4.18 ms | 3.71 s |
68
- | Joi | 0.33 ms | 3.35 ms | 2.69 s |
69
- | ArkType | 0.08 ms | 0.70 ms | 576,80 ms |
67
+ | Library | Throughput average (ops/s) | Latency average (μs) |
68
+ |-------------------|-------------------------------:|-------------------------:|
69
+ | @esmj/schema | 3 142 587.31 ± 0.97% | 0.32 ± 0.99% |
70
+ | zod@3 | 1 018 777.24 ± 0.64% | 0.98 ± 0.65% |
71
+ | `@zod/mini` | `4 627 714.90 ± 2.23%` | `0.22 ± 2.36%` |
72
+ | Yup | 108 361.49 ± 0.50% | 9.23 ± 0.51% |
73
+ | Superstruct | 252 904.42 ± 2.20% | 3.96 ± 2.44% |
74
+ | Joi | 346 094.49 ± 0.65% | 2.89 ± 0.65% |
75
+ | @sinclair/typebox | 228 711.62 ± 2.03% | 4.38 ± 2.23% |
76
+ | ArkType | 1 677 066.00 ± 0.58% | 0.60 ± 0.59% |
77
+ | effect/Schema | 1 060 056.14 ± 0.61% | 0.94 ± 0.61% |
70
78
 
71
79
  #### Error Handling Performance
72
80
 
73
- | Library | 1 Iteration | 1,000 Iterations | 1,000,000 Iterations |
74
- |-----------------|-------------|------------------|----------------------|
75
- | `@esmj/schema` | `0.03 ms` | `0.59 ms` | `365.32 ms` |
76
- | zod3 | 0.05 ms | 2.09 ms | 1.26 s |
77
- | @zod/mini | 0.07 ms | 0.99 ms | 545.12 ms |
78
- | Yup | 0.27 ms | 19.28 ms | 18.87 s |
79
- | Superstruct | 0.04 ms | 8.62 ms | 6.24 s |
80
- | Joi | 0.15 ms | 4.13 ms | 2.57 s |
81
- | ArkType | 0.07 ms | 3.78 ms | 2.87 s |
81
+ | Library | Throughput average (ops/s) | Latency average (μs) |
82
+ |-------------------|-------------------------------:|-------------------------:|
83
+ | `@esmj/schema` | `2 428 049.34 ± 0.54%` | `0.41 ± 0.53%` |
84
+ | zod@3 | 641 504.22 ± 3.67% | 1.57 ± 4.38% |
85
+ | @zod/mini | 1 386 616.61 ± 0.60% | 0.72 ± 0.60% |
86
+ | Yup | 98 904.30 ± 0.61% | 10.11 ± 0.61% |
87
+ | Superstruct | 122 782.09 ± 1.03% | 8.15 ± 1.03% |
88
+ | Joi | 271 301.11 ± 1.58% | 3.69 ± 1.59% |
89
+ | @sinclair/typebox | 228 734.49 ± 0.55% | 4.37 ± 0.56% |
90
+ | ArkType | 258 685.33 ± 1.23% | 3.87 ± 1.23% |
91
+ | effect/Schema | 165 753.69 ± 0.99% | 6.03 ± 1.00% |
82
92
 
83
93
  **Note:** During the performance tests, `@zod/mini` was observed to consume 200% CPU, while other libraries used only 100% CPU. This may affect the interpretation of the results, especially in multi-threaded environments.
84
94
 
@@ -134,8 +144,14 @@ console.log(result);
134
144
 
135
145
  Creates a string schema. You can optionally pass `options` to customize error messages.
136
146
 
147
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
148
+
137
149
  ```typescript
138
150
  const stringSchema = s.string({
151
+ message: 'This is a constant error message.',
152
+ });
153
+
154
+ const stringSchemaFunc = s.string({
139
155
  message: (value) => `Custom error: "${value}" is not a valid string.`,
140
156
  });
141
157
  ```
@@ -144,8 +160,14 @@ const stringSchema = s.string({
144
160
 
145
161
  Creates a number schema. You can optionally pass `options` to customize error messages.
146
162
 
163
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
164
+
147
165
  ```typescript
148
166
  const numberSchema = s.number({
167
+ message: 'This is a constant error message.',
168
+ });
169
+
170
+ const numberSchemaFunc = s.number({
149
171
  message: (value) => `Custom error: "${value}" is not a valid number.`,
150
172
  });
151
173
  ```
@@ -154,8 +176,14 @@ const numberSchema = s.number({
154
176
 
155
177
  Creates a boolean schema. You can optionally pass `options` to customize error messages.
156
178
 
179
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
180
+
157
181
  ```typescript
158
182
  const booleanSchema = s.boolean({
183
+ message: 'This is a constant error message.',
184
+ });
185
+
186
+ const booleanSchemaFunc = s.boolean({
159
187
  message: (value) => `Custom error: "${value}" is not a valid boolean.`,
160
188
  });
161
189
  ```
@@ -164,8 +192,14 @@ const booleanSchema = s.boolean({
164
192
 
165
193
  Creates a date schema. You can optionally pass `options` to customize error messages.
166
194
 
195
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
196
+
167
197
  ```typescript
168
198
  const dateSchema = s.date({
199
+ message: 'This is a constant error message.',
200
+ });
201
+
202
+ const dateSchemaFunc = s.date({
169
203
  message: (value) => `Custom error: "${value}" is not a valid date.`,
170
204
  });
171
205
  ```
@@ -174,8 +208,20 @@ const dateSchema = s.date({
174
208
 
175
209
  Creates an object schema with the given definition. You can optionally pass `options` to customize error messages.
176
210
 
211
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
212
+
177
213
  ```typescript
178
214
  const objectSchema = s.object(
215
+ {
216
+ key: s.string(),
217
+ value: s.number(),
218
+ },
219
+ {
220
+ message: 'This is a constant error message.',
221
+ },
222
+ );
223
+
224
+ const objectSchemaFunc = s.object(
179
225
  {
180
226
  key: s.string(),
181
227
  value: s.number(),
@@ -190,8 +236,14 @@ const objectSchema = s.object(
190
236
 
191
237
  Creates an array schema with the given item definition. You can optionally pass `options` to customize error messages.
192
238
 
239
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
240
+
193
241
  ```typescript
194
242
  const arraySchema = s.array(s.string(), {
243
+ message: 'This is a constant error message.',
244
+ });
245
+
246
+ const arraySchemaFunc = s.array(s.string(), {
195
247
  message: (value) => `Custom error: "${JSON.stringify(value)}" is not a valid array.`,
196
248
  });
197
249
  ```
@@ -200,10 +252,14 @@ const arraySchema = s.array(s.string(), {
200
252
 
201
253
  Creates an enum schema that validates against a predefined set of string values. You can optionally pass `options` to customize error messages.
202
254
 
203
- - **`values`**: An array of strings representing the allowed values for the enum. Each value must be a string.
255
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
204
256
 
205
257
  ```typescript
206
258
  const enumSchema = s.enum(['admin', 'user', 'guest'], {
259
+ message: 'This is a constant error message.',
260
+ });
261
+
262
+ const enumSchemaFunc = s.enum(['admin', 'user', 'guest'], {
207
263
  message: (value) => `Custom error: "${value}" is not a valid enum value.`,
208
264
  });
209
265
  ```
@@ -212,43 +268,24 @@ const enumSchema = s.enum(['admin', 'user', 'guest'], {
212
268
 
213
269
  Creates a schema that validates against multiple schemas (a union of schemas). The value must match at least one of the provided schemas. You can optionally pass `options` to customize error messages.
214
270
 
215
- - **`definitions`**: An array of schemas to validate against.
271
+ - **`message`**: Can be either a constant string or a function `(value) => string`.
216
272
 
217
273
  ```typescript
218
274
  const schema = s.union([
219
275
  s.string(),
220
276
  s.number(),
221
277
  s.boolean(),
222
- ]);
223
-
224
- const validString = schema.parse('hello');
225
- console.log(validString);
226
- // 'hello'
227
-
228
- const validNumber = schema.parse(42);
229
- console.log(validNumber);
230
- // 42
231
-
232
- const validBoolean = schema.parse(true);
233
- console.log(validBoolean);
234
- // true
235
-
236
- const invalidValue = schema.safeParse({ key: 'value' });
237
- console.log(invalidValue.success);
238
- // false
239
- console.log(invalidValue.error.message);
240
- // Validation failed. Expected the value to match one of the schemas: "string" | "number" | "boolean", but received "object" with value "{"key":"value"}".
241
- ```
242
-
243
- **Use Case**: The `union` method is useful when you need to validate data that can be of multiple types, such as a value that can be a string, number, or boolean.
278
+ ], {
279
+ message: 'This is a constant error message.',
280
+ });
244
281
 
245
- ```typescript
246
- const schema = s.union(
247
- [s.string(), s.number(), s.boolean()],
248
- {
249
- message: (value) => `Custom error: "${value}" does not match any of the union schemas.`,
250
- },
251
- );
282
+ const schemaFunc = s.union([
283
+ s.string(),
284
+ s.number(),
285
+ s.boolean(),
286
+ ], {
287
+ message: (value) => `Custom error: "${value}" does not match any of the union schemas.`,
288
+ });
252
289
  ```
253
290
 
254
291
  #### `s.any()`
package/dist/index.d.mts CHANGED
@@ -24,9 +24,7 @@ interface SchemaInterface<Input, Output> {
24
24
  nullish(): SchemaInterface<Input, Output | undefined | null>;
25
25
  default(defaultValue: Partial<Input> | (() => Partial<Input>) | Partial<Output>): SchemaInterface<Input, Output>;
26
26
  pipe<NewOutput>(schema: SchemaInterface<Output, NewOutput>): SchemaInterface<Output, NewOutput>;
27
- refine(validation: (value: Output) => boolean, { message }: {
28
- message: ErrorMessage;
29
- }): SchemaInterface<Input, Output>;
27
+ refine(validation: (value: Output) => boolean, options?: SchemaInterfaceOptions): SchemaInterface<Input, Output>;
30
28
  }
31
29
  interface UnionSchemaInterface<T extends Array<SchemaInterface<unknown, unknown>>> extends SchemaInterface<ReturnType<T[number]['parse']>, ReturnType<T[number]['parse']>> {
32
30
  }
@@ -56,7 +54,7 @@ type ExtenderType = (inter: SchemaType, validation: Function, options?: {
56
54
  }) => SchemaType;
57
55
  interface CreateSchemaInterfaceOptions {
58
56
  type?: string;
59
- message?: (value: unknown) => string;
57
+ message?: ErrorMessage;
60
58
  }
61
59
  type SchemaInterfaceOptions = Omit<CreateSchemaInterfaceOptions, 'type'>;
62
60
  declare const s: {
package/dist/index.d.ts CHANGED
@@ -24,9 +24,7 @@ interface SchemaInterface<Input, Output> {
24
24
  nullish(): SchemaInterface<Input, Output | undefined | null>;
25
25
  default(defaultValue: Partial<Input> | (() => Partial<Input>) | Partial<Output>): SchemaInterface<Input, Output>;
26
26
  pipe<NewOutput>(schema: SchemaInterface<Output, NewOutput>): SchemaInterface<Output, NewOutput>;
27
- refine(validation: (value: Output) => boolean, { message }: {
28
- message: ErrorMessage;
29
- }): SchemaInterface<Input, Output>;
27
+ refine(validation: (value: Output) => boolean, options?: SchemaInterfaceOptions): SchemaInterface<Input, Output>;
30
28
  }
31
29
  interface UnionSchemaInterface<T extends Array<SchemaInterface<unknown, unknown>>> extends SchemaInterface<ReturnType<T[number]['parse']>, ReturnType<T[number]['parse']>> {
32
30
  }
@@ -56,7 +54,7 @@ type ExtenderType = (inter: SchemaType, validation: Function, options?: {
56
54
  }) => SchemaType;
57
55
  interface CreateSchemaInterfaceOptions {
58
56
  type?: string;
59
- message?: (value: unknown) => string;
57
+ message?: ErrorMessage;
60
58
  }
61
59
  type SchemaInterfaceOptions = Omit<CreateSchemaInterfaceOptions, 'type'>;
62
60
  declare const s: {
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var h=e=>typeof e=="string"||e instanceof String,I=e=>typeof e=="number"||e instanceof Number,l=e=>e===true||e===false,y=e=>e instanceof Date&&!Number.isNaN(e.getTime()),S=e=>Array.isArray(e),d=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),g={object(e,c){let s=p(d,{...c,type:"object"});return i(s,"_parse",(u,...o)=>{let t=u(...o);if(t.success===false)return t;let n={};for(let r in e){let a=e[r]._parse(t.data[r]);if(a.success)n[r]=a.data;else {a=a;let f=a?.error?.cause?.key?`${r}.${a?.error?.cause?.key}`:r;return a.error.message=`Error parsing key "${f}": ${a.error.message}`,a.error.cause={key:f},a}}return {success:true,data:n}}),s},string(e){return p(h,{...e,type:"string"})},number(e){return p(I,{...e,type:"number"})},boolean(e){return p(l,{...e,type:"boolean"})},date(e){return p(y,{...e,type:"date"})},enum(e,c){let s=n=>e.includes(n),u=n=>`Invalid ${o} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${n}".`,o="enum";return p(s,{message:u,...c,type:o})},array(e,c){let s=p(S,{...c,type:"array"});return i(s,"_parse",(u,...o)=>{let t=u(...o);if(t.success===false)return t;let n=[];for(let r=0;r<t.data.length;r++){let a=e._parse(t.data[r]);if(a.success)n.push(a.data);else {a=a;let f=a.error?.cause?.key?`${r}.${a.error.cause.key}`:`${r}`;return a.error.message=`Error parsing index "${r}": ${a.error.message}`,a.error.cause={key:f},a}}return {success:true,data:n}}),s},any(){return p(()=>true)},preprocess(e,c){return i(c,"_parse",(s,u)=>(u=e(u),s(u))),c},union(e,c){return p(t=>{for(let n=0;n<e.length;n++)if(e[n]._parse(t).success)return true;return false},{message:t=>`Invalid union value. Expected the value to match one of the schemas: ${e.map(n=>`"${n._getType()}"`).join(" | ")}, but received "${typeof t}" with value "${t}".`,...c,type:"union"})}};function T(e){return c=>`The value "${c}" must be type of ${e} but is type of "${typeof c}".`}function i(e,c,s){let u=e[c];e[c]=(...o)=>s(u,...o);}function p(e,{type:c="any",message:s}={}){s=s||T(c);let u={message:s,type:c},o={_getType(){return c},_parse(t){return e(t)?{success:true,data:t}:{success:false,error:{message:s(t)}}},parse(t){let n=o._parse(t);if(!n.success)throw n=n,new Error(n.error.message,{cause:n.error.cause});return n.data},safeParse(t){return o._parse(t)},transform(t){return i(this,"_parse",(n,r)=>{let a=n(r);return a.success&&(a.data=t(a.data)),a}),this},optional(){return i(this,"_parse",(t,n)=>{let r=t(n);return r.success||(r.data=void 0,r.success=true),r}),this},nullable(){return i(this,"_parse",(t,n)=>{let r=t(n);return r.success||(r.data=null,r.success=true),r}),this},nullish(){return i(this,"_parse",(t,n)=>{let r=t(n);return !r.success&&n==null&&(r.success=true,r.data=n),r}),this},default(t){return i(this,"_parse",(n,r)=>(r===void 0&&(r=t,r=typeof t=="function"?t():t),n(r))),this},pipe(t){return i(this,"_parse",(n,r)=>{let a=n(r);return a.success?t._parse(a.data):a}),this},refine(t,{message:n}){return i(this,"_parse",(r,a)=>{let f=r(a);return t(f.data)?f:{success:false,error:{message:n}}}),this}};return m.length>0?m.reduce((t,n)=>n(t,e,u)??t,o):o}var m=[];function b(e){m.push(e);}exports.extend=b;exports.s=g;
1
+ 'use strict';var h=e=>typeof e=="string"||e instanceof String,I=e=>typeof e=="number"||e instanceof Number,y=e=>e===true||e===false,l=e=>e instanceof Date&&!Number.isNaN(e.getTime()),S=e=>Array.isArray(e),d=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),b={object(e,c){let s=f(d,{...c,type:"object"});return i(s,"_parse",(u,...o)=>{let n=u(...o);if(n.success===false)return n;let t={};for(let r in e){let a=e[r]._parse(n.data[r]);if(a.success)t[r]=a.data;else {a=a;let p=a?.error?.cause?.key?`${r}.${a?.error?.cause?.key}`:r;return a.error.message=`Error parsing key "${p}": ${a.error.message}`,a.error.cause={key:p},a}}return {success:true,data:t}}),s},string(e){return f(h,{...e,type:"string"})},number(e){return f(I,{...e,type:"number"})},boolean(e){return f(y,{...e,type:"boolean"})},date(e){return f(l,{...e,type:"date"})},enum(e,c){let s=t=>e.includes(t),u=t=>`Invalid ${o} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${t}".`,o="enum";return f(s,{message:u,...c,type:o})},array(e,c){let s=f(S,{...c,type:"array"});return i(s,"_parse",(u,...o)=>{let n=u(...o);if(n.success===false)return n;let t=[];for(let r=0;r<n.data.length;r++){let a=e._parse(n.data[r]);if(a.success)t.push(a.data);else {a=a;let p=a.error?.cause?.key?`${r}.${a.error.cause.key}`:`${r}`;return a.error.message=`Error parsing index "${r}": ${a.error.message}`,a.error.cause={key:p},a}}return {success:true,data:t}}),s},any(){return f(()=>true)},preprocess(e,c){return i(c,"_parse",(s,u)=>(u=e(u),s(u))),c},union(e,c){return f(n=>{for(let t=0;t<e.length;t++)if(e[t]._parse(n).success)return true;return false},{message:n=>`Invalid union value. Expected the value to match one of the schemas: ${e.map(t=>`"${t._getType()}"`).join(" | ")}, but received "${typeof n}" with value "${n}".`,...c,type:"union"})}};function T(e){return c=>`The value "${c}" must be type of ${e} but is type of "${typeof c}".`}function i(e,c,s){let u=e[c];e[c]=(...o)=>s(u,...o);}function f(e,{type:c="any",message:s}={}){s=s||T(c);let u={message:s,type:c},o={_getType(){return c},_parse(n){return e(n)?{success:true,data:n}:{success:false,error:{message:typeof s=="function"?s(n):s}}},parse(n){let t=o._parse(n);if(!t.success)throw t=t,new Error(t.error.message,{cause:t.error.cause});return t.data},safeParse(n){return o._parse(n)},transform(n){return i(this,"_parse",(t,r)=>{let a=t(r);return a.success&&(a.data=n(a.data)),a}),this},optional(){return i(this,"_parse",(n,t)=>{let r=n(t);return r.success||(r.data=void 0,r.success=true),r}),this},nullable(){return i(this,"_parse",(n,t)=>{let r=n(t);return r.success||(r.data=null,r.success=true),r}),this},nullish(){return i(this,"_parse",(n,t)=>{let r=n(t);return !r.success&&t==null&&(r.success=true,r.data=t),r}),this},default(n){return i(this,"_parse",(t,r)=>(r===void 0&&(r=n,r=typeof n=="function"?n():n),t(r))),this},pipe(n){return i(this,"_parse",(t,r)=>{let a=t(r);return a.success?n._parse(a.data):a}),this},refine(n,{message:t}={}){return i(this,"_parse",(r,a)=>{let p=r(a);return p.success?n(p.data)?p:{success:false,error:{message:typeof t=="function"?t(a):t}}:p}),this}};return m.length>0?m.reduce((n,t)=>t(n,e,u)??n,o):o}var m=[];function g(e){m.push(e);}exports.extend=g;exports.s=b;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var h=e=>typeof e=="string"||e instanceof String,I=e=>typeof e=="number"||e instanceof Number,l=e=>e===true||e===false,y=e=>e instanceof Date&&!Number.isNaN(e.getTime()),S=e=>Array.isArray(e),d=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),g={object(e,c){let s=p(d,{...c,type:"object"});return i(s,"_parse",(u,...o)=>{let t=u(...o);if(t.success===false)return t;let n={};for(let r in e){let a=e[r]._parse(t.data[r]);if(a.success)n[r]=a.data;else {a=a;let f=a?.error?.cause?.key?`${r}.${a?.error?.cause?.key}`:r;return a.error.message=`Error parsing key "${f}": ${a.error.message}`,a.error.cause={key:f},a}}return {success:true,data:n}}),s},string(e){return p(h,{...e,type:"string"})},number(e){return p(I,{...e,type:"number"})},boolean(e){return p(l,{...e,type:"boolean"})},date(e){return p(y,{...e,type:"date"})},enum(e,c){let s=n=>e.includes(n),u=n=>`Invalid ${o} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${n}".`,o="enum";return p(s,{message:u,...c,type:o})},array(e,c){let s=p(S,{...c,type:"array"});return i(s,"_parse",(u,...o)=>{let t=u(...o);if(t.success===false)return t;let n=[];for(let r=0;r<t.data.length;r++){let a=e._parse(t.data[r]);if(a.success)n.push(a.data);else {a=a;let f=a.error?.cause?.key?`${r}.${a.error.cause.key}`:`${r}`;return a.error.message=`Error parsing index "${r}": ${a.error.message}`,a.error.cause={key:f},a}}return {success:true,data:n}}),s},any(){return p(()=>true)},preprocess(e,c){return i(c,"_parse",(s,u)=>(u=e(u),s(u))),c},union(e,c){return p(t=>{for(let n=0;n<e.length;n++)if(e[n]._parse(t).success)return true;return false},{message:t=>`Invalid union value. Expected the value to match one of the schemas: ${e.map(n=>`"${n._getType()}"`).join(" | ")}, but received "${typeof t}" with value "${t}".`,...c,type:"union"})}};function T(e){return c=>`The value "${c}" must be type of ${e} but is type of "${typeof c}".`}function i(e,c,s){let u=e[c];e[c]=(...o)=>s(u,...o);}function p(e,{type:c="any",message:s}={}){s=s||T(c);let u={message:s,type:c},o={_getType(){return c},_parse(t){return e(t)?{success:true,data:t}:{success:false,error:{message:s(t)}}},parse(t){let n=o._parse(t);if(!n.success)throw n=n,new Error(n.error.message,{cause:n.error.cause});return n.data},safeParse(t){return o._parse(t)},transform(t){return i(this,"_parse",(n,r)=>{let a=n(r);return a.success&&(a.data=t(a.data)),a}),this},optional(){return i(this,"_parse",(t,n)=>{let r=t(n);return r.success||(r.data=void 0,r.success=true),r}),this},nullable(){return i(this,"_parse",(t,n)=>{let r=t(n);return r.success||(r.data=null,r.success=true),r}),this},nullish(){return i(this,"_parse",(t,n)=>{let r=t(n);return !r.success&&n==null&&(r.success=true,r.data=n),r}),this},default(t){return i(this,"_parse",(n,r)=>(r===void 0&&(r=t,r=typeof t=="function"?t():t),n(r))),this},pipe(t){return i(this,"_parse",(n,r)=>{let a=n(r);return a.success?t._parse(a.data):a}),this},refine(t,{message:n}){return i(this,"_parse",(r,a)=>{let f=r(a);return t(f.data)?f:{success:false,error:{message:n}}}),this}};return m.length>0?m.reduce((t,n)=>n(t,e,u)??t,o):o}var m=[];function b(e){m.push(e);}export{b as extend,g as s};
1
+ var h=e=>typeof e=="string"||e instanceof String,I=e=>typeof e=="number"||e instanceof Number,y=e=>e===true||e===false,l=e=>e instanceof Date&&!Number.isNaN(e.getTime()),S=e=>Array.isArray(e),d=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),b={object(e,c){let s=f(d,{...c,type:"object"});return i(s,"_parse",(u,...o)=>{let n=u(...o);if(n.success===false)return n;let t={};for(let r in e){let a=e[r]._parse(n.data[r]);if(a.success)t[r]=a.data;else {a=a;let p=a?.error?.cause?.key?`${r}.${a?.error?.cause?.key}`:r;return a.error.message=`Error parsing key "${p}": ${a.error.message}`,a.error.cause={key:p},a}}return {success:true,data:t}}),s},string(e){return f(h,{...e,type:"string"})},number(e){return f(I,{...e,type:"number"})},boolean(e){return f(y,{...e,type:"boolean"})},date(e){return f(l,{...e,type:"date"})},enum(e,c){let s=t=>e.includes(t),u=t=>`Invalid ${o} value. Expected ${e.map(r=>`"${r}"`).join(" | ")}, received "${t}".`,o="enum";return f(s,{message:u,...c,type:o})},array(e,c){let s=f(S,{...c,type:"array"});return i(s,"_parse",(u,...o)=>{let n=u(...o);if(n.success===false)return n;let t=[];for(let r=0;r<n.data.length;r++){let a=e._parse(n.data[r]);if(a.success)t.push(a.data);else {a=a;let p=a.error?.cause?.key?`${r}.${a.error.cause.key}`:`${r}`;return a.error.message=`Error parsing index "${r}": ${a.error.message}`,a.error.cause={key:p},a}}return {success:true,data:t}}),s},any(){return f(()=>true)},preprocess(e,c){return i(c,"_parse",(s,u)=>(u=e(u),s(u))),c},union(e,c){return f(n=>{for(let t=0;t<e.length;t++)if(e[t]._parse(n).success)return true;return false},{message:n=>`Invalid union value. Expected the value to match one of the schemas: ${e.map(t=>`"${t._getType()}"`).join(" | ")}, but received "${typeof n}" with value "${n}".`,...c,type:"union"})}};function T(e){return c=>`The value "${c}" must be type of ${e} but is type of "${typeof c}".`}function i(e,c,s){let u=e[c];e[c]=(...o)=>s(u,...o);}function f(e,{type:c="any",message:s}={}){s=s||T(c);let u={message:s,type:c},o={_getType(){return c},_parse(n){return e(n)?{success:true,data:n}:{success:false,error:{message:typeof s=="function"?s(n):s}}},parse(n){let t=o._parse(n);if(!t.success)throw t=t,new Error(t.error.message,{cause:t.error.cause});return t.data},safeParse(n){return o._parse(n)},transform(n){return i(this,"_parse",(t,r)=>{let a=t(r);return a.success&&(a.data=n(a.data)),a}),this},optional(){return i(this,"_parse",(n,t)=>{let r=n(t);return r.success||(r.data=void 0,r.success=true),r}),this},nullable(){return i(this,"_parse",(n,t)=>{let r=n(t);return r.success||(r.data=null,r.success=true),r}),this},nullish(){return i(this,"_parse",(n,t)=>{let r=n(t);return !r.success&&t==null&&(r.success=true,r.data=t),r}),this},default(n){return i(this,"_parse",(t,r)=>(r===void 0&&(r=n,r=typeof n=="function"?n():n),t(r))),this},pipe(n){return i(this,"_parse",(t,r)=>{let a=t(r);return a.success?n._parse(a.data):a}),this},refine(n,{message:t}={}){return i(this,"_parse",(r,a)=>{let p=r(a);return p.success?n(p.data)?p:{success:false,error:{message:typeof t=="function"?t(a):t}}:p}),this}};return m.length>0?m.reduce((n,t)=>t(n,e,u)??n,o):o}var m=[];function g(e){m.push(e);}export{g as extend,b as s};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esmj/schema",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Tiny extendable package for schema validation.",
5
5
  "keywords": [
6
6
  "schema",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "lint": "biome check --no-errors-on-unmatched",
24
24
  "lint:fix": "npm run lint -- --fix --unsafe",
25
- "benchmark": "node benchmark/benchmark.ts",
25
+ "benchmark": "node --expose-gc benchmark/benchmark.ts",
26
26
  "dev": "node_modules/.bin/tsup --dts --watch --onSuccess 'node ./dist/index.mjs'",
27
27
  "test": "node --test --experimental-strip-types",
28
28
  "test:watch": "npm run test -- --watch",
@@ -65,6 +65,7 @@
65
65
  "@biomejs/biome": "1.9.4",
66
66
  "@commitlint/cli": "^19.8.1",
67
67
  "@commitlint/config-conventional": "^19.8.1",
68
+ "@sinclair/typebox": "^0.34.38",
68
69
  "@typescript-eslint/eslint-plugin": "^8.33.0",
69
70
  "@typescript-eslint/parser": "^8.33.0",
70
71
  "@zod/mini": "^4.0.0-beta.0",
@@ -72,6 +73,7 @@
72
73
  "commitizen": "^4.3.1",
73
74
  "conventional-changelog-cli": "^5.0.0",
74
75
  "cz-conventional-changelog": "^3.3.0",
76
+ "effect": "^3.17.6",
75
77
  "git-cz": "^4.9.0",
76
78
  "husky": "^9.1.7",
77
79
  "joi": "^17.13.3",