@dzeio/schema 0.6.0 → 0.7.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/dist/Schema.d.mts CHANGED
@@ -67,6 +67,7 @@ declare abstract class SchemaItem<Output = any, Input = Output> implements Stand
67
67
  unwrap?(): SchemaItem;
68
68
  parse(input: unknown, options?: ValidationOptions): ValidationResult<Output>;
69
69
  toJSON(): SchemaJSON;
70
+ private deepSerializeItem;
70
71
  addValidation(fn: ((input: Output) => boolean) | {
71
72
  fn: (input: Output) => boolean;
72
73
  error?: string;
@@ -128,7 +129,7 @@ type ValidationResultOld<T> = {
128
129
  */
129
130
  interface SchemaJSON {
130
131
  /** Id of the schema item (name of the constructor) */
131
- i: string
132
+ _i: string
132
133
  /** Attributes */
133
134
  a?: Array<string> | undefined
134
135
  /** Children schema items */
@@ -159,6 +160,8 @@ type ModelInfer$1<M extends Model> = {
159
160
  [key in keyof M]: SchemaInfer<M[key]>
160
161
  }
161
162
 
163
+ type Literal = string | number | bigint | boolean | null | undefined
164
+
162
165
  declare class SchemaAny extends SchemaItem {
163
166
  isOfType(_input: unknown): _input is any;
164
167
  }
@@ -187,6 +190,7 @@ declare class SchemaArray<Child extends SchemaItem, Output = SchemaInfer<Child>,
187
190
  * transform the array so it only contains one of each elements
188
191
  */
189
192
  unique(): this;
193
+ clean(): this;
190
194
  /**
191
195
  * split a string into an array
192
196
  * @param [separator] default:`,` the separator to use
@@ -221,16 +225,18 @@ declare class SchemaEnum<E extends EnumLike> extends SchemaItem<E[keyof E]> {
221
225
  isOfType(input: unknown): input is E[keyof E];
222
226
  }
223
227
 
224
- declare class SchemaLiteral<Type> extends SchemaItem<Type> {
225
- private readonly value;
226
- constructor(value: Type);
227
- isOfType(input: unknown): input is Type;
228
+ declare class SchemaLiteral<Types extends Array<Literal>> extends SchemaItem<Types[number]> {
229
+ private readonly values;
230
+ constructor(...values: Types);
231
+ isOfType(input: unknown): input is Types[number];
228
232
  }
229
233
 
230
234
  declare class SchemaNullable<Child extends SchemaItem, Output = SchemaInfer<Child>, Input = SchemaInputInfer<Child>> extends SchemaItem<Output | undefined, Input | null | undefined> {
231
235
  private readonly child;
232
236
  constructor(child: Child);
233
237
  falsyAsNull(): this;
238
+ emptyAsNull(): this;
239
+ emptyFileAsNull(): this;
234
240
  unwrap(): Child;
235
241
  isOfType(input: unknown): input is Output | undefined;
236
242
  protected getSubInputs(input: unknown): Array<{
@@ -323,6 +329,11 @@ declare class SchemaString extends SchemaItem<string> {
323
329
  * @param message the message to display on an error
324
330
  */
325
331
  regex(regex: RegExp, message?: string): this;
332
+ /**
333
+ * force the input text to be an email
334
+ * @param message the message to display on an error
335
+ */
336
+ email(message?: string): this;
326
337
  minLength(value: number, message?: string): this;
327
338
  maxLength(value: number, message?: string): this;
328
339
  isOfType(input: unknown): input is string;
@@ -415,30 +426,10 @@ declare function parseForm<T extends SchemaItem>(model: T, form: HTMLFormElement
415
426
  */
416
427
  declare function parsable(): (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>;
417
428
  type SchemaItemStatic = new (...args: Array<any>) => SchemaItem;
418
- declare const Types: {
419
- readonly Any: typeof SchemaAny;
420
- readonly Array: typeof SchemaArray;
421
- readonly Tuple: typeof SchemaTuple;
422
- readonly Boolean: typeof SchemaBoolean;
423
- readonly Date: typeof SchemaDate;
424
- readonly Enum: typeof SchemaEnum;
425
- readonly Literal: typeof SchemaLiteral;
426
- readonly Nullable: typeof SchemaNullable;
427
- readonly Object: typeof SchemaObject;
428
- readonly Record: typeof SchemaRecord;
429
- readonly String: typeof SchemaString;
430
- readonly Union: typeof SchemaUnion;
431
- readonly Intersection: typeof SchemaIntersection;
432
- readonly Default: typeof SchemaDefault;
433
- readonly Undefined: typeof SchemaUndefined;
434
- readonly Void: typeof SchemaVoid;
435
- readonly Null: typeof SchemaNull;
436
- readonly Nullish: typeof SchemaNullish;
437
- };
438
429
  declare class Schema<T extends Record<string, SchemaItem> = Record<string, SchemaItem>> extends SchemaObject<T> {
439
430
  private static readonly registeredModules;
440
431
  static register(module: SchemaItemStatic): void;
441
- static getModule(name: string): SchemaItemStatic | undefined;
432
+ static getModule(name: string): SchemaItemStatic;
442
433
  static any(): SchemaAny;
443
434
  static array<Type extends SchemaItem>(...inputs: ConstructorParameters<typeof SchemaArray<Type>>): SchemaArray<Type>;
444
435
  static boolean(...inputs: ConstructorParameters<typeof SchemaBoolean>): SchemaBoolean;
@@ -449,7 +440,7 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
449
440
  * @param input the literal value (note: append `as const` else the typing won't work correctly)
450
441
  * @returns
451
442
  */
452
- static literal<Type>(input: Type): SchemaLiteral<Type>;
443
+ static literal<Type extends Array<Literal>>(...inputs: ConstructorParameters<typeof SchemaLiteral<Type>>): SchemaLiteral<Type>;
453
444
  static nullable<Type extends SchemaItem>(...inputs: ConstructorParameters<typeof SchemaNullable<Type>>): SchemaNullable<Type>;
454
445
  static number(...inputs: ConstructorParameters<typeof SchemaNumber>): SchemaNumber;
455
446
  static object<Type extends Record<string, SchemaItem>>(...inputs: ConstructorParameters<typeof SchemaObject<Type>>): SchemaObject<Type>;
@@ -468,6 +459,7 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
468
459
  static void(...inputs: ConstructorParameters<typeof SchemaVoid>): SchemaVoid;
469
460
  static never(...inputs: ConstructorParameters<typeof SchemaNever>): SchemaNever;
470
461
  static fromJSON(json: SchemaJSON): SchemaItem;
462
+ static deepParseSchemaJSON(item: unknown): unknown;
471
463
  static isSchemaJSON(data: unknown): data is SchemaJSON;
472
464
  /**
473
465
  * @deprecated use helper `parseQuery`
@@ -488,4 +480,4 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
488
480
  }
489
481
  declare const s: typeof Schema;
490
482
 
491
- export { type Infer, type InputInfer, type Model, type ModelInfer$1 as ModelInfer, SchemaAny, SchemaArray, SchemaBoolean, SchemaDate, SchemaDefault, SchemaEnum, SchemaFile, type SchemaInfer, type SchemaInputInfer, SchemaIntersection, SchemaItem, type SchemaItemJSON, type SchemaJSON, SchemaLiteral, SchemaNever, SchemaNull, SchemaNullable, SchemaNullish, SchemaNumber, SchemaObject, SchemaRecord, SchemaString, SchemaUndefined, SchemaUnion, SchemaVoid, Types, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationResultOld, Schema as default, isNull, parsable, parseForm, parseFormData, parseQuery, s };
483
+ export { type Infer, type InputInfer, type Literal, type Model, type ModelInfer$1 as ModelInfer, SchemaAny, SchemaArray, SchemaBoolean, SchemaDate, SchemaDefault, SchemaEnum, SchemaFile, type SchemaInfer, type SchemaInputInfer, SchemaIntersection, SchemaItem, type SchemaItemJSON, type SchemaJSON, SchemaLiteral, SchemaNever, SchemaNull, SchemaNullable, SchemaNullish, SchemaNumber, SchemaObject, SchemaRecord, SchemaString, SchemaUndefined, SchemaUnion, SchemaVoid, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationResultOld, Schema as default, isNull, parsable, parseForm, parseFormData, parseQuery, s };
package/dist/Schema.d.ts CHANGED
@@ -67,6 +67,7 @@ declare abstract class SchemaItem<Output = any, Input = Output> implements Stand
67
67
  unwrap?(): SchemaItem;
68
68
  parse(input: unknown, options?: ValidationOptions): ValidationResult<Output>;
69
69
  toJSON(): SchemaJSON;
70
+ private deepSerializeItem;
70
71
  addValidation(fn: ((input: Output) => boolean) | {
71
72
  fn: (input: Output) => boolean;
72
73
  error?: string;
@@ -128,7 +129,7 @@ type ValidationResultOld<T> = {
128
129
  */
129
130
  interface SchemaJSON {
130
131
  /** Id of the schema item (name of the constructor) */
131
- i: string
132
+ _i: string
132
133
  /** Attributes */
133
134
  a?: Array<string> | undefined
134
135
  /** Children schema items */
@@ -159,6 +160,8 @@ type ModelInfer$1<M extends Model> = {
159
160
  [key in keyof M]: SchemaInfer<M[key]>
160
161
  }
161
162
 
163
+ type Literal = string | number | bigint | boolean | null | undefined
164
+
162
165
  declare class SchemaAny extends SchemaItem {
163
166
  isOfType(_input: unknown): _input is any;
164
167
  }
@@ -187,6 +190,7 @@ declare class SchemaArray<Child extends SchemaItem, Output = SchemaInfer<Child>,
187
190
  * transform the array so it only contains one of each elements
188
191
  */
189
192
  unique(): this;
193
+ clean(): this;
190
194
  /**
191
195
  * split a string into an array
192
196
  * @param [separator] default:`,` the separator to use
@@ -221,16 +225,18 @@ declare class SchemaEnum<E extends EnumLike> extends SchemaItem<E[keyof E]> {
221
225
  isOfType(input: unknown): input is E[keyof E];
222
226
  }
223
227
 
224
- declare class SchemaLiteral<Type> extends SchemaItem<Type> {
225
- private readonly value;
226
- constructor(value: Type);
227
- isOfType(input: unknown): input is Type;
228
+ declare class SchemaLiteral<Types extends Array<Literal>> extends SchemaItem<Types[number]> {
229
+ private readonly values;
230
+ constructor(...values: Types);
231
+ isOfType(input: unknown): input is Types[number];
228
232
  }
229
233
 
230
234
  declare class SchemaNullable<Child extends SchemaItem, Output = SchemaInfer<Child>, Input = SchemaInputInfer<Child>> extends SchemaItem<Output | undefined, Input | null | undefined> {
231
235
  private readonly child;
232
236
  constructor(child: Child);
233
237
  falsyAsNull(): this;
238
+ emptyAsNull(): this;
239
+ emptyFileAsNull(): this;
234
240
  unwrap(): Child;
235
241
  isOfType(input: unknown): input is Output | undefined;
236
242
  protected getSubInputs(input: unknown): Array<{
@@ -323,6 +329,11 @@ declare class SchemaString extends SchemaItem<string> {
323
329
  * @param message the message to display on an error
324
330
  */
325
331
  regex(regex: RegExp, message?: string): this;
332
+ /**
333
+ * force the input text to be an email
334
+ * @param message the message to display on an error
335
+ */
336
+ email(message?: string): this;
326
337
  minLength(value: number, message?: string): this;
327
338
  maxLength(value: number, message?: string): this;
328
339
  isOfType(input: unknown): input is string;
@@ -415,30 +426,10 @@ declare function parseForm<T extends SchemaItem>(model: T, form: HTMLFormElement
415
426
  */
416
427
  declare function parsable(): (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>;
417
428
  type SchemaItemStatic = new (...args: Array<any>) => SchemaItem;
418
- declare const Types: {
419
- readonly Any: typeof SchemaAny;
420
- readonly Array: typeof SchemaArray;
421
- readonly Tuple: typeof SchemaTuple;
422
- readonly Boolean: typeof SchemaBoolean;
423
- readonly Date: typeof SchemaDate;
424
- readonly Enum: typeof SchemaEnum;
425
- readonly Literal: typeof SchemaLiteral;
426
- readonly Nullable: typeof SchemaNullable;
427
- readonly Object: typeof SchemaObject;
428
- readonly Record: typeof SchemaRecord;
429
- readonly String: typeof SchemaString;
430
- readonly Union: typeof SchemaUnion;
431
- readonly Intersection: typeof SchemaIntersection;
432
- readonly Default: typeof SchemaDefault;
433
- readonly Undefined: typeof SchemaUndefined;
434
- readonly Void: typeof SchemaVoid;
435
- readonly Null: typeof SchemaNull;
436
- readonly Nullish: typeof SchemaNullish;
437
- };
438
429
  declare class Schema<T extends Record<string, SchemaItem> = Record<string, SchemaItem>> extends SchemaObject<T> {
439
430
  private static readonly registeredModules;
440
431
  static register(module: SchemaItemStatic): void;
441
- static getModule(name: string): SchemaItemStatic | undefined;
432
+ static getModule(name: string): SchemaItemStatic;
442
433
  static any(): SchemaAny;
443
434
  static array<Type extends SchemaItem>(...inputs: ConstructorParameters<typeof SchemaArray<Type>>): SchemaArray<Type>;
444
435
  static boolean(...inputs: ConstructorParameters<typeof SchemaBoolean>): SchemaBoolean;
@@ -449,7 +440,7 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
449
440
  * @param input the literal value (note: append `as const` else the typing won't work correctly)
450
441
  * @returns
451
442
  */
452
- static literal<Type>(input: Type): SchemaLiteral<Type>;
443
+ static literal<Type extends Array<Literal>>(...inputs: ConstructorParameters<typeof SchemaLiteral<Type>>): SchemaLiteral<Type>;
453
444
  static nullable<Type extends SchemaItem>(...inputs: ConstructorParameters<typeof SchemaNullable<Type>>): SchemaNullable<Type>;
454
445
  static number(...inputs: ConstructorParameters<typeof SchemaNumber>): SchemaNumber;
455
446
  static object<Type extends Record<string, SchemaItem>>(...inputs: ConstructorParameters<typeof SchemaObject<Type>>): SchemaObject<Type>;
@@ -468,6 +459,7 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
468
459
  static void(...inputs: ConstructorParameters<typeof SchemaVoid>): SchemaVoid;
469
460
  static never(...inputs: ConstructorParameters<typeof SchemaNever>): SchemaNever;
470
461
  static fromJSON(json: SchemaJSON): SchemaItem;
462
+ static deepParseSchemaJSON(item: unknown): unknown;
471
463
  static isSchemaJSON(data: unknown): data is SchemaJSON;
472
464
  /**
473
465
  * @deprecated use helper `parseQuery`
@@ -488,4 +480,4 @@ declare class Schema<T extends Record<string, SchemaItem> = Record<string, Schem
488
480
  }
489
481
  declare const s: typeof Schema;
490
482
 
491
- export { type Infer, type InputInfer, type Model, type ModelInfer$1 as ModelInfer, SchemaAny, SchemaArray, SchemaBoolean, SchemaDate, SchemaDefault, SchemaEnum, SchemaFile, type SchemaInfer, type SchemaInputInfer, SchemaIntersection, SchemaItem, type SchemaItemJSON, type SchemaJSON, SchemaLiteral, SchemaNever, SchemaNull, SchemaNullable, SchemaNullish, SchemaNumber, SchemaObject, SchemaRecord, SchemaString, SchemaUndefined, SchemaUnion, SchemaVoid, Types, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationResultOld, Schema as default, isNull, parsable, parseForm, parseFormData, parseQuery, s };
483
+ export { type Infer, type InputInfer, type Literal, type Model, type ModelInfer$1 as ModelInfer, SchemaAny, SchemaArray, SchemaBoolean, SchemaDate, SchemaDefault, SchemaEnum, SchemaFile, type SchemaInfer, type SchemaInputInfer, SchemaIntersection, SchemaItem, type SchemaItemJSON, type SchemaJSON, SchemaLiteral, SchemaNever, SchemaNull, SchemaNullable, SchemaNullish, SchemaNumber, SchemaObject, SchemaRecord, SchemaString, SchemaUndefined, SchemaUnion, SchemaVoid, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationResultOld, Schema as default, isNull, parsable, parseForm, parseFormData, parseQuery, s };
package/dist/Schema.js CHANGED
@@ -49,7 +49,6 @@ __export(Schema_exports, {
49
49
  SchemaUndefined: () => SchemaUndefined,
50
50
  SchemaUnion: () => SchemaUnion,
51
51
  SchemaVoid: () => SchemaVoid,
52
- Types: () => Types,
53
52
  default: () => Schema,
54
53
  isNull: () => isNull,
55
54
  parsable: () => parsable,
@@ -180,7 +179,7 @@ var _SchemaItem = class _SchemaItem {
180
179
  if (!this.isOfType(input)) {
181
180
  return {
182
181
  valid: false,
183
- errors: [{ message: "invalid type" }]
182
+ errors: [{ message: this.invalidError }]
184
183
  };
185
184
  }
186
185
  const validationErrors = [];
@@ -212,14 +211,24 @@ var _SchemaItem = class _SchemaItem {
212
211
  toJSON() {
213
212
  var _a;
214
213
  const res = {
215
- i: this.constructor.name,
214
+ _i: this.constructor.name,
216
215
  a: this.attributes.length > 0 ? this.attributes : void 0,
217
- c: (_a = this.items) == null ? void 0 : _a.map((it) => it instanceof _SchemaItem ? it.toJSON() : it),
216
+ c: (_a = this.items) == null ? void 0 : _a.map((it) => this.deepSerializeItem(it)),
218
217
  f: this.savedCalls.map((it) => it.args ? { n: it.name, a: Array.from(it.args) } : { n: it.name })
219
218
  };
220
219
  (0, import_object_util.objectClean)(res, { deep: false });
221
220
  return res;
222
221
  }
222
+ deepSerializeItem(item) {
223
+ if (item instanceof _SchemaItem) {
224
+ return item.toJSON();
225
+ } else if (Array.isArray(item)) {
226
+ return item.map((it) => this.deepSerializeItem(it));
227
+ } else if ((0, import_object_util.isObject)(item)) {
228
+ return (0, import_object_util.objectRemap)(item, (value, key) => ({ value: this.deepSerializeItem(value), key }));
229
+ }
230
+ return item;
231
+ }
223
232
  addValidation(fn, error) {
224
233
  this.validations.push(typeof fn === "function" ? { fn, error } : fn);
225
234
  return this;
@@ -283,6 +292,10 @@ var SchemaArray = class extends SchemaItem {
283
292
  this.postProcess.push((input) => input.filter((it, idx) => input.indexOf(it) === idx));
284
293
  return this;
285
294
  }
295
+ clean() {
296
+ this.postProcess.push((input) => input.filter((it) => !isNull(it)));
297
+ return this;
298
+ }
286
299
  split(separator = ",") {
287
300
  this.addPreProcess((it) => typeof it === "string" ? it.split(separator) : it);
288
301
  return this;
@@ -300,6 +313,9 @@ var SchemaArray = class extends SchemaItem {
300
313
  __decorateClass([
301
314
  parsable()
302
315
  ], SchemaArray.prototype, "unique", 1);
316
+ __decorateClass([
317
+ parsable()
318
+ ], SchemaArray.prototype, "clean", 1);
303
319
  __decorateClass([
304
320
  parsable()
305
321
  ], SchemaArray.prototype, "split", 1);
@@ -339,6 +355,14 @@ var SchemaNullable = class extends SchemaItem {
339
355
  this.addPreProcess((it) => !it ? void 0 : it);
340
356
  return this;
341
357
  }
358
+ emptyAsNull() {
359
+ this.addPreProcess((it) => it === "" ? void 0 : it);
360
+ return this;
361
+ }
362
+ emptyFileAsNull() {
363
+ this.addPreProcess((it) => it instanceof File && it.size === 0 ? void 0 : it);
364
+ return this;
365
+ }
342
366
  unwrap() {
343
367
  return this.child;
344
368
  }
@@ -358,6 +382,12 @@ var SchemaNullable = class extends SchemaItem {
358
382
  __decorateClass([
359
383
  parsable()
360
384
  ], SchemaNullable.prototype, "falsyAsNull", 1);
385
+ __decorateClass([
386
+ parsable()
387
+ ], SchemaNullable.prototype, "emptyAsNull", 1);
388
+ __decorateClass([
389
+ parsable()
390
+ ], SchemaNullable.prototype, "emptyFileAsNull", 1);
361
391
 
362
392
  // src/items/object.ts
363
393
  var import_object_util2 = require("@dzeio/object-util");
@@ -384,7 +414,8 @@ function parseQuery(schema, query, opts) {
384
414
  for (const [key, value] of query) {
385
415
  const keys = key.split(".").map((it) => /^\d+$/g.test(it) ? Number.parseInt(it, 10) : it);
386
416
  const schemaItem = getSchemaItemAtPath(schema, keys);
387
- const finalValue = schemaItem instanceof SchemaArray ? query.getAll(key) : value;
417
+ const allValues = query.getAll(key);
418
+ const finalValue = schemaItem && schemaItem.parse(allValues).valid ? allValues : value;
388
419
  (0, import_object_util3.objectSet)(record, keys, finalValue);
389
420
  }
390
421
  return schema.parse(record, opts);
@@ -394,7 +425,8 @@ function parseFormData(schema, data, opts) {
394
425
  for (const [key, value] of data) {
395
426
  const keys = key.split(".").map((it) => /^\d+$/g.test(it) ? Number.parseInt(it, 10) : it);
396
427
  const schemaItem = getSchemaItemAtPath(schema, keys);
397
- const finalValue = schemaItem instanceof SchemaArray ? data.getAll(key) : value;
428
+ const allValues = data.getAll(key);
429
+ const finalValue = schemaItem && schemaItem.parse(allValues).valid ? allValues : value;
398
430
  (0, import_object_util3.objectSet)(record, keys, finalValue);
399
431
  }
400
432
  const handleBoolean = (value, keys) => {
@@ -560,13 +592,13 @@ var SchemaEnum = class extends SchemaItem {
560
592
 
561
593
  // src/items/literal.ts
562
594
  var SchemaLiteral = class extends SchemaItem {
563
- constructor(value) {
564
- super([value]);
565
- this.value = value;
566
- this.validations.push({ fn: (it) => it === this.value });
595
+ constructor(...values) {
596
+ super(values);
597
+ this.values = values;
598
+ this.validations.push({ fn: (it) => this.values.includes(it) });
567
599
  }
568
600
  isOfType(input) {
569
- return typeof input === typeof this.value;
601
+ return this.values.some((it) => typeof input === typeof it);
570
602
  }
571
603
  };
572
604
 
@@ -681,6 +713,15 @@ var SchemaString = class extends SchemaItem {
681
713
  });
682
714
  return this;
683
715
  }
716
+ email(message) {
717
+ this.addValidation({
718
+ fn(input) {
719
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input);
720
+ },
721
+ error: message
722
+ });
723
+ return this;
724
+ }
684
725
  minLength(value, message) {
685
726
  return this.min(value, message);
686
727
  }
@@ -706,6 +747,9 @@ __decorateClass([
706
747
  __decorateClass([
707
748
  parsable()
708
749
  ], SchemaString.prototype, "regex", 1);
750
+ __decorateClass([
751
+ parsable()
752
+ ], SchemaString.prototype, "email", 1);
709
753
 
710
754
  // src/items/union.ts
711
755
  var SchemaUnion = class extends SchemaItem {
@@ -852,6 +896,7 @@ var SchemaNever = class extends SchemaItem {
852
896
  };
853
897
 
854
898
  // src/Schema.ts
899
+ var import_object_util6 = require("@dzeio/object-util");
855
900
  function parsable() {
856
901
  return (target, propertyKey, descriptor) => {
857
902
  if (!(propertyKey in target)) {
@@ -866,32 +911,16 @@ function parsable() {
866
911
  return descriptor;
867
912
  };
868
913
  }
869
- var Types = {
870
- Any: SchemaAny,
871
- Array: SchemaArray,
872
- Tuple: SchemaTuple,
873
- Boolean: SchemaBoolean,
874
- Date: SchemaDate,
875
- Enum: SchemaEnum,
876
- Literal: SchemaLiteral,
877
- Nullable: SchemaNullable,
878
- Object: SchemaObject,
879
- Record: SchemaRecord,
880
- String: SchemaString,
881
- Union: SchemaUnion,
882
- Intersection: SchemaIntersection,
883
- Default: SchemaDefault,
884
- Undefined: SchemaUndefined,
885
- Void: SchemaVoid,
886
- Null: SchemaNull,
887
- Nullish: SchemaNullish
888
- };
889
914
  var _Schema = class _Schema extends SchemaObject {
890
915
  static register(module2) {
891
916
  this.registeredModules.push(module2);
892
917
  }
893
918
  static getModule(name) {
894
- return this.registeredModules.find((it) => it.name === name);
919
+ const module2 = this.registeredModules.find((it) => it.name === name);
920
+ if (!module2) {
921
+ console.log("Couldn't find module", name);
922
+ }
923
+ return module2 != null ? module2 : SchemaAny;
895
924
  }
896
925
  static any() {
897
926
  return new SchemaAny();
@@ -913,8 +942,8 @@ var _Schema = class _Schema extends SchemaObject {
913
942
  * @param input the literal value (note: append `as const` else the typing won't work correctly)
914
943
  * @returns
915
944
  */
916
- static literal(input) {
917
- return new SchemaLiteral(input);
945
+ static literal(...inputs) {
946
+ return new SchemaLiteral(...inputs);
918
947
  }
919
948
  static nullable(...inputs) {
920
949
  return new SchemaNullable(...inputs);
@@ -963,25 +992,35 @@ var _Schema = class _Schema extends SchemaObject {
963
992
  }
964
993
  static fromJSON(json) {
965
994
  var _a, _b, _c, _d, _e, _f;
966
- const fn = this.getModule(json.i);
995
+ const fn = this.getModule(json._i);
967
996
  if (!fn) {
968
- throw new Error(`Schema cannot parse ${json.i}`);
997
+ throw new Error(`Schema cannot parse ${json._i}`);
969
998
  }
970
- const item = new fn(...(_b = (_a = json.c) == null ? void 0 : _a.map((it) => this.isSchemaJSON(it) ? _Schema.fromJSON(it) : it)) != null ? _b : []);
999
+ const item = new fn(...(_b = (_a = json.c) == null ? void 0 : _a.map((it) => this.deepParseSchemaJSON(it))) != null ? _b : []);
971
1000
  for (const validation of (_c = json.f) != null ? _c : []) {
972
1001
  if (!(validation.n in item)) {
973
1002
  throw new Error("validation not available in Schema Item");
974
1003
  }
975
- item[validation.n](...(_e = (_d = validation.a) == null ? void 0 : _d.map((it) => _Schema.isSchemaJSON(it) ? _Schema.fromJSON(it) : it)) != null ? _e : []);
1004
+ item[validation.n](...(_e = (_d = validation.a) == null ? void 0 : _d.map((it) => this.deepParseSchemaJSON(it))) != null ? _e : []);
976
1005
  }
977
1006
  item.attrs(...(_f = json.a) != null ? _f : []);
978
1007
  return item;
979
1008
  }
1009
+ static deepParseSchemaJSON(item) {
1010
+ if (this.isSchemaJSON(item)) {
1011
+ return _Schema.fromJSON(item);
1012
+ } else if (Array.isArray(item)) {
1013
+ return item.map((it) => this.deepParseSchemaJSON(it));
1014
+ } else if ((0, import_object_util6.isObject)(item)) {
1015
+ return (0, import_object_util6.objectRemap)(item, (value, key) => ({ value: this.deepParseSchemaJSON(value), key }));
1016
+ }
1017
+ return item;
1018
+ }
980
1019
  static isSchemaJSON(data) {
981
1020
  if (typeof data !== "object" || data === null) {
982
1021
  return false;
983
1022
  }
984
- if (!("i" in data)) {
1023
+ if (!("_i" in data)) {
985
1024
  return false;
986
1025
  }
987
1026
  return true;
@@ -1028,7 +1067,10 @@ _Schema.registeredModules = [
1028
1067
  SchemaUndefined,
1029
1068
  SchemaVoid,
1030
1069
  SchemaNull,
1031
- SchemaNullish
1070
+ SchemaNullish,
1071
+ SchemaFile,
1072
+ SchemaAny,
1073
+ SchemaNumber
1032
1074
  ];
1033
1075
  var Schema = _Schema;
1034
1076
  var s = Schema;
@@ -1055,7 +1097,6 @@ var s = Schema;
1055
1097
  SchemaUndefined,
1056
1098
  SchemaUnion,
1057
1099
  SchemaVoid,
1058
- Types,
1059
1100
  isNull,
1060
1101
  parsable,
1061
1102
  parseForm,
package/dist/Schema.mjs CHANGED
@@ -13,7 +13,7 @@ var __decorateClass = (decorators, target, key, kind) => {
13
13
  import { objectClone, objectGet, objectLoop, objectSet as objectSet2 } from "@dzeio/object-util";
14
14
 
15
15
  // src/SchemaItem.ts
16
- import { isObject, objectClean, objectSet } from "@dzeio/object-util";
16
+ import { isObject, objectClean, objectRemap, objectSet } from "@dzeio/object-util";
17
17
  var _SchemaItem = class _SchemaItem {
18
18
  constructor(items) {
19
19
  // standard Schema V1 spec
@@ -129,7 +129,7 @@ var _SchemaItem = class _SchemaItem {
129
129
  if (!this.isOfType(input)) {
130
130
  return {
131
131
  valid: false,
132
- errors: [{ message: "invalid type" }]
132
+ errors: [{ message: this.invalidError }]
133
133
  };
134
134
  }
135
135
  const validationErrors = [];
@@ -161,14 +161,24 @@ var _SchemaItem = class _SchemaItem {
161
161
  toJSON() {
162
162
  var _a;
163
163
  const res = {
164
- i: this.constructor.name,
164
+ _i: this.constructor.name,
165
165
  a: this.attributes.length > 0 ? this.attributes : void 0,
166
- c: (_a = this.items) == null ? void 0 : _a.map((it) => it instanceof _SchemaItem ? it.toJSON() : it),
166
+ c: (_a = this.items) == null ? void 0 : _a.map((it) => this.deepSerializeItem(it)),
167
167
  f: this.savedCalls.map((it) => it.args ? { n: it.name, a: Array.from(it.args) } : { n: it.name })
168
168
  };
169
169
  objectClean(res, { deep: false });
170
170
  return res;
171
171
  }
172
+ deepSerializeItem(item) {
173
+ if (item instanceof _SchemaItem) {
174
+ return item.toJSON();
175
+ } else if (Array.isArray(item)) {
176
+ return item.map((it) => this.deepSerializeItem(it));
177
+ } else if (isObject(item)) {
178
+ return objectRemap(item, (value, key) => ({ value: this.deepSerializeItem(value), key }));
179
+ }
180
+ return item;
181
+ }
172
182
  addValidation(fn, error) {
173
183
  this.validations.push(typeof fn === "function" ? { fn, error } : fn);
174
184
  return this;
@@ -232,6 +242,10 @@ var SchemaArray = class extends SchemaItem {
232
242
  this.postProcess.push((input) => input.filter((it, idx) => input.indexOf(it) === idx));
233
243
  return this;
234
244
  }
245
+ clean() {
246
+ this.postProcess.push((input) => input.filter((it) => !isNull(it)));
247
+ return this;
248
+ }
235
249
  split(separator = ",") {
236
250
  this.addPreProcess((it) => typeof it === "string" ? it.split(separator) : it);
237
251
  return this;
@@ -249,6 +263,9 @@ var SchemaArray = class extends SchemaItem {
249
263
  __decorateClass([
250
264
  parsable()
251
265
  ], SchemaArray.prototype, "unique", 1);
266
+ __decorateClass([
267
+ parsable()
268
+ ], SchemaArray.prototype, "clean", 1);
252
269
  __decorateClass([
253
270
  parsable()
254
271
  ], SchemaArray.prototype, "split", 1);
@@ -288,6 +305,14 @@ var SchemaNullable = class extends SchemaItem {
288
305
  this.addPreProcess((it) => !it ? void 0 : it);
289
306
  return this;
290
307
  }
308
+ emptyAsNull() {
309
+ this.addPreProcess((it) => it === "" ? void 0 : it);
310
+ return this;
311
+ }
312
+ emptyFileAsNull() {
313
+ this.addPreProcess((it) => it instanceof File && it.size === 0 ? void 0 : it);
314
+ return this;
315
+ }
291
316
  unwrap() {
292
317
  return this.child;
293
318
  }
@@ -307,6 +332,12 @@ var SchemaNullable = class extends SchemaItem {
307
332
  __decorateClass([
308
333
  parsable()
309
334
  ], SchemaNullable.prototype, "falsyAsNull", 1);
335
+ __decorateClass([
336
+ parsable()
337
+ ], SchemaNullable.prototype, "emptyAsNull", 1);
338
+ __decorateClass([
339
+ parsable()
340
+ ], SchemaNullable.prototype, "emptyFileAsNull", 1);
310
341
 
311
342
  // src/items/object.ts
312
343
  import { isObject as isObject2, objectFind, objectMap } from "@dzeio/object-util";
@@ -333,7 +364,8 @@ function parseQuery(schema, query, opts) {
333
364
  for (const [key, value] of query) {
334
365
  const keys = key.split(".").map((it) => /^\d+$/g.test(it) ? Number.parseInt(it, 10) : it);
335
366
  const schemaItem = getSchemaItemAtPath(schema, keys);
336
- const finalValue = schemaItem instanceof SchemaArray ? query.getAll(key) : value;
367
+ const allValues = query.getAll(key);
368
+ const finalValue = schemaItem && schemaItem.parse(allValues).valid ? allValues : value;
337
369
  objectSet2(record, keys, finalValue);
338
370
  }
339
371
  return schema.parse(record, opts);
@@ -343,7 +375,8 @@ function parseFormData(schema, data, opts) {
343
375
  for (const [key, value] of data) {
344
376
  const keys = key.split(".").map((it) => /^\d+$/g.test(it) ? Number.parseInt(it, 10) : it);
345
377
  const schemaItem = getSchemaItemAtPath(schema, keys);
346
- const finalValue = schemaItem instanceof SchemaArray ? data.getAll(key) : value;
378
+ const allValues = data.getAll(key);
379
+ const finalValue = schemaItem && schemaItem.parse(allValues).valid ? allValues : value;
347
380
  objectSet2(record, keys, finalValue);
348
381
  }
349
382
  const handleBoolean = (value, keys) => {
@@ -509,13 +542,13 @@ var SchemaEnum = class extends SchemaItem {
509
542
 
510
543
  // src/items/literal.ts
511
544
  var SchemaLiteral = class extends SchemaItem {
512
- constructor(value) {
513
- super([value]);
514
- this.value = value;
515
- this.validations.push({ fn: (it) => it === this.value });
545
+ constructor(...values) {
546
+ super(values);
547
+ this.values = values;
548
+ this.validations.push({ fn: (it) => this.values.includes(it) });
516
549
  }
517
550
  isOfType(input) {
518
- return typeof input === typeof this.value;
551
+ return this.values.some((it) => typeof input === typeof it);
519
552
  }
520
553
  };
521
554
 
@@ -630,6 +663,15 @@ var SchemaString = class extends SchemaItem {
630
663
  });
631
664
  return this;
632
665
  }
666
+ email(message) {
667
+ this.addValidation({
668
+ fn(input) {
669
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input);
670
+ },
671
+ error: message
672
+ });
673
+ return this;
674
+ }
633
675
  minLength(value, message) {
634
676
  return this.min(value, message);
635
677
  }
@@ -655,6 +697,9 @@ __decorateClass([
655
697
  __decorateClass([
656
698
  parsable()
657
699
  ], SchemaString.prototype, "regex", 1);
700
+ __decorateClass([
701
+ parsable()
702
+ ], SchemaString.prototype, "email", 1);
658
703
 
659
704
  // src/items/union.ts
660
705
  var SchemaUnion = class extends SchemaItem {
@@ -801,6 +846,7 @@ var SchemaNever = class extends SchemaItem {
801
846
  };
802
847
 
803
848
  // src/Schema.ts
849
+ import { isObject as isObject5, objectRemap as objectRemap2 } from "@dzeio/object-util";
804
850
  function parsable() {
805
851
  return (target, propertyKey, descriptor) => {
806
852
  if (!(propertyKey in target)) {
@@ -815,32 +861,16 @@ function parsable() {
815
861
  return descriptor;
816
862
  };
817
863
  }
818
- var Types = {
819
- Any: SchemaAny,
820
- Array: SchemaArray,
821
- Tuple: SchemaTuple,
822
- Boolean: SchemaBoolean,
823
- Date: SchemaDate,
824
- Enum: SchemaEnum,
825
- Literal: SchemaLiteral,
826
- Nullable: SchemaNullable,
827
- Object: SchemaObject,
828
- Record: SchemaRecord,
829
- String: SchemaString,
830
- Union: SchemaUnion,
831
- Intersection: SchemaIntersection,
832
- Default: SchemaDefault,
833
- Undefined: SchemaUndefined,
834
- Void: SchemaVoid,
835
- Null: SchemaNull,
836
- Nullish: SchemaNullish
837
- };
838
864
  var _Schema = class _Schema extends SchemaObject {
839
865
  static register(module) {
840
866
  this.registeredModules.push(module);
841
867
  }
842
868
  static getModule(name) {
843
- return this.registeredModules.find((it) => it.name === name);
869
+ const module = this.registeredModules.find((it) => it.name === name);
870
+ if (!module) {
871
+ console.log("Couldn't find module", name);
872
+ }
873
+ return module != null ? module : SchemaAny;
844
874
  }
845
875
  static any() {
846
876
  return new SchemaAny();
@@ -862,8 +892,8 @@ var _Schema = class _Schema extends SchemaObject {
862
892
  * @param input the literal value (note: append `as const` else the typing won't work correctly)
863
893
  * @returns
864
894
  */
865
- static literal(input) {
866
- return new SchemaLiteral(input);
895
+ static literal(...inputs) {
896
+ return new SchemaLiteral(...inputs);
867
897
  }
868
898
  static nullable(...inputs) {
869
899
  return new SchemaNullable(...inputs);
@@ -912,25 +942,35 @@ var _Schema = class _Schema extends SchemaObject {
912
942
  }
913
943
  static fromJSON(json) {
914
944
  var _a, _b, _c, _d, _e, _f;
915
- const fn = this.getModule(json.i);
945
+ const fn = this.getModule(json._i);
916
946
  if (!fn) {
917
- throw new Error(`Schema cannot parse ${json.i}`);
947
+ throw new Error(`Schema cannot parse ${json._i}`);
918
948
  }
919
- const item = new fn(...(_b = (_a = json.c) == null ? void 0 : _a.map((it) => this.isSchemaJSON(it) ? _Schema.fromJSON(it) : it)) != null ? _b : []);
949
+ const item = new fn(...(_b = (_a = json.c) == null ? void 0 : _a.map((it) => this.deepParseSchemaJSON(it))) != null ? _b : []);
920
950
  for (const validation of (_c = json.f) != null ? _c : []) {
921
951
  if (!(validation.n in item)) {
922
952
  throw new Error("validation not available in Schema Item");
923
953
  }
924
- item[validation.n](...(_e = (_d = validation.a) == null ? void 0 : _d.map((it) => _Schema.isSchemaJSON(it) ? _Schema.fromJSON(it) : it)) != null ? _e : []);
954
+ item[validation.n](...(_e = (_d = validation.a) == null ? void 0 : _d.map((it) => this.deepParseSchemaJSON(it))) != null ? _e : []);
925
955
  }
926
956
  item.attrs(...(_f = json.a) != null ? _f : []);
927
957
  return item;
928
958
  }
959
+ static deepParseSchemaJSON(item) {
960
+ if (this.isSchemaJSON(item)) {
961
+ return _Schema.fromJSON(item);
962
+ } else if (Array.isArray(item)) {
963
+ return item.map((it) => this.deepParseSchemaJSON(it));
964
+ } else if (isObject5(item)) {
965
+ return objectRemap2(item, (value, key) => ({ value: this.deepParseSchemaJSON(value), key }));
966
+ }
967
+ return item;
968
+ }
929
969
  static isSchemaJSON(data) {
930
970
  if (typeof data !== "object" || data === null) {
931
971
  return false;
932
972
  }
933
- if (!("i" in data)) {
973
+ if (!("_i" in data)) {
934
974
  return false;
935
975
  }
936
976
  return true;
@@ -977,7 +1017,10 @@ _Schema.registeredModules = [
977
1017
  SchemaUndefined,
978
1018
  SchemaVoid,
979
1019
  SchemaNull,
980
- SchemaNullish
1020
+ SchemaNullish,
1021
+ SchemaFile,
1022
+ SchemaAny,
1023
+ SchemaNumber
981
1024
  ];
982
1025
  var Schema = _Schema;
983
1026
  var s = Schema;
@@ -1003,7 +1046,6 @@ export {
1003
1046
  SchemaUndefined,
1004
1047
  SchemaUnion,
1005
1048
  SchemaVoid,
1006
- Types,
1007
1049
  Schema as default,
1008
1050
  isNull,
1009
1051
  parsable,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzeio/schema",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "dependencies": {
5
5
  "@dzeio/object-util": "^1.9.2"
6
6
  },