decoders 2.11.0 → 2.12.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 +123 -45
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +123 -45
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -371,29 +371,60 @@ ${formatted}`);
|
|
|
371
371
|
return formatted;
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
374
|
+
var _standard = /* @__PURE__ */ new WeakMap();
|
|
375
|
+
var DecoderImpl = class {
|
|
376
|
+
/**
|
|
377
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
378
|
+
*
|
|
379
|
+
* Contrasted with `.verify()`, calls to `.decode()` will never fail and
|
|
380
|
+
* instead return a result type.
|
|
381
|
+
*/
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
385
|
+
* When accepted, returns a value of type `T`. Otherwise fail with
|
|
386
|
+
* a runtime error.
|
|
387
|
+
*/
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
391
|
+
* When accepted, returns the decoded `T` value directly. Otherwise returns
|
|
392
|
+
* `undefined`.
|
|
393
|
+
*
|
|
394
|
+
* Use this when you're not interested in programmatically handling the
|
|
395
|
+
* error message.
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
constructor(fn) {
|
|
399
|
+
const decode = (blob) => {
|
|
400
|
+
const makeFlexErr = (msg) => err(isAnnotation(msg) ? msg : public_annotate(blob, msg));
|
|
401
|
+
return fn(blob, ok, makeFlexErr);
|
|
402
|
+
};
|
|
403
|
+
const verify = (blob, formatter = formatInline) => {
|
|
404
|
+
const result = decode(blob);
|
|
405
|
+
if (result.ok) {
|
|
406
|
+
return result.value;
|
|
407
|
+
} else {
|
|
408
|
+
throw format(result.error, formatter);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const value = (blob) => decode(blob).value;
|
|
412
|
+
this.decode = decode;
|
|
413
|
+
this.verify = verify;
|
|
414
|
+
this.value = value;
|
|
390
415
|
}
|
|
391
|
-
|
|
392
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Accepts any value the given decoder accepts, and on success, will call
|
|
418
|
+
* the given function **on the decoded result**. If the transformation
|
|
419
|
+
* function throws an error, the whole decoder will fail using the error
|
|
420
|
+
* message as the failure reason.
|
|
421
|
+
*/
|
|
422
|
+
transform(transformFn) {
|
|
423
|
+
return this.chain(noThrow(transformFn));
|
|
393
424
|
}
|
|
394
|
-
|
|
395
|
-
return reject(
|
|
396
|
-
(
|
|
425
|
+
refine(predicateFn, errmsg) {
|
|
426
|
+
return this.reject(
|
|
427
|
+
(value) => predicateFn(value) ? (
|
|
397
428
|
// Don't reject
|
|
398
429
|
null
|
|
399
430
|
) : (
|
|
@@ -402,10 +433,25 @@ function define(fn) {
|
|
|
402
433
|
)
|
|
403
434
|
);
|
|
404
435
|
}
|
|
405
|
-
|
|
406
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Cast the return type of this read-only decoder to a narrower type. This is
|
|
438
|
+
* useful to return "branded" types. This method has no runtime effect.
|
|
439
|
+
*/
|
|
440
|
+
refineType() {
|
|
441
|
+
return this;
|
|
407
442
|
}
|
|
408
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Send the output of the current decoder into another decoder or acceptance
|
|
445
|
+
* function. The given acceptance function will receive the output of the
|
|
446
|
+
* current decoder as its input.
|
|
447
|
+
*
|
|
448
|
+
* > _**NOTE:** This is an advanced, low-level, API. It's not recommended
|
|
449
|
+
* > to reach for this construct unless there is no other way. Most cases can
|
|
450
|
+
* > be covered more elegantly by `.transform()`, `.refine()`, or `.pipe()`
|
|
451
|
+
* > instead._
|
|
452
|
+
*/
|
|
453
|
+
chain(next) {
|
|
454
|
+
const decode = this.decode;
|
|
409
455
|
return /* @__PURE__ */ define((blob, ok2, err2) => {
|
|
410
456
|
const r1 = decode(blob);
|
|
411
457
|
if (!r1.ok) return r1;
|
|
@@ -413,16 +459,46 @@ function define(fn) {
|
|
|
413
459
|
return /* @__PURE__ */ isDecoder(r2) ? r2.decode(r1.value) : r2;
|
|
414
460
|
});
|
|
415
461
|
}
|
|
416
|
-
|
|
417
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Send the output of this decoder as input to another decoder.
|
|
464
|
+
*
|
|
465
|
+
* This can be useful to validate the results of a transform, i.e.:
|
|
466
|
+
*
|
|
467
|
+
* string
|
|
468
|
+
* .transform((s) => s.split(','))
|
|
469
|
+
* .pipe(array(nonEmptyString))
|
|
470
|
+
*
|
|
471
|
+
* You can also conditionally pipe:
|
|
472
|
+
*
|
|
473
|
+
* string.pipe((s) => s.startsWith('@') ? username : email)
|
|
474
|
+
*/
|
|
475
|
+
pipe(next) {
|
|
476
|
+
return this.chain(next);
|
|
418
477
|
}
|
|
419
|
-
|
|
420
|
-
|
|
478
|
+
/**
|
|
479
|
+
* Adds an extra predicate to a decoder. The new decoder is like the
|
|
480
|
+
* original decoder, but only accepts values that aren't rejected by the
|
|
481
|
+
* given function.
|
|
482
|
+
*
|
|
483
|
+
* The given function can return `null` to accept the decoded value, or
|
|
484
|
+
* return a specific error message to reject.
|
|
485
|
+
*
|
|
486
|
+
* Unlike `.refine()`, you can use this function to return a dynamic error
|
|
487
|
+
* message.
|
|
488
|
+
*/
|
|
489
|
+
reject(rejectFn) {
|
|
490
|
+
return this.chain((blob, ok2, err2) => {
|
|
421
491
|
const errmsg = rejectFn(blob);
|
|
422
492
|
return errmsg === null ? ok2(blob) : err2(typeof errmsg === "string" ? public_annotate(blob, errmsg) : errmsg);
|
|
423
493
|
});
|
|
424
494
|
}
|
|
425
|
-
|
|
495
|
+
/**
|
|
496
|
+
* Uses the given decoder, but will use an alternative error message in
|
|
497
|
+
* case it rejects. This can be used to simplify or shorten otherwise
|
|
498
|
+
* long or low-level/technical errors.
|
|
499
|
+
*/
|
|
500
|
+
describe(message) {
|
|
501
|
+
const decode = this.decode;
|
|
426
502
|
return /* @__PURE__ */ define((blob, _, err2) => {
|
|
427
503
|
const result = decode(blob);
|
|
428
504
|
if (result.ok) {
|
|
@@ -432,18 +508,14 @@ function define(fn) {
|
|
|
432
508
|
}
|
|
433
509
|
});
|
|
434
510
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
describe,
|
|
444
|
-
chain,
|
|
445
|
-
pipe,
|
|
446
|
-
"~standard": {
|
|
511
|
+
/**
|
|
512
|
+
* The Standard Schema interface for this decoder.
|
|
513
|
+
*/
|
|
514
|
+
get "~standard"() {
|
|
515
|
+
const memo = _standard.get(this);
|
|
516
|
+
if (memo !== void 0) return memo;
|
|
517
|
+
const decode = this.decode;
|
|
518
|
+
const props = {
|
|
447
519
|
version: 1,
|
|
448
520
|
vendor: "decoders",
|
|
449
521
|
validate: (blob) => {
|
|
@@ -455,10 +527,16 @@ function define(fn) {
|
|
|
455
527
|
return { issues };
|
|
456
528
|
}
|
|
457
529
|
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
530
|
+
};
|
|
531
|
+
_standard.set(this, props);
|
|
532
|
+
return props;
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
Object.defineProperty(DecoderImpl, "name", { value: "Decoder" });
|
|
536
|
+
// @__NO_SIDE_EFFECTS__
|
|
537
|
+
function define(fn) {
|
|
538
|
+
const decoder = new DecoderImpl(fn);
|
|
539
|
+
return stamp2(decoder);
|
|
462
540
|
}
|
|
463
541
|
var kDecoderRegistry = /* @__PURE__ */ Symbol.for("decoders.kDecoderRegistry");
|
|
464
542
|
var _stamped2 = globalThis[kDecoderRegistry] ??= /* @__PURE__ */ new WeakSet();
|
package/dist/index.d.cts
CHANGED
|
@@ -179,7 +179,7 @@ interface Decoder<T> {
|
|
|
179
179
|
/**
|
|
180
180
|
* The Standard Schema interface for this decoder.
|
|
181
181
|
*/
|
|
182
|
-
'~standard': StandardSchemaV1.Props<unknown, T>;
|
|
182
|
+
readonly '~standard': StandardSchemaV1.Props<unknown, T>;
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
185
|
* Helper type to return the output type of a Decoder.
|
|
@@ -673,9 +673,10 @@ declare function either<TDecoders extends readonly Decoder<unknown>[]>(...decode
|
|
|
673
673
|
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
674
674
|
* specified values.
|
|
675
675
|
*/
|
|
676
|
-
declare function oneOf<C extends Scalar>(constants: readonly C[]): Decoder<C>;
|
|
676
|
+
declare function oneOf<const C extends Scalar>(constants: readonly C[]): Decoder<C>;
|
|
677
677
|
/**
|
|
678
|
-
* Accepts and return an enum value.
|
|
678
|
+
* Accepts and return an enum value. Works with TypeScript enums, as well as
|
|
679
|
+
* with `as const` objects.
|
|
679
680
|
*/
|
|
680
681
|
declare function enum_<TEnum extends Record<string, string | number>>(enumObj: TEnum): Decoder<TEnum[keyof TEnum]>;
|
|
681
682
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -179,7 +179,7 @@ interface Decoder<T> {
|
|
|
179
179
|
/**
|
|
180
180
|
* The Standard Schema interface for this decoder.
|
|
181
181
|
*/
|
|
182
|
-
'~standard': StandardSchemaV1.Props<unknown, T>;
|
|
182
|
+
readonly '~standard': StandardSchemaV1.Props<unknown, T>;
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
185
|
* Helper type to return the output type of a Decoder.
|
|
@@ -673,9 +673,10 @@ declare function either<TDecoders extends readonly Decoder<unknown>[]>(...decode
|
|
|
673
673
|
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
674
674
|
* specified values.
|
|
675
675
|
*/
|
|
676
|
-
declare function oneOf<C extends Scalar>(constants: readonly C[]): Decoder<C>;
|
|
676
|
+
declare function oneOf<const C extends Scalar>(constants: readonly C[]): Decoder<C>;
|
|
677
677
|
/**
|
|
678
|
-
* Accepts and return an enum value.
|
|
678
|
+
* Accepts and return an enum value. Works with TypeScript enums, as well as
|
|
679
|
+
* with `as const` objects.
|
|
679
680
|
*/
|
|
680
681
|
declare function enum_<TEnum extends Record<string, string | number>>(enumObj: TEnum): Decoder<TEnum[keyof TEnum]>;
|
|
681
682
|
/**
|
package/dist/index.js
CHANGED
|
@@ -371,29 +371,60 @@ ${formatted}`);
|
|
|
371
371
|
return formatted;
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
374
|
+
var _standard = /* @__PURE__ */ new WeakMap();
|
|
375
|
+
var DecoderImpl = class {
|
|
376
|
+
/**
|
|
377
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
378
|
+
*
|
|
379
|
+
* Contrasted with `.verify()`, calls to `.decode()` will never fail and
|
|
380
|
+
* instead return a result type.
|
|
381
|
+
*/
|
|
382
|
+
decode;
|
|
383
|
+
/**
|
|
384
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
385
|
+
* When accepted, returns a value of type `T`. Otherwise fail with
|
|
386
|
+
* a runtime error.
|
|
387
|
+
*/
|
|
388
|
+
verify;
|
|
389
|
+
/**
|
|
390
|
+
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
391
|
+
* When accepted, returns the decoded `T` value directly. Otherwise returns
|
|
392
|
+
* `undefined`.
|
|
393
|
+
*
|
|
394
|
+
* Use this when you're not interested in programmatically handling the
|
|
395
|
+
* error message.
|
|
396
|
+
*/
|
|
397
|
+
value;
|
|
398
|
+
constructor(fn) {
|
|
399
|
+
const decode = (blob) => {
|
|
400
|
+
const makeFlexErr = (msg) => err(isAnnotation(msg) ? msg : public_annotate(blob, msg));
|
|
401
|
+
return fn(blob, ok, makeFlexErr);
|
|
402
|
+
};
|
|
403
|
+
const verify = (blob, formatter = formatInline) => {
|
|
404
|
+
const result = decode(blob);
|
|
405
|
+
if (result.ok) {
|
|
406
|
+
return result.value;
|
|
407
|
+
} else {
|
|
408
|
+
throw format(result.error, formatter);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const value = (blob) => decode(blob).value;
|
|
412
|
+
this.decode = decode;
|
|
413
|
+
this.verify = verify;
|
|
414
|
+
this.value = value;
|
|
390
415
|
}
|
|
391
|
-
|
|
392
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Accepts any value the given decoder accepts, and on success, will call
|
|
418
|
+
* the given function **on the decoded result**. If the transformation
|
|
419
|
+
* function throws an error, the whole decoder will fail using the error
|
|
420
|
+
* message as the failure reason.
|
|
421
|
+
*/
|
|
422
|
+
transform(transformFn) {
|
|
423
|
+
return this.chain(noThrow(transformFn));
|
|
393
424
|
}
|
|
394
|
-
|
|
395
|
-
return reject(
|
|
396
|
-
(
|
|
425
|
+
refine(predicateFn, errmsg) {
|
|
426
|
+
return this.reject(
|
|
427
|
+
(value) => predicateFn(value) ? (
|
|
397
428
|
// Don't reject
|
|
398
429
|
null
|
|
399
430
|
) : (
|
|
@@ -402,10 +433,25 @@ function define(fn) {
|
|
|
402
433
|
)
|
|
403
434
|
);
|
|
404
435
|
}
|
|
405
|
-
|
|
406
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Cast the return type of this read-only decoder to a narrower type. This is
|
|
438
|
+
* useful to return "branded" types. This method has no runtime effect.
|
|
439
|
+
*/
|
|
440
|
+
refineType() {
|
|
441
|
+
return this;
|
|
407
442
|
}
|
|
408
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Send the output of the current decoder into another decoder or acceptance
|
|
445
|
+
* function. The given acceptance function will receive the output of the
|
|
446
|
+
* current decoder as its input.
|
|
447
|
+
*
|
|
448
|
+
* > _**NOTE:** This is an advanced, low-level, API. It's not recommended
|
|
449
|
+
* > to reach for this construct unless there is no other way. Most cases can
|
|
450
|
+
* > be covered more elegantly by `.transform()`, `.refine()`, or `.pipe()`
|
|
451
|
+
* > instead._
|
|
452
|
+
*/
|
|
453
|
+
chain(next) {
|
|
454
|
+
const decode = this.decode;
|
|
409
455
|
return /* @__PURE__ */ define((blob, ok2, err2) => {
|
|
410
456
|
const r1 = decode(blob);
|
|
411
457
|
if (!r1.ok) return r1;
|
|
@@ -413,16 +459,46 @@ function define(fn) {
|
|
|
413
459
|
return /* @__PURE__ */ isDecoder(r2) ? r2.decode(r1.value) : r2;
|
|
414
460
|
});
|
|
415
461
|
}
|
|
416
|
-
|
|
417
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Send the output of this decoder as input to another decoder.
|
|
464
|
+
*
|
|
465
|
+
* This can be useful to validate the results of a transform, i.e.:
|
|
466
|
+
*
|
|
467
|
+
* string
|
|
468
|
+
* .transform((s) => s.split(','))
|
|
469
|
+
* .pipe(array(nonEmptyString))
|
|
470
|
+
*
|
|
471
|
+
* You can also conditionally pipe:
|
|
472
|
+
*
|
|
473
|
+
* string.pipe((s) => s.startsWith('@') ? username : email)
|
|
474
|
+
*/
|
|
475
|
+
pipe(next) {
|
|
476
|
+
return this.chain(next);
|
|
418
477
|
}
|
|
419
|
-
|
|
420
|
-
|
|
478
|
+
/**
|
|
479
|
+
* Adds an extra predicate to a decoder. The new decoder is like the
|
|
480
|
+
* original decoder, but only accepts values that aren't rejected by the
|
|
481
|
+
* given function.
|
|
482
|
+
*
|
|
483
|
+
* The given function can return `null` to accept the decoded value, or
|
|
484
|
+
* return a specific error message to reject.
|
|
485
|
+
*
|
|
486
|
+
* Unlike `.refine()`, you can use this function to return a dynamic error
|
|
487
|
+
* message.
|
|
488
|
+
*/
|
|
489
|
+
reject(rejectFn) {
|
|
490
|
+
return this.chain((blob, ok2, err2) => {
|
|
421
491
|
const errmsg = rejectFn(blob);
|
|
422
492
|
return errmsg === null ? ok2(blob) : err2(typeof errmsg === "string" ? public_annotate(blob, errmsg) : errmsg);
|
|
423
493
|
});
|
|
424
494
|
}
|
|
425
|
-
|
|
495
|
+
/**
|
|
496
|
+
* Uses the given decoder, but will use an alternative error message in
|
|
497
|
+
* case it rejects. This can be used to simplify or shorten otherwise
|
|
498
|
+
* long or low-level/technical errors.
|
|
499
|
+
*/
|
|
500
|
+
describe(message) {
|
|
501
|
+
const decode = this.decode;
|
|
426
502
|
return /* @__PURE__ */ define((blob, _, err2) => {
|
|
427
503
|
const result = decode(blob);
|
|
428
504
|
if (result.ok) {
|
|
@@ -432,18 +508,14 @@ function define(fn) {
|
|
|
432
508
|
}
|
|
433
509
|
});
|
|
434
510
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
describe,
|
|
444
|
-
chain,
|
|
445
|
-
pipe,
|
|
446
|
-
"~standard": {
|
|
511
|
+
/**
|
|
512
|
+
* The Standard Schema interface for this decoder.
|
|
513
|
+
*/
|
|
514
|
+
get "~standard"() {
|
|
515
|
+
const memo = _standard.get(this);
|
|
516
|
+
if (memo !== void 0) return memo;
|
|
517
|
+
const decode = this.decode;
|
|
518
|
+
const props = {
|
|
447
519
|
version: 1,
|
|
448
520
|
vendor: "decoders",
|
|
449
521
|
validate: (blob) => {
|
|
@@ -455,10 +527,16 @@ function define(fn) {
|
|
|
455
527
|
return { issues };
|
|
456
528
|
}
|
|
457
529
|
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
530
|
+
};
|
|
531
|
+
_standard.set(this, props);
|
|
532
|
+
return props;
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
Object.defineProperty(DecoderImpl, "name", { value: "Decoder" });
|
|
536
|
+
// @__NO_SIDE_EFFECTS__
|
|
537
|
+
function define(fn) {
|
|
538
|
+
const decoder = new DecoderImpl(fn);
|
|
539
|
+
return stamp2(decoder);
|
|
462
540
|
}
|
|
463
541
|
var kDecoderRegistry = /* @__PURE__ */ Symbol.for("decoders.kDecoderRegistry");
|
|
464
542
|
var _stamped2 = globalThis[kDecoderRegistry] ??= /* @__PURE__ */ new WeakSet();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "decoders",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "Elegant and battle-tested validation library for type-safe input data for TypeScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -66,11 +66,11 @@
|
|
|
66
66
|
"@release-it/keep-a-changelog": "^8.0.1",
|
|
67
67
|
"@standard-schema/spec": "^1.1.0",
|
|
68
68
|
"@vitest/coverage-istanbul": "^4.1.11",
|
|
69
|
-
"fast-check": "^4.10.
|
|
69
|
+
"fast-check": "^4.10.2",
|
|
70
70
|
"itertools": "^2.7.1",
|
|
71
71
|
"oxlint": "^1.83.0",
|
|
72
72
|
"pkg-pr-new": "^0.0.88",
|
|
73
|
-
"prettier": "^3.9.
|
|
73
|
+
"prettier": "^3.9.9",
|
|
74
74
|
"publint": "^0.3.24",
|
|
75
75
|
"release-it": "^21.0.3",
|
|
76
76
|
"ts-morph": "^28.0.0",
|