decoders 2.9.3 → 2.10.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/index.cjs +58 -23
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +58 -23
- package/package.json +13 -13
package/dist/index.cjs
CHANGED
|
@@ -574,11 +574,26 @@ function difference(xs, ys) {
|
|
|
574
574
|
}
|
|
575
575
|
|
|
576
576
|
// src/objects.ts
|
|
577
|
+
// @__NO_SIDE_EFFECTS__
|
|
578
|
+
function rejectUnsafeKey(decoders) {
|
|
579
|
+
if (Object.prototype.hasOwnProperty.call(decoders, "__proto__")) {
|
|
580
|
+
throw new Error(
|
|
581
|
+
'Unsafe key: "__proto__" cannot be used in an object(), exact(), or inexact() definition'
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// @__NO_SIDE_EFFECTS__
|
|
586
|
+
function annotateUnsafeKey(plainObj) {
|
|
587
|
+
return merge(
|
|
588
|
+
public_annotateObject(plainObj),
|
|
589
|
+
/* @__PURE__ */ new Map([["__proto__", public_annotate(plainObj["__proto__"], "Unsafe key")]])
|
|
590
|
+
);
|
|
591
|
+
}
|
|
577
592
|
var pojo = define(
|
|
578
593
|
(blob, ok2, err2) => isPlainObject(blob) ? ok2(blob) : err2("Must be an object")
|
|
579
594
|
);
|
|
580
595
|
// @__NO_SIDE_EFFECTS__
|
|
581
|
-
function
|
|
596
|
+
function buildObject(decoders) {
|
|
582
597
|
const knownKeys = new Set(Object.keys(decoders));
|
|
583
598
|
return pojo.chain((plainObj, ok2, err2) => {
|
|
584
599
|
const actualKeys = new Set(Object.keys(plainObj));
|
|
@@ -621,36 +636,51 @@ function object(decoders) {
|
|
|
621
636
|
});
|
|
622
637
|
}
|
|
623
638
|
// @__NO_SIDE_EFFECTS__
|
|
639
|
+
function object(decoders) {
|
|
640
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
641
|
+
return /* @__PURE__ */ buildObject(decoders);
|
|
642
|
+
}
|
|
643
|
+
// @__NO_SIDE_EFFECTS__
|
|
624
644
|
function exact(decoders) {
|
|
645
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
625
646
|
const allowedKeys = new Set(Object.keys(decoders));
|
|
626
|
-
const checked = pojo.
|
|
647
|
+
const checked = pojo.chain((plainObj, ok2, err2) => {
|
|
627
648
|
const actualKeys = new Set(Object.keys(plainObj));
|
|
649
|
+
if (actualKeys.has("__proto__")) {
|
|
650
|
+
return err2(/* @__PURE__ */ annotateUnsafeKey(plainObj));
|
|
651
|
+
}
|
|
628
652
|
const extraKeys = difference(actualKeys, allowedKeys);
|
|
629
|
-
return extraKeys.size > 0 ? `Unexpected extra keys: ${Array.from(extraKeys).map(quote).join(", ")}` :
|
|
653
|
+
return extraKeys.size > 0 ? err2(`Unexpected extra keys: ${Array.from(extraKeys).map(quote).join(", ")}`) : ok2(plainObj);
|
|
630
654
|
});
|
|
631
|
-
return checked.pipe(/* @__PURE__ */
|
|
655
|
+
return checked.pipe(/* @__PURE__ */ buildObject(decoders));
|
|
632
656
|
}
|
|
633
657
|
// @__NO_SIDE_EFFECTS__
|
|
634
658
|
function inexact(decoders) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
659
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
660
|
+
return pojo.chain(
|
|
661
|
+
(plainObj, _ok, err2) => {
|
|
662
|
+
const allkeys = new Set(Object.keys(plainObj));
|
|
663
|
+
if (allkeys.has("__proto__")) {
|
|
664
|
+
return err2(/* @__PURE__ */ annotateUnsafeKey(plainObj));
|
|
665
|
+
}
|
|
666
|
+
return (/* @__PURE__ */ buildObject(decoders)).transform((safepart) => {
|
|
667
|
+
const safekeys = new Set(Object.keys(decoders));
|
|
668
|
+
for (const k of safekeys) allkeys.add(k);
|
|
669
|
+
const rv = {};
|
|
670
|
+
for (const k of allkeys) {
|
|
671
|
+
if (safekeys.has(k)) {
|
|
672
|
+
const value = safepart[k];
|
|
673
|
+
if (value !== void 0) {
|
|
674
|
+
rv[k] = value;
|
|
675
|
+
}
|
|
676
|
+
} else {
|
|
677
|
+
rv[k] = plainObj[k];
|
|
646
678
|
}
|
|
647
|
-
} else {
|
|
648
|
-
rv[k] = plainObj[k];
|
|
649
679
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
|
|
680
|
+
return rv;
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
);
|
|
654
684
|
}
|
|
655
685
|
|
|
656
686
|
// src/unions.ts
|
|
@@ -785,6 +815,11 @@ function record(fst, snd) {
|
|
|
785
815
|
const errors = /* @__PURE__ */ new Map();
|
|
786
816
|
for (const key of Object.keys(input)) {
|
|
787
817
|
const value = input[key];
|
|
818
|
+
if (key === "__proto__") {
|
|
819
|
+
errors.set(key, public_annotate(value, "Unsafe key"));
|
|
820
|
+
rv = {};
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
788
823
|
const keyResult = _optionalChain([keyDecoder, 'optionalAccess', _4 => _4.decode, 'call', _5 => _5(key)]);
|
|
789
824
|
if (_optionalChain([keyResult, 'optionalAccess', _6 => _6.ok]) === false) {
|
|
790
825
|
return err2(
|
|
@@ -819,7 +854,7 @@ function mapping(decoder) {
|
|
|
819
854
|
}
|
|
820
855
|
|
|
821
856
|
// src/strings.ts
|
|
822
|
-
var url_re = /^
|
|
857
|
+
var url_re = /^[A-Za-z]{2,12}(?:[+][A-Za-z]{2,12})?:\/\/(?:[^@]*@)?[A-Za-z0-9.-]+(?::[0-9]{2,5})?(?:\/[-+~%/.,!$&'()*:;=@\w]*(?:\?[-+~%/.,!$&'()*:;=@?\w]*)?)?(?:#[^\s#]*)?$/;
|
|
823
858
|
var string = define(
|
|
824
859
|
(blob, ok2, err2) => isString(blob) ? ok2(blob) : err2("Must be string")
|
|
825
860
|
);
|
|
@@ -844,7 +879,7 @@ function endsWith(suffix) {
|
|
|
844
879
|
}
|
|
845
880
|
var email = /* @__PURE__ */ regex(
|
|
846
881
|
// The almost perfect email regex, taken from https://emailregex.com/
|
|
847
|
-
/^(
|
|
882
|
+
/^(?:[^<>()[\]\\.,;:\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,})$/,
|
|
848
883
|
"Must be email"
|
|
849
884
|
);
|
|
850
885
|
var urlString = /* @__PURE__ */ regex(url_re, "Must be URL");
|
package/dist/index.d.cts
CHANGED
|
@@ -550,10 +550,6 @@ type ObjectDecoderType<Ds extends Record<string, Decoder<unknown>>> = UndefinedT
|
|
|
550
550
|
* values further.
|
|
551
551
|
*/
|
|
552
552
|
declare const pojo: Decoder<Record<string, unknown>>;
|
|
553
|
-
/**
|
|
554
|
-
* Accepts objects with fields matching the given decoders. Extra fields that
|
|
555
|
-
* exist on the input object are ignored and will not be returned.
|
|
556
|
-
*/
|
|
557
553
|
declare function object(decoders: Record<any, never>): Decoder<Record<string, never>>;
|
|
558
554
|
declare function object<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds): Decoder<ObjectDecoderType<Ds>>;
|
|
559
555
|
/**
|
|
@@ -565,6 +561,10 @@ declare function exact<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds
|
|
|
565
561
|
/**
|
|
566
562
|
* Like `object()`, but will pass through any extra fields on the input object
|
|
567
563
|
* unvalidated that will thus be of `unknown` type statically.
|
|
564
|
+
*
|
|
565
|
+
* A `__proto__` key is the one exception: it cannot be passed through without
|
|
566
|
+
* reassigning the prototype of the returned object, so inputs containing one
|
|
567
|
+
* are rejected.
|
|
568
568
|
*/
|
|
569
569
|
declare function inexact(decoders: Record<any, never>): Decoder<Record<string, unknown>>;
|
|
570
570
|
declare function inexact<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds): Decoder<ObjectDecoderType<Ds> & Record<string, unknown>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -550,10 +550,6 @@ type ObjectDecoderType<Ds extends Record<string, Decoder<unknown>>> = UndefinedT
|
|
|
550
550
|
* values further.
|
|
551
551
|
*/
|
|
552
552
|
declare const pojo: Decoder<Record<string, unknown>>;
|
|
553
|
-
/**
|
|
554
|
-
* Accepts objects with fields matching the given decoders. Extra fields that
|
|
555
|
-
* exist on the input object are ignored and will not be returned.
|
|
556
|
-
*/
|
|
557
553
|
declare function object(decoders: Record<any, never>): Decoder<Record<string, never>>;
|
|
558
554
|
declare function object<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds): Decoder<ObjectDecoderType<Ds>>;
|
|
559
555
|
/**
|
|
@@ -565,6 +561,10 @@ declare function exact<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds
|
|
|
565
561
|
/**
|
|
566
562
|
* Like `object()`, but will pass through any extra fields on the input object
|
|
567
563
|
* unvalidated that will thus be of `unknown` type statically.
|
|
564
|
+
*
|
|
565
|
+
* A `__proto__` key is the one exception: it cannot be passed through without
|
|
566
|
+
* reassigning the prototype of the returned object, so inputs containing one
|
|
567
|
+
* are rejected.
|
|
568
568
|
*/
|
|
569
569
|
declare function inexact(decoders: Record<any, never>): Decoder<Record<string, unknown>>;
|
|
570
570
|
declare function inexact<Ds extends Record<string, Decoder<unknown>>>(decoders: Ds): Decoder<ObjectDecoderType<Ds> & Record<string, unknown>>;
|
package/dist/index.js
CHANGED
|
@@ -574,11 +574,26 @@ function difference(xs, ys) {
|
|
|
574
574
|
}
|
|
575
575
|
|
|
576
576
|
// src/objects.ts
|
|
577
|
+
// @__NO_SIDE_EFFECTS__
|
|
578
|
+
function rejectUnsafeKey(decoders) {
|
|
579
|
+
if (Object.prototype.hasOwnProperty.call(decoders, "__proto__")) {
|
|
580
|
+
throw new Error(
|
|
581
|
+
'Unsafe key: "__proto__" cannot be used in an object(), exact(), or inexact() definition'
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// @__NO_SIDE_EFFECTS__
|
|
586
|
+
function annotateUnsafeKey(plainObj) {
|
|
587
|
+
return merge(
|
|
588
|
+
public_annotateObject(plainObj),
|
|
589
|
+
/* @__PURE__ */ new Map([["__proto__", public_annotate(plainObj["__proto__"], "Unsafe key")]])
|
|
590
|
+
);
|
|
591
|
+
}
|
|
577
592
|
var pojo = define(
|
|
578
593
|
(blob, ok2, err2) => isPlainObject(blob) ? ok2(blob) : err2("Must be an object")
|
|
579
594
|
);
|
|
580
595
|
// @__NO_SIDE_EFFECTS__
|
|
581
|
-
function
|
|
596
|
+
function buildObject(decoders) {
|
|
582
597
|
const knownKeys = new Set(Object.keys(decoders));
|
|
583
598
|
return pojo.chain((plainObj, ok2, err2) => {
|
|
584
599
|
const actualKeys = new Set(Object.keys(plainObj));
|
|
@@ -621,36 +636,51 @@ function object(decoders) {
|
|
|
621
636
|
});
|
|
622
637
|
}
|
|
623
638
|
// @__NO_SIDE_EFFECTS__
|
|
639
|
+
function object(decoders) {
|
|
640
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
641
|
+
return /* @__PURE__ */ buildObject(decoders);
|
|
642
|
+
}
|
|
643
|
+
// @__NO_SIDE_EFFECTS__
|
|
624
644
|
function exact(decoders) {
|
|
645
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
625
646
|
const allowedKeys = new Set(Object.keys(decoders));
|
|
626
|
-
const checked = pojo.
|
|
647
|
+
const checked = pojo.chain((plainObj, ok2, err2) => {
|
|
627
648
|
const actualKeys = new Set(Object.keys(plainObj));
|
|
649
|
+
if (actualKeys.has("__proto__")) {
|
|
650
|
+
return err2(/* @__PURE__ */ annotateUnsafeKey(plainObj));
|
|
651
|
+
}
|
|
628
652
|
const extraKeys = difference(actualKeys, allowedKeys);
|
|
629
|
-
return extraKeys.size > 0 ? `Unexpected extra keys: ${Array.from(extraKeys).map(quote).join(", ")}` :
|
|
653
|
+
return extraKeys.size > 0 ? err2(`Unexpected extra keys: ${Array.from(extraKeys).map(quote).join(", ")}`) : ok2(plainObj);
|
|
630
654
|
});
|
|
631
|
-
return checked.pipe(/* @__PURE__ */
|
|
655
|
+
return checked.pipe(/* @__PURE__ */ buildObject(decoders));
|
|
632
656
|
}
|
|
633
657
|
// @__NO_SIDE_EFFECTS__
|
|
634
658
|
function inexact(decoders) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
659
|
+
/* @__PURE__ */ rejectUnsafeKey(decoders);
|
|
660
|
+
return pojo.chain(
|
|
661
|
+
(plainObj, _ok, err2) => {
|
|
662
|
+
const allkeys = new Set(Object.keys(plainObj));
|
|
663
|
+
if (allkeys.has("__proto__")) {
|
|
664
|
+
return err2(/* @__PURE__ */ annotateUnsafeKey(plainObj));
|
|
665
|
+
}
|
|
666
|
+
return (/* @__PURE__ */ buildObject(decoders)).transform((safepart) => {
|
|
667
|
+
const safekeys = new Set(Object.keys(decoders));
|
|
668
|
+
for (const k of safekeys) allkeys.add(k);
|
|
669
|
+
const rv = {};
|
|
670
|
+
for (const k of allkeys) {
|
|
671
|
+
if (safekeys.has(k)) {
|
|
672
|
+
const value = safepart[k];
|
|
673
|
+
if (value !== void 0) {
|
|
674
|
+
rv[k] = value;
|
|
675
|
+
}
|
|
676
|
+
} else {
|
|
677
|
+
rv[k] = plainObj[k];
|
|
646
678
|
}
|
|
647
|
-
} else {
|
|
648
|
-
rv[k] = plainObj[k];
|
|
649
679
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
|
|
680
|
+
return rv;
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
);
|
|
654
684
|
}
|
|
655
685
|
|
|
656
686
|
// src/unions.ts
|
|
@@ -785,6 +815,11 @@ function record(fst, snd) {
|
|
|
785
815
|
const errors = /* @__PURE__ */ new Map();
|
|
786
816
|
for (const key of Object.keys(input)) {
|
|
787
817
|
const value = input[key];
|
|
818
|
+
if (key === "__proto__") {
|
|
819
|
+
errors.set(key, public_annotate(value, "Unsafe key"));
|
|
820
|
+
rv = {};
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
788
823
|
const keyResult = keyDecoder?.decode(key);
|
|
789
824
|
if (keyResult?.ok === false) {
|
|
790
825
|
return err2(
|
|
@@ -819,7 +854,7 @@ function mapping(decoder) {
|
|
|
819
854
|
}
|
|
820
855
|
|
|
821
856
|
// src/strings.ts
|
|
822
|
-
var url_re = /^
|
|
857
|
+
var url_re = /^[A-Za-z]{2,12}(?:[+][A-Za-z]{2,12})?:\/\/(?:[^@]*@)?[A-Za-z0-9.-]+(?::[0-9]{2,5})?(?:\/[-+~%/.,!$&'()*:;=@\w]*(?:\?[-+~%/.,!$&'()*:;=@?\w]*)?)?(?:#[^\s#]*)?$/;
|
|
823
858
|
var string = define(
|
|
824
859
|
(blob, ok2, err2) => isString(blob) ? ok2(blob) : err2("Must be string")
|
|
825
860
|
);
|
|
@@ -844,7 +879,7 @@ function endsWith(suffix) {
|
|
|
844
879
|
}
|
|
845
880
|
var email = /* @__PURE__ */ regex(
|
|
846
881
|
// The almost perfect email regex, taken from https://emailregex.com/
|
|
847
|
-
/^(
|
|
882
|
+
/^(?:[^<>()[\]\\.,;:\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,})$/,
|
|
848
883
|
"Must be email"
|
|
849
884
|
);
|
|
850
885
|
var urlString = /* @__PURE__ */ regex(url_re, "Must be URL");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "decoders",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"description": "Elegant and battle-tested validation library for type-safe input data for TypeScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -62,22 +62,22 @@
|
|
|
62
62
|
"verify"
|
|
63
63
|
],
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@arethetypeswrong/cli": "^0.18.
|
|
66
|
-
"@release-it/keep-a-changelog": "^
|
|
65
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
66
|
+
"@release-it/keep-a-changelog": "^8.0.1",
|
|
67
67
|
"@standard-schema/spec": "^1.1.0",
|
|
68
|
-
"@vitest/coverage-istanbul": "^4.1.
|
|
69
|
-
"fast-check": "^4.
|
|
70
|
-
"itertools": "^2.
|
|
71
|
-
"oxlint": "^1.
|
|
72
|
-
"pkg-pr-new": "^0.0.
|
|
73
|
-
"prettier": "^3.
|
|
74
|
-
"publint": "^0.3.
|
|
75
|
-
"release-it": "^
|
|
76
|
-
"ts-morph": "^
|
|
68
|
+
"@vitest/coverage-istanbul": "^4.1.11",
|
|
69
|
+
"fast-check": "^4.10.0",
|
|
70
|
+
"itertools": "^2.7.1",
|
|
71
|
+
"oxlint": "^1.83.0",
|
|
72
|
+
"pkg-pr-new": "^0.0.88",
|
|
73
|
+
"prettier": "^3.9.6",
|
|
74
|
+
"publint": "^0.3.24",
|
|
75
|
+
"release-it": "^21.0.3",
|
|
76
|
+
"ts-morph": "^28.0.0",
|
|
77
77
|
"tsd": "^0.33.0",
|
|
78
78
|
"tsup": "^8.5.1",
|
|
79
79
|
"typescript": "^5.9.3",
|
|
80
|
-
"vitest": "^4.1.
|
|
80
|
+
"vitest": "^4.1.11"
|
|
81
81
|
},
|
|
82
82
|
"githubUrl": "https://github.com/nvie/decoders",
|
|
83
83
|
"sideEffects": false
|