decoders 2.9.0-pre.1 → 2.9.0-pre.2
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/index.cjs +47 -16
- package/dist/index.d.cts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +46 -15
- package/package.json +4 -5
package/dist/index.cjs
CHANGED
|
@@ -478,6 +478,28 @@ function tuple(...decoders) {
|
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
// src/lib/size-options.ts
|
|
482
|
+
function bySizeOptions(options) {
|
|
483
|
+
const size = options.size;
|
|
484
|
+
const min2 = _nullishCoalesce(size, () => ( options.min));
|
|
485
|
+
const max2 = _nullishCoalesce(size, () => ( options.max));
|
|
486
|
+
const atLeast = min2 === max2 ? "" : "at least ";
|
|
487
|
+
const atMost = min2 === max2 ? "" : "at most ";
|
|
488
|
+
return (value) => {
|
|
489
|
+
const len = _nullishCoalesce(value.length, () => ( value.size));
|
|
490
|
+
if (typeof value === "string") {
|
|
491
|
+
if (min2 !== void 0 && len < min2)
|
|
492
|
+
return `Too short, must be ${atLeast}${min2} chars`;
|
|
493
|
+
if (max2 !== void 0 && len > max2)
|
|
494
|
+
return `Too long, must be ${atMost}${max2} chars`;
|
|
495
|
+
} else {
|
|
496
|
+
if (min2 !== void 0 && len < min2) return `Must have ${atLeast}${min2} items`;
|
|
497
|
+
if (max2 !== void 0 && len > max2) return `Must have ${atMost}${max2} items`;
|
|
498
|
+
}
|
|
499
|
+
return null;
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
481
503
|
// src/misc.ts
|
|
482
504
|
function instanceOf(klass) {
|
|
483
505
|
return define(
|
|
@@ -490,6 +512,9 @@ function instanceOf(klass) {
|
|
|
490
512
|
function lazy(decoderFn) {
|
|
491
513
|
return define((blob) => decoderFn().decode(blob));
|
|
492
514
|
}
|
|
515
|
+
function sized(decoder, options) {
|
|
516
|
+
return decoder.reject(bySizeOptions(options));
|
|
517
|
+
}
|
|
493
518
|
function prep(mapperFn, decoder) {
|
|
494
519
|
return define((originalInput, _, err2) => {
|
|
495
520
|
let blob;
|
|
@@ -748,18 +773,6 @@ function mapping(decoder) {
|
|
|
748
773
|
return record(decoder).transform((obj) => new Map(Object.entries(obj)));
|
|
749
774
|
}
|
|
750
775
|
|
|
751
|
-
// src/lib/size-options.ts
|
|
752
|
-
function bySizeOptions(options) {
|
|
753
|
-
const size = options.size;
|
|
754
|
-
const min = _nullishCoalesce(size, () => ( options.min));
|
|
755
|
-
const max = _nullishCoalesce(size, () => ( options.max));
|
|
756
|
-
const atLeast = min === max ? "" : "at least ";
|
|
757
|
-
const atMost = min === max ? "" : "at most ";
|
|
758
|
-
const tooShort = min !== void 0 && `Too short, must be ${atLeast}${min} chars`;
|
|
759
|
-
const tooLong = max !== void 0 && `Too long, must be ${atMost}${max} chars`;
|
|
760
|
-
return tooShort && tooLong ? (s) => s.length < min ? tooShort : s.length > max ? tooLong : null : tooShort ? (s) => s.length < min ? tooShort : null : tooLong ? (s) => s.length > max ? tooLong : null : () => null;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
776
|
// src/strings.ts
|
|
764
777
|
var url_re = /^([A-Za-z]{2,12}(?:[+][A-Za-z]{2,12})?):\/\/(?:([^@:]*:?(?:[^@]+)?)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,/\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
765
778
|
var string = define(
|
|
@@ -786,6 +799,10 @@ var email = regex(
|
|
|
786
799
|
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
787
800
|
"Must be email"
|
|
788
801
|
);
|
|
802
|
+
var urlString = string.refine(
|
|
803
|
+
(s) => URL.canParse(s),
|
|
804
|
+
"Must be URL"
|
|
805
|
+
);
|
|
789
806
|
var url = either(
|
|
790
807
|
regex(url_re, "Must be URL").transform((value) => new URL(value)),
|
|
791
808
|
instanceOf(URL)
|
|
@@ -799,9 +816,7 @@ var identifier = regex(
|
|
|
799
816
|
"Must be valid identifier"
|
|
800
817
|
);
|
|
801
818
|
function nanoid(options) {
|
|
802
|
-
return regex(/^[a-z0-9_-]+$/i, "Must be nano ID")
|
|
803
|
-
bySizeOptions(_nullishCoalesce(options, () => ( { size: 21 })))
|
|
804
|
-
);
|
|
819
|
+
return sized(regex(/^[a-z0-9_-]+$/i, "Must be nano ID"), _nullishCoalesce(options, () => ( { size: 21 })));
|
|
805
820
|
}
|
|
806
821
|
var uuid = regex(
|
|
807
822
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
@@ -857,6 +872,17 @@ var positiveInteger = integer.refine(
|
|
|
857
872
|
(n) => n >= 0 && !Object.is(n, -0),
|
|
858
873
|
"Number must be positive"
|
|
859
874
|
);
|
|
875
|
+
function min(min2, decoder = number) {
|
|
876
|
+
return decoder.reject((value) => value < min2 ? `Must be at least ${min2}` : null);
|
|
877
|
+
}
|
|
878
|
+
function max(max2, decoder = number) {
|
|
879
|
+
return decoder.reject((value) => value > max2 ? `Must be at most ${max2}` : null);
|
|
880
|
+
}
|
|
881
|
+
function between(min2, max2, decoder = number) {
|
|
882
|
+
return decoder.reject(
|
|
883
|
+
(value) => value < min2 ? `Must be at least ${min2}` : value > max2 ? `Must be at most ${max2}` : null
|
|
884
|
+
);
|
|
885
|
+
}
|
|
860
886
|
var bigint = define(
|
|
861
887
|
(blob, ok2, err2) => isBigInt(blob) ? ok2(blob) : err2("Must be bigint")
|
|
862
888
|
);
|
|
@@ -944,5 +970,10 @@ var json = either(
|
|
|
944
970
|
|
|
945
971
|
|
|
946
972
|
|
|
947
|
-
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
exports._annotate = public_annotate; exports.always = always; exports.anyNumber = anyNumber; exports.anything = anything; exports.array = array; exports.between = between; exports.bigint = bigint; exports.boolean = boolean; exports.constant = constant; exports.date = date; exports.dateString = dateString; exports.datelike = datelike; exports.decimal = decimal; exports.define = define; exports.either = either; exports.email = email; exports.endsWith = endsWith; exports.enum_ = enum_; exports.err = err; exports.exact = exact; exports.fail = fail; exports.formatInline = formatInline; exports.formatShort = formatShort; exports.hexadecimal = hexadecimal; exports.httpsUrl = httpsUrl; exports.identifier = identifier; exports.inexact = inexact; exports.instanceOf = instanceOf; exports.integer = integer; exports.isDate = isDate; exports.isDecoder = isDecoder; exports.isPlainObject = isPlainObject; exports.isPromiseLike = isPromiseLike; exports.iso8601 = iso8601; exports.json = json; exports.jsonArray = jsonArray; exports.jsonObject = jsonObject; exports.lazy = lazy; exports.mapping = mapping; exports.max = max; exports.min = min; exports.nanoid = nanoid; exports.never = never; exports.nonEmptyArray = nonEmptyArray; exports.nonEmptyString = nonEmptyString; exports.null_ = null_; exports.nullable = nullable; exports.nullish = nullish; exports.number = number; exports.numeric = numeric; exports.object = object; exports.ok = ok; exports.oneOf = oneOf; exports.optional = optional; exports.poja = poja; exports.pojo = pojo; exports.positiveInteger = positiveInteger; exports.positiveNumber = positiveNumber; exports.prep = prep; exports.record = record; exports.regex = regex; exports.select = select; exports.setFromArray = setFromArray; exports.sized = sized; exports.startsWith = startsWith; exports.string = string; exports.taggedUnion = taggedUnion; exports.truthy = truthy; exports.tuple = tuple; exports.undefined_ = undefined_; exports.unknown = unknown; exports.url = url; exports.urlString = urlString; exports.uuid = uuid; exports.uuidv1 = uuidv1; exports.uuidv4 = uuidv4;
|
|
948
979
|
// istanbul ignore else -- @preserve
|
package/dist/index.d.cts
CHANGED
|
@@ -398,11 +398,41 @@ declare const jsonArray: Decoder<JSONArray>;
|
|
|
398
398
|
*/
|
|
399
399
|
declare const json: Decoder<JSONValue>;
|
|
400
400
|
|
|
401
|
+
/**
|
|
402
|
+
* Forces TypeScript to "evaluate" named helper types, making API signatures
|
|
403
|
+
* clearer in IDEs.
|
|
404
|
+
*
|
|
405
|
+
* @see https://effectivetypescript.com/2022/02/25/gentips-4-display/
|
|
406
|
+
*/
|
|
407
|
+
type Resolve$1<T> = T extends (...args: unknown[]) => unknown ? T : {
|
|
408
|
+
[K in keyof T]: T[K];
|
|
409
|
+
};
|
|
410
|
+
/**
|
|
411
|
+
* Relaxes a discriminated union type definition, by explicitly adding
|
|
412
|
+
* properties defined in any other member as optional `never`.
|
|
413
|
+
*
|
|
414
|
+
* This makes accessing the members much more relaxed in TypeScript.
|
|
415
|
+
*/
|
|
416
|
+
type Relax<T> = DistributiveRelax<T, T extends any ? keyof T : never>;
|
|
417
|
+
type DistributiveRelax<T, Ks extends string | number | symbol> = T extends any ? Resolve$1<{
|
|
418
|
+
[K in keyof T]: T[K];
|
|
419
|
+
} & {
|
|
420
|
+
[K in Exclude<Ks, keyof T>]?: never;
|
|
421
|
+
}> : never;
|
|
422
|
+
|
|
401
423
|
type SizeOptions = {
|
|
402
424
|
min?: number;
|
|
403
425
|
max?: number;
|
|
404
426
|
size?: number;
|
|
405
427
|
};
|
|
428
|
+
/**
|
|
429
|
+
* Anything with a .length or .size property, like strings, arrays, or sets.
|
|
430
|
+
*/
|
|
431
|
+
type Sized = Relax<{
|
|
432
|
+
length: number;
|
|
433
|
+
} | {
|
|
434
|
+
size: number;
|
|
435
|
+
}>;
|
|
406
436
|
|
|
407
437
|
interface Klass<T> extends Function {
|
|
408
438
|
new (...args: readonly any[]): T;
|
|
@@ -417,6 +447,10 @@ declare function instanceOf<K extends Klass<any>>(klass: K): Decoder<Instance<K>
|
|
|
417
447
|
* types for recursive data structures.
|
|
418
448
|
*/
|
|
419
449
|
declare function lazy<T>(decoderFn: () => Decoder<T>): Decoder<T>;
|
|
450
|
+
/**
|
|
451
|
+
* Only accept strings, arrays, or sets with given length constraints.
|
|
452
|
+
*/
|
|
453
|
+
declare function sized<T extends Sized>(decoder: Decoder<T>, options: SizeOptions): Decoder<T>;
|
|
420
454
|
/**
|
|
421
455
|
* Pre-process the data input before passing it into the decoder. This gives
|
|
422
456
|
* you the ability to arbitrarily customize the input on the fly before passing
|
|
@@ -450,6 +484,24 @@ declare const positiveNumber: Decoder<number>;
|
|
|
450
484
|
* Accepts only non-negative (zero or positive) finite whole numbers.
|
|
451
485
|
*/
|
|
452
486
|
declare const positiveInteger: Decoder<number>;
|
|
487
|
+
/**
|
|
488
|
+
* Accepts numbers greater than or equal to the given minimum.
|
|
489
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
490
|
+
* different decoder to further restrict accepted values, e.g. ``min(0, integer)``.
|
|
491
|
+
*/
|
|
492
|
+
declare function min(min: number, decoder?: Decoder<number>): Decoder<number>;
|
|
493
|
+
/**
|
|
494
|
+
* Accepts numbers less than or equal to the given maximum.
|
|
495
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
496
|
+
* different decoder to further restrict accepted values, e.g. ``max(100, integer)``.
|
|
497
|
+
*/
|
|
498
|
+
declare function max(max: number, decoder?: Decoder<number>): Decoder<number>;
|
|
499
|
+
/**
|
|
500
|
+
* Accepts numbers within the given range (bounds are inclusive).
|
|
501
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
502
|
+
* different decoder to further restrict accepted values, e.g. ``between(1, 10, integer)``.
|
|
503
|
+
*/
|
|
504
|
+
declare function between(min: number, max: number, decoder?: Decoder<number>): Decoder<number>;
|
|
453
505
|
/**
|
|
454
506
|
* Accepts any valid ``bigint`` value.
|
|
455
507
|
*/
|
|
@@ -535,6 +587,10 @@ declare function endsWith<S extends string>(suffix: S): Decoder<`${string}${S}`>
|
|
|
535
587
|
* (This will not mean that the email address actually exist.)
|
|
536
588
|
*/
|
|
537
589
|
declare const email: Decoder<string>;
|
|
590
|
+
/**
|
|
591
|
+
* Accepts strings that are valid URLs.
|
|
592
|
+
*/
|
|
593
|
+
declare const urlString: Decoder<string>;
|
|
538
594
|
/**
|
|
539
595
|
* Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
540
596
|
*/
|
|
@@ -660,4 +716,4 @@ declare function isPromiseLike(value: unknown): value is PromiseLike<unknown>;
|
|
|
660
716
|
*/
|
|
661
717
|
declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
662
718
|
|
|
663
|
-
export { type Annotation, type ArrayAnnotation, type DecodeResult, type Decoder, type DecoderType, type Err, type Formatter, type JSONArray, type JSONObject, type JSONValue, type ObjectAnnotation, type Ok, type OpaqueAnnotation, type Result, type Scalar, type ScalarAnnotation, type SizeOptions, public_annotate as _annotate, always, anyNumber, anything, array, bigint, boolean, constant, date, dateString, datelike, decimal, define, either, email, endsWith, enum_, err, exact, fail, formatInline, formatShort, hexadecimal, httpsUrl, identifier, inexact, instanceOf, integer, isDate, isDecoder, isPlainObject, isPromiseLike, iso8601, json, jsonArray, jsonObject, lazy, mapping, nanoid, never, nonEmptyArray, nonEmptyString, null_, nullable, nullish, number, numeric, object, ok, oneOf, optional, poja, pojo, positiveInteger, positiveNumber, prep, record, regex, select, setFromArray, startsWith, string, taggedUnion, truthy, tuple, undefined_, unknown, url, uuid, uuidv1, uuidv4 };
|
|
719
|
+
export { type Annotation, type ArrayAnnotation, type DecodeResult, type Decoder, type DecoderType, type Err, type Formatter, type JSONArray, type JSONObject, type JSONValue, type ObjectAnnotation, type Ok, type OpaqueAnnotation, type Result, type Scalar, type ScalarAnnotation, type SizeOptions, type Sized, public_annotate as _annotate, always, anyNumber, anything, array, between, bigint, boolean, constant, date, dateString, datelike, decimal, define, either, email, endsWith, enum_, err, exact, fail, formatInline, formatShort, hexadecimal, httpsUrl, identifier, inexact, instanceOf, integer, isDate, isDecoder, isPlainObject, isPromiseLike, iso8601, json, jsonArray, jsonObject, lazy, mapping, max, min, nanoid, never, nonEmptyArray, nonEmptyString, null_, nullable, nullish, number, numeric, object, ok, oneOf, optional, poja, pojo, positiveInteger, positiveNumber, prep, record, regex, select, setFromArray, sized, startsWith, string, taggedUnion, truthy, tuple, undefined_, unknown, url, urlString, uuid, uuidv1, uuidv4 };
|
package/dist/index.d.ts
CHANGED
|
@@ -398,11 +398,41 @@ declare const jsonArray: Decoder<JSONArray>;
|
|
|
398
398
|
*/
|
|
399
399
|
declare const json: Decoder<JSONValue>;
|
|
400
400
|
|
|
401
|
+
/**
|
|
402
|
+
* Forces TypeScript to "evaluate" named helper types, making API signatures
|
|
403
|
+
* clearer in IDEs.
|
|
404
|
+
*
|
|
405
|
+
* @see https://effectivetypescript.com/2022/02/25/gentips-4-display/
|
|
406
|
+
*/
|
|
407
|
+
type Resolve$1<T> = T extends (...args: unknown[]) => unknown ? T : {
|
|
408
|
+
[K in keyof T]: T[K];
|
|
409
|
+
};
|
|
410
|
+
/**
|
|
411
|
+
* Relaxes a discriminated union type definition, by explicitly adding
|
|
412
|
+
* properties defined in any other member as optional `never`.
|
|
413
|
+
*
|
|
414
|
+
* This makes accessing the members much more relaxed in TypeScript.
|
|
415
|
+
*/
|
|
416
|
+
type Relax<T> = DistributiveRelax<T, T extends any ? keyof T : never>;
|
|
417
|
+
type DistributiveRelax<T, Ks extends string | number | symbol> = T extends any ? Resolve$1<{
|
|
418
|
+
[K in keyof T]: T[K];
|
|
419
|
+
} & {
|
|
420
|
+
[K in Exclude<Ks, keyof T>]?: never;
|
|
421
|
+
}> : never;
|
|
422
|
+
|
|
401
423
|
type SizeOptions = {
|
|
402
424
|
min?: number;
|
|
403
425
|
max?: number;
|
|
404
426
|
size?: number;
|
|
405
427
|
};
|
|
428
|
+
/**
|
|
429
|
+
* Anything with a .length or .size property, like strings, arrays, or sets.
|
|
430
|
+
*/
|
|
431
|
+
type Sized = Relax<{
|
|
432
|
+
length: number;
|
|
433
|
+
} | {
|
|
434
|
+
size: number;
|
|
435
|
+
}>;
|
|
406
436
|
|
|
407
437
|
interface Klass<T> extends Function {
|
|
408
438
|
new (...args: readonly any[]): T;
|
|
@@ -417,6 +447,10 @@ declare function instanceOf<K extends Klass<any>>(klass: K): Decoder<Instance<K>
|
|
|
417
447
|
* types for recursive data structures.
|
|
418
448
|
*/
|
|
419
449
|
declare function lazy<T>(decoderFn: () => Decoder<T>): Decoder<T>;
|
|
450
|
+
/**
|
|
451
|
+
* Only accept strings, arrays, or sets with given length constraints.
|
|
452
|
+
*/
|
|
453
|
+
declare function sized<T extends Sized>(decoder: Decoder<T>, options: SizeOptions): Decoder<T>;
|
|
420
454
|
/**
|
|
421
455
|
* Pre-process the data input before passing it into the decoder. This gives
|
|
422
456
|
* you the ability to arbitrarily customize the input on the fly before passing
|
|
@@ -450,6 +484,24 @@ declare const positiveNumber: Decoder<number>;
|
|
|
450
484
|
* Accepts only non-negative (zero or positive) finite whole numbers.
|
|
451
485
|
*/
|
|
452
486
|
declare const positiveInteger: Decoder<number>;
|
|
487
|
+
/**
|
|
488
|
+
* Accepts numbers greater than or equal to the given minimum.
|
|
489
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
490
|
+
* different decoder to further restrict accepted values, e.g. ``min(0, integer)``.
|
|
491
|
+
*/
|
|
492
|
+
declare function min(min: number, decoder?: Decoder<number>): Decoder<number>;
|
|
493
|
+
/**
|
|
494
|
+
* Accepts numbers less than or equal to the given maximum.
|
|
495
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
496
|
+
* different decoder to further restrict accepted values, e.g. ``max(100, integer)``.
|
|
497
|
+
*/
|
|
498
|
+
declare function max(max: number, decoder?: Decoder<number>): Decoder<number>;
|
|
499
|
+
/**
|
|
500
|
+
* Accepts numbers within the given range (bounds are inclusive).
|
|
501
|
+
* Defaults to the ``number`` decoder if none is provided. Pass a
|
|
502
|
+
* different decoder to further restrict accepted values, e.g. ``between(1, 10, integer)``.
|
|
503
|
+
*/
|
|
504
|
+
declare function between(min: number, max: number, decoder?: Decoder<number>): Decoder<number>;
|
|
453
505
|
/**
|
|
454
506
|
* Accepts any valid ``bigint`` value.
|
|
455
507
|
*/
|
|
@@ -535,6 +587,10 @@ declare function endsWith<S extends string>(suffix: S): Decoder<`${string}${S}`>
|
|
|
535
587
|
* (This will not mean that the email address actually exist.)
|
|
536
588
|
*/
|
|
537
589
|
declare const email: Decoder<string>;
|
|
590
|
+
/**
|
|
591
|
+
* Accepts strings that are valid URLs.
|
|
592
|
+
*/
|
|
593
|
+
declare const urlString: Decoder<string>;
|
|
538
594
|
/**
|
|
539
595
|
* Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
540
596
|
*/
|
|
@@ -660,4 +716,4 @@ declare function isPromiseLike(value: unknown): value is PromiseLike<unknown>;
|
|
|
660
716
|
*/
|
|
661
717
|
declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
662
718
|
|
|
663
|
-
export { type Annotation, type ArrayAnnotation, type DecodeResult, type Decoder, type DecoderType, type Err, type Formatter, type JSONArray, type JSONObject, type JSONValue, type ObjectAnnotation, type Ok, type OpaqueAnnotation, type Result, type Scalar, type ScalarAnnotation, type SizeOptions, public_annotate as _annotate, always, anyNumber, anything, array, bigint, boolean, constant, date, dateString, datelike, decimal, define, either, email, endsWith, enum_, err, exact, fail, formatInline, formatShort, hexadecimal, httpsUrl, identifier, inexact, instanceOf, integer, isDate, isDecoder, isPlainObject, isPromiseLike, iso8601, json, jsonArray, jsonObject, lazy, mapping, nanoid, never, nonEmptyArray, nonEmptyString, null_, nullable, nullish, number, numeric, object, ok, oneOf, optional, poja, pojo, positiveInteger, positiveNumber, prep, record, regex, select, setFromArray, startsWith, string, taggedUnion, truthy, tuple, undefined_, unknown, url, uuid, uuidv1, uuidv4 };
|
|
719
|
+
export { type Annotation, type ArrayAnnotation, type DecodeResult, type Decoder, type DecoderType, type Err, type Formatter, type JSONArray, type JSONObject, type JSONValue, type ObjectAnnotation, type Ok, type OpaqueAnnotation, type Result, type Scalar, type ScalarAnnotation, type SizeOptions, type Sized, public_annotate as _annotate, always, anyNumber, anything, array, between, bigint, boolean, constant, date, dateString, datelike, decimal, define, either, email, endsWith, enum_, err, exact, fail, formatInline, formatShort, hexadecimal, httpsUrl, identifier, inexact, instanceOf, integer, isDate, isDecoder, isPlainObject, isPromiseLike, iso8601, json, jsonArray, jsonObject, lazy, mapping, max, min, nanoid, never, nonEmptyArray, nonEmptyString, null_, nullable, nullish, number, numeric, object, ok, oneOf, optional, poja, pojo, positiveInteger, positiveNumber, prep, record, regex, select, setFromArray, sized, startsWith, string, taggedUnion, truthy, tuple, undefined_, unknown, url, urlString, uuid, uuidv1, uuidv4 };
|
package/dist/index.js
CHANGED
|
@@ -478,6 +478,28 @@ function tuple(...decoders) {
|
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
// src/lib/size-options.ts
|
|
482
|
+
function bySizeOptions(options) {
|
|
483
|
+
const size = options.size;
|
|
484
|
+
const min2 = size ?? options.min;
|
|
485
|
+
const max2 = size ?? options.max;
|
|
486
|
+
const atLeast = min2 === max2 ? "" : "at least ";
|
|
487
|
+
const atMost = min2 === max2 ? "" : "at most ";
|
|
488
|
+
return (value) => {
|
|
489
|
+
const len = value.length ?? value.size;
|
|
490
|
+
if (typeof value === "string") {
|
|
491
|
+
if (min2 !== void 0 && len < min2)
|
|
492
|
+
return `Too short, must be ${atLeast}${min2} chars`;
|
|
493
|
+
if (max2 !== void 0 && len > max2)
|
|
494
|
+
return `Too long, must be ${atMost}${max2} chars`;
|
|
495
|
+
} else {
|
|
496
|
+
if (min2 !== void 0 && len < min2) return `Must have ${atLeast}${min2} items`;
|
|
497
|
+
if (max2 !== void 0 && len > max2) return `Must have ${atMost}${max2} items`;
|
|
498
|
+
}
|
|
499
|
+
return null;
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
481
503
|
// src/misc.ts
|
|
482
504
|
function instanceOf(klass) {
|
|
483
505
|
return define(
|
|
@@ -490,6 +512,9 @@ function instanceOf(klass) {
|
|
|
490
512
|
function lazy(decoderFn) {
|
|
491
513
|
return define((blob) => decoderFn().decode(blob));
|
|
492
514
|
}
|
|
515
|
+
function sized(decoder, options) {
|
|
516
|
+
return decoder.reject(bySizeOptions(options));
|
|
517
|
+
}
|
|
493
518
|
function prep(mapperFn, decoder) {
|
|
494
519
|
return define((originalInput, _, err2) => {
|
|
495
520
|
let blob;
|
|
@@ -748,18 +773,6 @@ function mapping(decoder) {
|
|
|
748
773
|
return record(decoder).transform((obj) => new Map(Object.entries(obj)));
|
|
749
774
|
}
|
|
750
775
|
|
|
751
|
-
// src/lib/size-options.ts
|
|
752
|
-
function bySizeOptions(options) {
|
|
753
|
-
const size = options.size;
|
|
754
|
-
const min = size ?? options.min;
|
|
755
|
-
const max = size ?? options.max;
|
|
756
|
-
const atLeast = min === max ? "" : "at least ";
|
|
757
|
-
const atMost = min === max ? "" : "at most ";
|
|
758
|
-
const tooShort = min !== void 0 && `Too short, must be ${atLeast}${min} chars`;
|
|
759
|
-
const tooLong = max !== void 0 && `Too long, must be ${atMost}${max} chars`;
|
|
760
|
-
return tooShort && tooLong ? (s) => s.length < min ? tooShort : s.length > max ? tooLong : null : tooShort ? (s) => s.length < min ? tooShort : null : tooLong ? (s) => s.length > max ? tooLong : null : () => null;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
776
|
// src/strings.ts
|
|
764
777
|
var url_re = /^([A-Za-z]{2,12}(?:[+][A-Za-z]{2,12})?):\/\/(?:([^@:]*:?(?:[^@]+)?)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,/\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
765
778
|
var string = define(
|
|
@@ -786,6 +799,10 @@ var email = regex(
|
|
|
786
799
|
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
787
800
|
"Must be email"
|
|
788
801
|
);
|
|
802
|
+
var urlString = string.refine(
|
|
803
|
+
(s) => URL.canParse(s),
|
|
804
|
+
"Must be URL"
|
|
805
|
+
);
|
|
789
806
|
var url = either(
|
|
790
807
|
regex(url_re, "Must be URL").transform((value) => new URL(value)),
|
|
791
808
|
instanceOf(URL)
|
|
@@ -799,9 +816,7 @@ var identifier = regex(
|
|
|
799
816
|
"Must be valid identifier"
|
|
800
817
|
);
|
|
801
818
|
function nanoid(options) {
|
|
802
|
-
return regex(/^[a-z0-9_-]+$/i, "Must be nano ID")
|
|
803
|
-
bySizeOptions(options ?? { size: 21 })
|
|
804
|
-
);
|
|
819
|
+
return sized(regex(/^[a-z0-9_-]+$/i, "Must be nano ID"), options ?? { size: 21 });
|
|
805
820
|
}
|
|
806
821
|
var uuid = regex(
|
|
807
822
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
@@ -857,6 +872,17 @@ var positiveInteger = integer.refine(
|
|
|
857
872
|
(n) => n >= 0 && !Object.is(n, -0),
|
|
858
873
|
"Number must be positive"
|
|
859
874
|
);
|
|
875
|
+
function min(min2, decoder = number) {
|
|
876
|
+
return decoder.reject((value) => value < min2 ? `Must be at least ${min2}` : null);
|
|
877
|
+
}
|
|
878
|
+
function max(max2, decoder = number) {
|
|
879
|
+
return decoder.reject((value) => value > max2 ? `Must be at most ${max2}` : null);
|
|
880
|
+
}
|
|
881
|
+
function between(min2, max2, decoder = number) {
|
|
882
|
+
return decoder.reject(
|
|
883
|
+
(value) => value < min2 ? `Must be at least ${min2}` : value > max2 ? `Must be at most ${max2}` : null
|
|
884
|
+
);
|
|
885
|
+
}
|
|
860
886
|
var bigint = define(
|
|
861
887
|
(blob, ok2, err2) => isBigInt(blob) ? ok2(blob) : err2("Must be bigint")
|
|
862
888
|
);
|
|
@@ -878,6 +904,7 @@ export {
|
|
|
878
904
|
anyNumber,
|
|
879
905
|
anything,
|
|
880
906
|
array,
|
|
907
|
+
between,
|
|
881
908
|
bigint,
|
|
882
909
|
boolean,
|
|
883
910
|
constant,
|
|
@@ -911,6 +938,8 @@ export {
|
|
|
911
938
|
jsonObject,
|
|
912
939
|
lazy,
|
|
913
940
|
mapping,
|
|
941
|
+
max,
|
|
942
|
+
min,
|
|
914
943
|
nanoid,
|
|
915
944
|
never,
|
|
916
945
|
nonEmptyArray,
|
|
@@ -933,6 +962,7 @@ export {
|
|
|
933
962
|
regex,
|
|
934
963
|
select,
|
|
935
964
|
setFromArray,
|
|
965
|
+
sized,
|
|
936
966
|
startsWith,
|
|
937
967
|
string,
|
|
938
968
|
taggedUnion,
|
|
@@ -941,6 +971,7 @@ export {
|
|
|
941
971
|
undefined_,
|
|
942
972
|
unknown,
|
|
943
973
|
url,
|
|
974
|
+
urlString,
|
|
944
975
|
uuid,
|
|
945
976
|
uuidv1,
|
|
946
977
|
uuidv4
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "decoders",
|
|
3
|
-
"version": "2.9.0-pre.
|
|
3
|
+
"version": "2.9.0-pre.2",
|
|
4
4
|
"description": "Elegant and battle-tested validation library for type-safe input data for TypeScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,12 +35,11 @@
|
|
|
35
35
|
],
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsup",
|
|
38
|
-
"docs
|
|
39
|
-
"docs:build": "cd docs && npm run build",
|
|
38
|
+
"docs": "npm run build && cp -r dist/ docs/decoders-latest-snapshot/ && cd docs && rm -rf .next && npm run dev",
|
|
40
39
|
"docs:update-sources": "node bin/update-source-lines.js",
|
|
41
40
|
"lint": "oxlint src/ test/ && prettier --list-different src/ test/ test-d/",
|
|
42
41
|
"lint:package": "publint --strict && attw --pack",
|
|
43
|
-
"format": "oxlint --fix src/ test/ ; prettier --write src/ test/ test-d/",
|
|
42
|
+
"format": "oxlint --fix src/ test/ ; prettier --write src/ test/ test-d/ docs/content/ ; npm run docs:update-sources",
|
|
44
43
|
"test": "vitest run --coverage",
|
|
45
44
|
"test:completeness": "./bin/check.sh",
|
|
46
45
|
"test:typescript": "tsc --noEmit",
|
|
@@ -67,7 +66,7 @@
|
|
|
67
66
|
"@vitest/coverage-istanbul": "^4.0.18",
|
|
68
67
|
"fast-check": "^4.5.3",
|
|
69
68
|
"itertools": "^2.6.0",
|
|
70
|
-
"oxlint": "^1.
|
|
69
|
+
"oxlint": "^1.51.0",
|
|
71
70
|
"pkg-pr-new": "^0.0.65",
|
|
72
71
|
"prettier": "^3.8.1",
|
|
73
72
|
"publint": "^0.3.18",
|