decoders 2.9.1-pre.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/decoders.svg)](https://www.npmjs.com/package/decoders)
4
4
  [![Test Status](https://github.com/nvie/decoders/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/nvie/decoders/actions)
5
- [![Bundle size for decoders](https://pkg-size.dev/badge/bundle/4200)](https://pkg-size.dev/decoders)
5
+ [![Bundle size](https://deno.bundlejs.com/badge?q=decoders@2.9.0&treeshake=[{number,object,optional,string}])](https://bundlejs.com/?q=decoders%402.9.0&treeshake=%5B%7B+number%2Cobject%2Coptional%2Cstring+%7D%5D)
6
6
 
7
7
  Elegant and battle-tested validation library for type-safe input data for TypeScript.
8
8
 
9
9
  ## Basic example
10
10
 
11
11
  ```typescript
12
- import { array, iso8601, number, object, optional, string } from 'decoders';
12
+ import { array, isoDate, number, object, optional, string } from 'decoders';
13
13
 
14
14
  // Incoming data at runtime, e.g. the request body
15
15
  // The point is that this data is untrusted and its type unknown
@@ -24,7 +24,7 @@ const externalData = {
24
24
  const userDecoder = object({
25
25
  id: number,
26
26
  name: string,
27
- createdAt: optional(iso8601),
27
+ createdAt: optional(isoDate),
28
28
  tags: array(string),
29
29
  });
30
30
 
package/dist/index.cjs CHANGED
@@ -1,19 +1,29 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/lib/utils.ts
2
+ // @__NO_SIDE_EFFECTS__
3
+ function qty(n, unit) {
4
+ return n === 1 ? `${n} ${unit}` : `${n} ${unit}s`;
5
+ }
6
+ // @__NO_SIDE_EFFECTS__
2
7
  function isNumber(value) {
3
8
  return typeof value === "number";
4
9
  }
10
+ // @__NO_SIDE_EFFECTS__
5
11
  function isString(value) {
6
12
  return typeof value === "string";
7
13
  }
14
+ // @__NO_SIDE_EFFECTS__
8
15
  function isBigInt(value) {
9
16
  return typeof value === "bigint";
10
17
  }
18
+ // @__NO_SIDE_EFFECTS__
11
19
  function isDate(value) {
12
20
  return !!value && Object.prototype.toString.call(value) === "[object Date]" && !isNaN(value);
13
21
  }
22
+ // @__NO_SIDE_EFFECTS__
14
23
  function isPromiseLike(value) {
15
24
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
16
25
  }
26
+ // @__NO_SIDE_EFFECTS__
17
27
  function isPlainObject(value) {
18
28
  return value !== null && typeof value === "object" && // This still seems to be the only reliable way to determine whether
19
29
  // something is a pojo... ¯\_(ツ)_/¯
@@ -112,36 +122,40 @@ function public_annotateObject(obj, text) {
112
122
 
113
123
  // src/lib/text.ts
114
124
  var INDENT = " ";
125
+ // @__NO_SIDE_EFFECTS__
115
126
  function isMultiline(s) {
116
127
  return s.includes("\n");
117
128
  }
129
+ // @__NO_SIDE_EFFECTS__
118
130
  function indent(s, prefix = INDENT) {
119
- if (isMultiline(s)) {
131
+ if (/* @__PURE__ */ isMultiline(s)) {
120
132
  return s.split("\n").map((line) => `${prefix}${line}`).join("\n");
121
133
  } else {
122
134
  return `${prefix}${s}`;
123
135
  }
124
136
  }
125
137
  var quotePattern = /'/g;
138
+ // @__NO_SIDE_EFFECTS__
126
139
  function quote(value) {
127
140
  return typeof value === "string" ? "'" + value.replace(quotePattern, "\\'") + "'" : value === void 0 ? "undefined" : JSON.stringify(value);
128
141
  }
129
142
 
130
143
  // src/core/format.ts
144
+ // @__NO_SIDE_EFFECTS__
131
145
  function summarize(ann, keypath = []) {
132
146
  const result = [];
133
147
  if (ann.type === "array") {
134
148
  const items = ann.items;
135
149
  let index = 0;
136
150
  for (const ann2 of items) {
137
- for (const item of summarize(ann2, [...keypath, index++])) {
151
+ for (const item of /* @__PURE__ */ summarize(ann2, [...keypath, index++])) {
138
152
  result.push(item);
139
153
  }
140
154
  }
141
155
  } else if (ann.type === "object") {
142
156
  const fields = ann.fields;
143
157
  for (const [key, value] of fields) {
144
- for (const item of summarize(value, [...keypath, key])) {
158
+ for (const item of /* @__PURE__ */ summarize(value, [...keypath, key])) {
145
159
  result.push(item);
146
160
  }
147
161
  }
@@ -253,7 +267,7 @@ ${annotation}`;
253
267
  }
254
268
  }
255
269
  function formatShort(ann) {
256
- return summarize(ann, []).join("\n");
270
+ return (/* @__PURE__ */ summarize(ann, [])).join("\n");
257
271
  }
258
272
  function* iterAnnotation(ann, stack) {
259
273
  if (ann.text) {
@@ -292,9 +306,11 @@ function formatAsIssues(ann) {
292
306
  }
293
307
 
294
308
  // src/core/Result.ts
309
+ // @__NO_SIDE_EFFECTS__
295
310
  function ok(value) {
296
311
  return { ok: true, value, error: void 0 };
297
312
  }
313
+ // @__NO_SIDE_EFFECTS__
298
314
  function err(error) {
299
315
  return { ok: false, value: void 0, error };
300
316
  }
@@ -321,6 +337,7 @@ ${formatted}`);
321
337
  return formatted;
322
338
  }
323
339
  }
340
+ // @__NO_SIDE_EFFECTS__
324
341
  function define(fn) {
325
342
  function decode(blob) {
326
343
  const makeFlexErr = (msg) => err(isAnnotation(msg) ? msg : public_annotate(blob, msg));
@@ -355,11 +372,11 @@ function define(fn) {
355
372
  return self;
356
373
  }
357
374
  function chain(next) {
358
- return define((blob, ok2, err2) => {
375
+ return /* @__PURE__ */ define((blob, ok2, err2) => {
359
376
  const r1 = decode(blob);
360
377
  if (!r1.ok) return r1;
361
- const r2 = isDecoder(next) ? next : next(r1.value, ok2, err2);
362
- return isDecoder(r2) ? r2.decode(r1.value) : r2;
378
+ const r2 = /* @__PURE__ */ isDecoder(next) ? next : next(r1.value, ok2, err2);
379
+ return /* @__PURE__ */ isDecoder(r2) ? r2.decode(r1.value) : r2;
363
380
  });
364
381
  }
365
382
  function pipe(next) {
@@ -372,7 +389,7 @@ function define(fn) {
372
389
  });
373
390
  }
374
391
  function describe(message) {
375
- return define((blob, _, err2) => {
392
+ return /* @__PURE__ */ define((blob, _, err2) => {
376
393
  const result = decode(blob);
377
394
  if (result.ok) {
378
395
  return result;
@@ -415,6 +432,7 @@ function brand2(decoder) {
415
432
  _register2.add(decoder);
416
433
  return decoder;
417
434
  }
435
+ // @__NO_SIDE_EFFECTS__
418
436
  function isDecoder(value) {
419
437
  return _register2.has(value);
420
438
  }
@@ -426,6 +444,7 @@ var poja = define((blob, ok2, err2) => {
426
444
  }
427
445
  return ok2(blob);
428
446
  });
447
+ // @__NO_SIDE_EFFECTS__
429
448
  function array(decoder) {
430
449
  const decodeFn = decoder.decode;
431
450
  return poja.chain((inputs, ok2, err2) => {
@@ -453,12 +472,14 @@ function array(decoder) {
453
472
  function isNonEmpty(arr) {
454
473
  return arr.length > 0;
455
474
  }
475
+ // @__NO_SIDE_EFFECTS__
456
476
  function nonEmptyArray(decoder) {
457
- return array(decoder).refine(isNonEmpty, "Must be non-empty array");
477
+ return (/* @__PURE__ */ array(decoder)).refine(isNonEmpty, "Must have at least 1 item");
458
478
  }
459
- var ntuple = (n) => poja.refine((arr) => arr.length === n, `Must be a ${n}-tuple`);
479
+ var ntuple = /* @__NO_SIDE_EFFECTS__ */ (n) => poja.refine((arr) => arr.length === n, `Must be a ${n}-tuple`);
480
+ // @__NO_SIDE_EFFECTS__
460
481
  function tuple(...decoders) {
461
- return ntuple(decoders.length).chain((blobs, ok2, err2) => {
482
+ return (/* @__PURE__ */ ntuple(decoders.length)).chain((blobs, ok2, err2) => {
462
483
  let allOk = true;
463
484
  const rvs = decoders.map((decoder, i) => {
464
485
  const blob = blobs[i];
@@ -478,7 +499,32 @@ function tuple(...decoders) {
478
499
  });
479
500
  }
480
501
 
502
+ // src/lib/size-options.ts
503
+ // @__NO_SIDE_EFFECTS__
504
+ function bySizeOptions(options) {
505
+ const size = options.size;
506
+ const min2 = _nullishCoalesce(size, () => ( options.min));
507
+ const max2 = _nullishCoalesce(size, () => ( options.max));
508
+ const atLeast = min2 === max2 ? "" : "at least ";
509
+ const atMost = min2 === max2 ? "" : "at most ";
510
+ return (value) => {
511
+ const len = _nullishCoalesce(value.length, () => ( value.size));
512
+ if (typeof value === "string") {
513
+ if (min2 !== void 0 && len < min2)
514
+ return `Too short, must be ${atLeast}${qty(min2, "char")}`;
515
+ if (max2 !== void 0 && len > max2)
516
+ return `Too long, must be ${atMost}${qty(max2, "char")}`;
517
+ } else {
518
+ if (min2 !== void 0 && len < min2)
519
+ return `Must have ${atLeast}${qty(min2, "item")}`;
520
+ if (max2 !== void 0 && len > max2) return `Must have ${atMost}${qty(max2, "item")}`;
521
+ }
522
+ return null;
523
+ };
524
+ }
525
+
481
526
  // src/misc.ts
527
+ // @__NO_SIDE_EFFECTS__
482
528
  function instanceOf(klass) {
483
529
  return define(
484
530
  (blob, ok2, err2) => (
@@ -487,9 +533,15 @@ function instanceOf(klass) {
487
533
  )
488
534
  );
489
535
  }
536
+ // @__NO_SIDE_EFFECTS__
490
537
  function lazy(decoderFn) {
491
538
  return define((blob) => decoderFn().decode(blob));
492
539
  }
540
+ // @__NO_SIDE_EFFECTS__
541
+ function sized(decoder, options) {
542
+ return decoder.reject(bySizeOptions(options));
543
+ }
544
+ // @__NO_SIDE_EFFECTS__
493
545
  function prep(mapperFn, decoder) {
494
546
  return define((originalInput, _, err2) => {
495
547
  let blob;
@@ -510,6 +562,7 @@ function prep(mapperFn, decoder) {
510
562
  }
511
563
 
512
564
  // src/lib/set-methods.ts
565
+ // @__NO_SIDE_EFFECTS__
513
566
  function difference(xs, ys) {
514
567
  const result = /* @__PURE__ */ new Set();
515
568
  for (const x of xs) {
@@ -524,6 +577,7 @@ function difference(xs, ys) {
524
577
  var pojo = define(
525
578
  (blob, ok2, err2) => isPlainObject(blob) ? ok2(blob) : err2("Must be an object")
526
579
  );
580
+ // @__NO_SIDE_EFFECTS__
527
581
  function object(decoders) {
528
582
  const knownKeys = new Set(Object.keys(decoders));
529
583
  return pojo.chain((plainObj, ok2, err2) => {
@@ -566,6 +620,7 @@ function object(decoders) {
566
620
  return ok2(record2);
567
621
  });
568
622
  }
623
+ // @__NO_SIDE_EFFECTS__
569
624
  function exact(decoders) {
570
625
  const allowedKeys = new Set(Object.keys(decoders));
571
626
  const checked = pojo.reject((plainObj) => {
@@ -573,12 +628,13 @@ function exact(decoders) {
573
628
  const extraKeys = difference(actualKeys, allowedKeys);
574
629
  return extraKeys.size > 0 ? `Unexpected extra keys: ${Array.from(extraKeys).map(quote).join(", ")}` : null;
575
630
  });
576
- return checked.pipe(object(decoders));
631
+ return checked.pipe(/* @__PURE__ */ object(decoders));
577
632
  }
633
+ // @__NO_SIDE_EFFECTS__
578
634
  function inexact(decoders) {
579
635
  return pojo.pipe((plainObj) => {
580
636
  const allkeys = new Set(Object.keys(plainObj));
581
- return object(decoders).transform((safepart) => {
637
+ return (/* @__PURE__ */ object(decoders)).transform((safepart) => {
582
638
  const safekeys = new Set(Object.keys(decoders));
583
639
  for (const k of safekeys) allkeys.add(k);
584
640
  const rv = {};
@@ -605,6 +661,7 @@ function itemize(s) {
605
661
  function nest(errText) {
606
662
  return errText.startsWith(EITHER_PREFIX) ? errText.substring(EITHER_PREFIX.length) : itemize(errText);
607
663
  }
664
+ // @__NO_SIDE_EFFECTS__
608
665
  function either(...decoders) {
609
666
  if (decoders.length === 0) {
610
667
  throw new Error("Pass at least one decoder to either()");
@@ -623,6 +680,7 @@ function either(...decoders) {
623
680
  return err2(text);
624
681
  });
625
682
  }
683
+ // @__NO_SIDE_EFFECTS__
626
684
  function oneOf(constants) {
627
685
  return define((blob, ok2, err2) => {
628
686
  const index = constants.indexOf(blob);
@@ -632,28 +690,31 @@ function oneOf(constants) {
632
690
  return err2(`Must be one of ${constants.map((value) => quote(value)).join(", ")}`);
633
691
  });
634
692
  }
693
+ // @__NO_SIDE_EFFECTS__
635
694
  function enum_(enumObj) {
636
695
  const values = Object.values(enumObj);
637
696
  if (!values.some(isNumber)) {
638
- return oneOf(values);
697
+ return /* @__PURE__ */ oneOf(values);
639
698
  } else {
640
699
  const nums = values.filter(isNumber);
641
700
  const ignore = new Set(nums.map((val) => enumObj[val]));
642
701
  const strings = values.filter(isString).filter((val) => !ignore.has(val));
643
- return oneOf([...nums, ...strings]);
702
+ return /* @__PURE__ */ oneOf([...nums, ...strings]);
644
703
  }
645
704
  }
705
+ // @__NO_SIDE_EFFECTS__
646
706
  function taggedUnion(field, mapping2) {
647
707
  const scout = object({
648
- [field]: prep(String, oneOf(Object.keys(mapping2)))
708
+ [field]: prep(String, /* @__PURE__ */ oneOf(Object.keys(mapping2)))
649
709
  }).transform((o) => o[field]);
650
- return select(
710
+ return /* @__PURE__ */ select(
651
711
  scout,
652
712
  // peek...
653
713
  (key) => mapping2[key]
654
714
  // ...then select
655
715
  );
656
716
  }
717
+ // @__NO_SIDE_EFFECTS__
657
718
  function select(scout, selectFn) {
658
719
  return define((blob) => {
659
720
  const result = scout.decode(blob);
@@ -665,36 +726,42 @@ function select(scout, selectFn) {
665
726
  function lazyval(value) {
666
727
  return typeof value === "function" ? value() : value;
667
728
  }
668
- var null_ = constant(null);
669
- var undefined_ = constant(void 0);
729
+ var null_ = /* @__PURE__ */ constant(null);
730
+ var undefined_ = /* @__PURE__ */ constant(void 0);
670
731
  var nullish_ = define(
671
732
  (blob, ok2, err2) => (
672
733
  // Equiv to either(undefined_, null_), but combined for better error message
673
734
  blob == null ? ok2(blob) : err2("Must be undefined or null")
674
735
  )
675
736
  );
737
+ // @__NO_SIDE_EFFECTS__
676
738
  function optional(decoder, defaultValue) {
677
739
  const rv = either(undefined_, decoder);
678
740
  return arguments.length >= 2 ? rv.transform((value) => _nullishCoalesce(value, () => ( lazyval(defaultValue)))) : rv;
679
741
  }
742
+ // @__NO_SIDE_EFFECTS__
680
743
  function nullable(decoder, defaultValue) {
681
744
  const rv = either(null_, decoder);
682
745
  return arguments.length >= 2 ? rv.transform((value) => _nullishCoalesce(value, () => ( lazyval(defaultValue)))) : rv;
683
746
  }
747
+ // @__NO_SIDE_EFFECTS__
684
748
  function nullish(decoder, defaultValue) {
685
749
  const rv = either(nullish_, decoder);
686
750
  return arguments.length >= 2 ? rv.transform((value) => _nullishCoalesce(value, () => ( lazyval(defaultValue)))) : rv;
687
751
  }
752
+ // @__NO_SIDE_EFFECTS__
688
753
  function constant(value) {
689
754
  return define(
690
755
  (blob, ok2, err2) => blob === value ? ok2(value) : err2(`Must be ${typeof value === "symbol" ? String(value) : quote(value)}`)
691
756
  );
692
757
  }
758
+ // @__NO_SIDE_EFFECTS__
693
759
  function always(value) {
694
760
  return define(
695
761
  typeof value === "function" ? (_, ok2) => ok2(value()) : (_, ok2) => ok2(value)
696
762
  );
697
763
  }
764
+ // @__NO_SIDE_EFFECTS__
698
765
  function never(msg) {
699
766
  return define((_, __, err2) => err2(msg));
700
767
  }
@@ -709,6 +776,7 @@ var boolean = define((blob, ok2, err2) => {
709
776
  var truthy = define((blob, ok2, _) => ok2(!!blob));
710
777
 
711
778
  // src/collections.ts
779
+ // @__NO_SIDE_EFFECTS__
712
780
  function record(fst, snd) {
713
781
  const keyDecoder = snd !== void 0 ? fst : void 0;
714
782
  const valueDecoder = _nullishCoalesce(snd, () => ( fst));
@@ -741,23 +809,13 @@ function record(fst, snd) {
741
809
  }
742
810
  });
743
811
  }
812
+ // @__NO_SIDE_EFFECTS__
744
813
  function setFromArray(decoder) {
745
814
  return array(decoder).transform((items) => new Set(items));
746
815
  }
816
+ // @__NO_SIDE_EFFECTS__
747
817
  function mapping(decoder) {
748
- return record(decoder).transform((obj) => new Map(Object.entries(obj)));
749
- }
750
-
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;
818
+ return (/* @__PURE__ */ record(decoder)).transform((obj) => new Map(Object.entries(obj)));
761
819
  }
762
820
 
763
821
  // src/strings.ts
@@ -765,98 +823,127 @@ var url_re = /^([A-Za-z]{2,12}(?:[+][A-Za-z]{2,12})?):\/\/(?:([^@:]*:?(?:[^@]+)?
765
823
  var string = define(
766
824
  (blob, ok2, err2) => isString(blob) ? ok2(blob) : err2("Must be string")
767
825
  );
768
- var nonEmptyString = regex(/\S/, "Must be non-empty string");
826
+ var nonEmptyString = /* @__PURE__ */ regex(/\S/, "Must be non-empty string");
827
+ // @__NO_SIDE_EFFECTS__
769
828
  function regex(regex2, msg) {
770
829
  return string.refine((s) => regex2.test(s), msg);
771
830
  }
831
+ // @__NO_SIDE_EFFECTS__
772
832
  function startsWith(prefix) {
773
833
  return string.refine(
774
834
  (s) => s.startsWith(prefix),
775
835
  `Must start with '${prefix}'`
776
836
  );
777
837
  }
838
+ // @__NO_SIDE_EFFECTS__
778
839
  function endsWith(suffix) {
779
840
  return string.refine(
780
841
  (s) => s.endsWith(suffix),
781
842
  `Must end with '${suffix}'`
782
843
  );
783
844
  }
784
- var email = regex(
845
+ var email = /* @__PURE__ */ regex(
785
846
  // The almost perfect email regex, taken from https://emailregex.com/
786
847
  /^(([^<>()[\]\\.,;:\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
848
  "Must be email"
788
849
  );
789
- var url = either(
790
- regex(url_re, "Must be URL").transform((value) => new URL(value)),
791
- instanceOf(URL)
850
+ var urlString = /* @__PURE__ */ regex(url_re, "Must be URL");
851
+ var url = select(
852
+ unknown,
853
+ (blob) => typeof blob === "string" ? /* @__PURE__ */ urlString.transform((s) => new URL(s)) : /* @__PURE__ */ instanceOf(URL).describe("Must be URL")
792
854
  );
793
- var httpsUrl = url.refine(
855
+ var httpsUrl = /* @__PURE__ */ url.refine(
794
856
  (value) => value.protocol === "https:",
795
- "Must be an HTTPS URL"
857
+ "Must be HTTPS URL"
796
858
  );
797
- var identifier = regex(
859
+ var identifier = /* @__PURE__ */ regex(
798
860
  /^[a-z_][a-z0-9_]*$/i,
799
861
  "Must be valid identifier"
800
862
  );
863
+ // @__NO_SIDE_EFFECTS__
801
864
  function nanoid(options) {
802
- return regex(/^[a-z0-9_-]+$/i, "Must be nano ID").reject(
803
- bySizeOptions(_nullishCoalesce(options, () => ( { size: 21 })))
804
- );
865
+ return sized(/* @__PURE__ */ regex(/^[a-z0-9_-]+$/i, "Must be nano ID"), _nullishCoalesce(options, () => ( { size: 21 })));
805
866
  }
806
- var uuid = regex(
867
+ var uuid = /* @__PURE__ */ regex(
807
868
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
808
869
  "Must be uuid"
809
870
  );
810
871
  var uuidv1 = (
811
872
  // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)
812
- uuid.refine((value) => value[14] === "1", "Must be uuidv1")
873
+ /* @__PURE__ */ uuid.refine((value) => value[14] === "1", "Must be uuidv1")
813
874
  );
814
875
  var uuidv4 = (
815
876
  // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
816
- uuid.refine((value) => value[14] === "4", "Must be uuidv4")
877
+ /* @__PURE__ */ uuid.refine((value) => value[14] === "4", "Must be uuidv4")
817
878
  );
818
- var decimal = regex(/^[0-9]+$/, "Must only contain digits");
819
- var hexadecimal = regex(
879
+ var decimal = /* @__PURE__ */ regex(/^[0-9]+$/, "Must only contain digits");
880
+ var hexadecimal = /* @__PURE__ */ regex(
820
881
  /^[0-9a-f]+$/i,
821
882
  "Must only contain hexadecimal digits"
822
883
  );
823
- var numeric = decimal.transform(Number);
884
+ var numeric = /* @__PURE__ */ decimal.transform(Number);
824
885
 
825
886
  // src/dates.ts
826
887
  var iso8601_re = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[.]\d+)?(?:Z|[+-]\d{2}:?\d{2})$/;
827
888
  var date = define((blob, ok2, err2) => {
828
889
  return isDate(blob) ? ok2(blob) : err2("Must be a Date");
829
890
  });
830
- var dateString = regex(
891
+ var isoDateString = /* @__PURE__ */ regex(
831
892
  iso8601_re,
832
893
  "Must be ISO8601 format"
833
894
  ).refine(
834
895
  (value) => !Number.isNaN(new Date(value).getTime()),
835
896
  "Must be valid date/time value"
836
897
  );
837
- var iso8601 = dateString.transform((value) => new Date(value));
838
- var datelike = either(date, iso8601).describe("Must be a Date or date string");
898
+ var isoDate = /* @__PURE__ */ isoDateString.transform(
899
+ (value) => new Date(value)
900
+ );
901
+ var flexDate = select(
902
+ unknown,
903
+ (blob) => typeof blob === "string" ? isoDate : isDate(blob) ? date : never("Must be a Date or date string")
904
+ );
905
+ var dateString = isoDateString;
906
+ var iso8601 = isoDate;
907
+ var datelike = flexDate;
839
908
 
840
909
  // src/numbers.ts
841
910
  var anyNumber = define(
842
911
  (blob, ok2, err2) => isNumber(blob) ? ok2(blob) : err2("Must be number")
843
912
  );
844
- var number = anyNumber.refine(
913
+ var number = /* @__PURE__ */ anyNumber.refine(
845
914
  (n) => Number.isFinite(n),
846
915
  "Number must be finite"
847
916
  );
848
- var integer = number.refine(
917
+ var integer = /* @__PURE__ */ number.refine(
849
918
  (n) => Number.isInteger(n),
850
919
  "Number must be an integer"
851
920
  );
852
- var positiveNumber = number.refine(
921
+ var positiveNumber = /* @__PURE__ */ number.refine(
853
922
  (n) => n >= 0 && !Object.is(n, -0),
854
923
  "Number must be positive"
855
924
  );
856
- var positiveInteger = integer.refine(
925
+ var positiveInteger = /* @__PURE__ */ integer.refine(
857
926
  (n) => n >= 0 && !Object.is(n, -0),
858
927
  "Number must be positive"
859
928
  );
929
+ // @__NO_SIDE_EFFECTS__
930
+ function min(min2, decoder = number) {
931
+ return decoder.reject(
932
+ (value) => value < min2 ? `Too low, must be at least ${min2}` : null
933
+ );
934
+ }
935
+ // @__NO_SIDE_EFFECTS__
936
+ function max(max2, decoder = number) {
937
+ return decoder.reject(
938
+ (value) => value > max2 ? `Too high, must be at most ${max2}` : null
939
+ );
940
+ }
941
+ // @__NO_SIDE_EFFECTS__
942
+ function between(min2, max2, decoder = number) {
943
+ return decoder.reject(
944
+ (value) => value < min2 ? `Too low, must be between ${min2} and ${max2}` : value > max2 ? `Too high, must be between ${min2} and ${max2}` : null
945
+ );
946
+ }
860
947
  var bigint = define(
861
948
  (blob, ok2, err2) => isBigInt(blob) ? ok2(blob) : err2("Must be bigint")
862
949
  );
@@ -864,7 +951,7 @@ var bigint = define(
864
951
  // src/json.ts
865
952
  var jsonObject = lazy(() => record(json));
866
953
  var jsonArray = lazy(() => array(json));
867
- var json = either(
954
+ var json = /* @__PURE__ */ either(
868
955
  null_,
869
956
  string,
870
957
  number,
@@ -944,5 +1031,13 @@ var json = either(
944
1031
 
945
1032
 
946
1033
 
947
- exports._annotate = public_annotate; exports.always = always; exports.anyNumber = anyNumber; exports.anything = anything; exports.array = array; 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.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.startsWith = startsWith; exports.string = string; exports.taggedUnion = taggedUnion; exports.truthy = truthy; exports.tuple = tuple; exports.undefined_ = undefined_; exports.unknown = unknown; exports.url = url; exports.uuid = uuid; exports.uuidv1 = uuidv1; exports.uuidv4 = uuidv4;
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+ 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.flexDate = flexDate; 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.isoDate = isoDate; exports.isoDateString = isoDateString; 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
1043
  // istanbul ignore else -- @preserve