nalloc 0.0.1 → 0.0.3

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.
Files changed (64) hide show
  1. package/README.md +124 -38
  2. package/build/index.cjs +12 -68
  3. package/build/index.cjs.map +1 -1
  4. package/build/index.d.ts +1 -4
  5. package/build/index.js +1 -3
  6. package/build/index.js.map +1 -1
  7. package/build/iter.cjs +105 -0
  8. package/build/iter.cjs.map +1 -0
  9. package/build/iter.d.ts +61 -0
  10. package/build/iter.js +78 -0
  11. package/build/iter.js.map +1 -0
  12. package/build/option.cjs +22 -7
  13. package/build/option.cjs.map +1 -1
  14. package/build/option.d.ts +22 -1
  15. package/build/option.js +17 -8
  16. package/build/option.js.map +1 -1
  17. package/build/result.cjs +137 -48
  18. package/build/result.cjs.map +1 -1
  19. package/build/result.d.ts +91 -50
  20. package/build/result.js +112 -35
  21. package/build/result.js.map +1 -1
  22. package/build/safe.cjs +34 -15
  23. package/build/safe.cjs.map +1 -1
  24. package/build/safe.d.ts +4 -27
  25. package/build/safe.js +3 -14
  26. package/build/safe.js.map +1 -1
  27. package/build/types.cjs +38 -7
  28. package/build/types.cjs.map +1 -1
  29. package/build/types.d.ts +26 -4
  30. package/build/types.js +23 -7
  31. package/build/types.js.map +1 -1
  32. package/build/unsafe.cjs +14 -61
  33. package/build/unsafe.cjs.map +1 -1
  34. package/build/unsafe.d.ts +2 -27
  35. package/build/unsafe.js +2 -9
  36. package/build/unsafe.js.map +1 -1
  37. package/package.json +13 -16
  38. package/src/__tests__/index.ts +42 -0
  39. package/src/__tests__/iter.ts +218 -0
  40. package/src/__tests__/option.ts +48 -19
  41. package/src/__tests__/result.ts +322 -91
  42. package/src/__tests__/result.types.ts +3 -22
  43. package/src/__tests__/safe.ts +9 -15
  44. package/src/__tests__/unsafe.ts +11 -12
  45. package/src/index.ts +1 -18
  46. package/src/iter.ts +129 -0
  47. package/src/option.ts +39 -9
  48. package/src/result.ts +236 -106
  49. package/src/safe.ts +5 -42
  50. package/src/types.ts +52 -14
  51. package/src/unsafe.ts +2 -47
  52. package/build/devtools.cjs +0 -79
  53. package/build/devtools.cjs.map +0 -1
  54. package/build/devtools.d.ts +0 -82
  55. package/build/devtools.js +0 -43
  56. package/build/devtools.js.map +0 -1
  57. package/build/testing.cjs +0 -111
  58. package/build/testing.cjs.map +0 -1
  59. package/build/testing.d.ts +0 -85
  60. package/build/testing.js +0 -81
  61. package/build/testing.js.map +0 -1
  62. package/src/__tests__/tooling.ts +0 -86
  63. package/src/devtools.ts +0 -97
  64. package/src/testing.ts +0 -159
@@ -1,7 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import {
3
3
  of,
4
- ofAsync,
5
4
  isSomeErr,
6
5
  map,
7
6
  mapErr,
@@ -34,20 +33,22 @@ import {
34
33
  isOkAnd,
35
34
  isErrAnd,
36
35
  tryCatch,
37
- tryAsync,
38
- fromPromise,
39
- mapAsync,
40
- andThenAsync,
41
- matchAsync,
42
36
  unwrapOrReturn,
43
37
  assertOk,
44
38
  assertErr,
45
39
  all,
46
40
  any,
47
- partitionAsync
41
+ partitionAsync,
42
+ tryCatchMaybePromise,
43
+ settleMaybePromise,
44
+ partitionMaybePromise,
45
+ filterOk,
46
+ filterErr,
47
+ safeTry,
48
+ safeTryAsync,
49
+ fromPromise
48
50
  } from '../result.js';
49
51
  import { ok, err, isOk, isErr, optionOf as optOf, none } from '../types.js';
50
- import { formatResult, inspectResult } from '../devtools.js';
51
52
 
52
53
  describe('Result', () => {
53
54
  describe('constructors', () => {
@@ -57,10 +58,9 @@ describe('Result', () => {
57
58
  expect(result).toBe(42);
58
59
  });
59
60
 
60
- it('ok does not throw when passed an Err', () => {
61
+ it('ok throws when passed an Err', () => {
61
62
  const error = err('test error');
62
- expect(() => ok(error)).not.toThrow();
63
- expect(isErr(ok(error))).toBe(true);
63
+ expect(() => ok(error)).toThrow('ok() cannot wrap an Err value');
64
64
  });
65
65
 
66
66
  it('err creates Err result', () => {
@@ -81,17 +81,6 @@ describe('Result', () => {
81
81
  expect((failure as any).error.message).toBe('failed');
82
82
  });
83
83
 
84
- it('ofAsync catches async errors', async () => {
85
- const success = await ofAsync(async () => 42);
86
- expect(isOk(success)).toBe(true);
87
- expect(unwrap(success)).toBe(42);
88
-
89
- const failure = await ofAsync(async () => {
90
- throw new Error('async failed');
91
- });
92
- expect(isErr(failure)).toBe(true);
93
- expect((failure as any).error.message).toBe('async failed');
94
- });
95
84
  });
96
85
 
97
86
  describe('type guards', () => {
@@ -249,8 +238,11 @@ describe('Result', () => {
249
238
  expect(unwrap(ok(42))).toBe(42);
250
239
  });
251
240
 
252
- it('throws for Err', () => {
253
- expect(() => unwrap(err('error'))).toThrow('Called unwrap on Err: error');
241
+ it('throws error value for Err', () => {
242
+ const e = err('error');
243
+ let caught: unknown;
244
+ try { unwrap(e); } catch (x) { caught = x; }
245
+ expect(caught).toBe('error');
254
246
  });
255
247
  });
256
248
 
@@ -430,6 +422,12 @@ describe('Result', () => {
430
422
  expect(isErr(result)).toBe(true);
431
423
  expect((result as any).error).toBe('first');
432
424
  });
425
+
426
+ it('returns second Err when first is Ok', () => {
427
+ const result = zip(ok(1), err('second'));
428
+ expect(isErr(result)).toBe(true);
429
+ expect((result as any).error).toBe('second');
430
+ });
433
431
  });
434
432
 
435
433
  describe('zipWith', () => {
@@ -443,6 +441,12 @@ describe('Result', () => {
443
441
  expect(isErr(result)).toBe(true);
444
442
  expect((result as any).error).toBe('fail');
445
443
  });
444
+
445
+ it('returns Err from right when left is Ok', () => {
446
+ const result = zipWith(ok(2), err('right'), (a, b) => a + b);
447
+ expect(isErr(result)).toBe(true);
448
+ expect((result as any).error).toBe('right');
449
+ });
446
450
  });
447
451
 
448
452
  describe('flatten', () => {
@@ -594,70 +598,14 @@ describe('Result', () => {
594
598
  expect((result as any).error).toBe('boom');
595
599
  });
596
600
 
597
- it('tryAsync maps async rejection', async () => {
598
- const result = await tryAsync<number, string>(
599
- async () => {
600
- throw new Error('boom');
601
- },
602
- error => (error as Error).message,
603
- );
604
- expect(isErr(result)).toBe(true);
605
- expect((result as any).error).toBe('boom');
606
- });
607
-
608
- it('fromPromise resolves to Ok', async () => {
609
- const result = await fromPromise(Promise.resolve(5));
610
- expect(isOk(result)).toBe(true);
611
- expect(unwrap(result)).toBe(5);
612
- });
613
-
614
- it('fromPromise maps rejection', async () => {
615
- const result = await fromPromise(
616
- Promise.reject(new Error('fail')),
617
- error => (error as Error).message.toUpperCase(),
618
- );
619
- expect(isErr(result)).toBe(true);
620
- expect((result as any).error).toBe('FAIL');
621
- });
622
601
  });
623
602
 
624
- describe('async mapping', () => {
625
- it('mapAsync maps Ok value', async () => {
626
- const result = await mapAsync(ok(2), async value => value * 3);
627
- expect(isOk(result)).toBe(true);
628
- expect(unwrap(result)).toBe(6);
629
- });
630
-
631
- it('mapAsync returns Err unchanged', async () => {
632
- const result = await mapAsync(err('nope'), async (value: number) => value * 3);
633
- expect(isErr(result)).toBe(true);
634
- expect((result as any).error).toBe('nope');
635
- });
636
-
637
- it('andThenAsync chains Ok value', async () => {
638
- const result = await andThenAsync(ok(2), async value => ok(value * 4));
639
- expect(isOk(result)).toBe(true);
640
- expect(unwrap(result)).toBe(8);
603
+ describe('control helpers', () => {
604
+ it('unwrapOrReturn returns value for Ok', () => {
605
+ const value = unwrapOrReturn(ok(42), () => 'fallback');
606
+ expect(value).toBe(42);
641
607
  });
642
608
 
643
- it('matchAsync selects branch', async () => {
644
- const okValue = await matchAsync(
645
- ok(5),
646
- async value => value * 2,
647
- async () => 0,
648
- );
649
- expect(okValue).toBe(10);
650
-
651
- const errValue = await matchAsync(
652
- err('fail'),
653
- async () => 0,
654
- async error => error.length,
655
- );
656
- expect(errValue).toBe(4);
657
- });
658
- });
659
-
660
- describe('control helpers', () => {
661
609
  it('unwrapOrReturn returns fallback for Err', () => {
662
610
  const value = unwrapOrReturn(err('oops'), () => 'fallback');
663
611
  expect(value).toBe('fallback');
@@ -669,11 +617,19 @@ describe('Result', () => {
669
617
  expect(result.id).toBe(1);
670
618
  });
671
619
 
620
+ it('assertOk throws on Err with default message', () => {
621
+ expect(() => assertOk(err('fail'))).toThrow('Expected Ok result');
622
+ });
623
+
672
624
  it('assertErr narrows failure', () => {
673
625
  const result = err('oops');
674
626
  assertErr(result);
675
627
  expect(result.error).toBe('oops');
676
628
  });
629
+
630
+ it('assertErr throws on Ok with default message', () => {
631
+ expect(() => assertErr(ok(42))).toThrow('Expected Err result');
632
+ });
677
633
  });
678
634
 
679
635
  describe('collections', () => {
@@ -705,17 +661,292 @@ describe('Result', () => {
705
661
  expect(oks).toEqual([1, 2]);
706
662
  expect(errs).toEqual(['a']);
707
663
  });
664
+
665
+ it('partitionAsync handles rejected promises as errors', async () => {
666
+ const promises = [
667
+ Promise.resolve(ok(1)),
668
+ Promise.reject(new Error('rejected')),
669
+ Promise.resolve(ok(2)),
670
+ ];
671
+ const [oks, errs] = await partitionAsync(promises);
672
+ expect(oks).toEqual([1, 2]);
673
+ expect(errs).toHaveLength(1);
674
+ expect((errs[0] as Error).message).toBe('rejected');
675
+ });
676
+
677
+ it('any returns first Ok at start', () => {
678
+ const outcome = any([ok(1), err('a'), err('b')]);
679
+ expect(isOk(outcome)).toBe(true);
680
+ expect(unwrap(outcome)).toBe(1);
681
+ });
682
+
683
+ it('any returns first Ok at end', () => {
684
+ const outcome = any([err('a'), err('b'), ok(3)]);
685
+ expect(isOk(outcome)).toBe(true);
686
+ expect(unwrap(outcome)).toBe(3);
687
+ });
688
+
689
+ it('any returns empty errors for empty array', () => {
690
+ const outcome = any([]);
691
+ expect(isErr(outcome)).toBe(true);
692
+ expect((outcome as any).error).toEqual([]);
693
+ });
708
694
  });
709
695
 
710
- describe('introspection helpers', () => {
711
- it('inspectResult exposes discriminated metadata', () => {
712
- expect(inspectResult(ok(4))).toEqual({ status: 'ok', value: 4 });
713
- expect(inspectResult(err('error'))).toEqual({ status: 'err', error: 'error' });
696
+ describe('tryCatchMaybePromise', () => {
697
+ it('returns Ok for sync success', () => {
698
+ const result = tryCatchMaybePromise(() => 42);
699
+ expect(isOk(result)).toBe(true);
700
+ expect(result).toBe(42);
714
701
  });
715
702
 
716
- it('formatResult prints friendly string', () => {
717
- expect(formatResult(ok(1))).toBe('Ok(1)');
718
- expect(formatResult(err(new Error('boom')))).toBe('Err(boom)');
703
+ it('returns Err for sync throw', () => {
704
+ const result = tryCatchMaybePromise(() => {
705
+ throw new Error('sync error');
706
+ });
707
+ expect(isErr(result)).toBe(true);
708
+ expect((result as any).error.message).toBe('sync error');
709
+ });
710
+
711
+ it('returns Ok for async success', async () => {
712
+ const result = await tryCatchMaybePromise(() => Promise.resolve(42));
713
+ expect(isOk(result)).toBe(true);
714
+ expect(result).toBe(42);
715
+ });
716
+
717
+ it('returns Err for async rejection', async () => {
718
+ const result = await tryCatchMaybePromise(() => Promise.reject(new Error('async error')));
719
+ expect(isErr(result)).toBe(true);
720
+ expect((result as any).error.message).toBe('async error');
721
+ });
722
+
723
+ it('uses onError mapper for sync throw', () => {
724
+ const result = tryCatchMaybePromise(
725
+ () => { throw new Error('fail'); },
726
+ (e) => `mapped: ${(e as Error).message}`
727
+ );
728
+ expect(isErr(result)).toBe(true);
729
+ expect((result as any).error).toBe('mapped: fail');
730
+ });
731
+
732
+ it('uses onError mapper for async rejection', async () => {
733
+ const result = await tryCatchMaybePromise(
734
+ () => Promise.reject(new Error('fail')),
735
+ (e) => `mapped: ${(e as Error).message}`
736
+ );
737
+ expect(isErr(result)).toBe(true);
738
+ expect((result as any).error).toBe('mapped: fail');
719
739
  });
720
740
  });
741
+
742
+ describe('settleMaybePromise', () => {
743
+ it('returns sync array for all sync values', () => {
744
+ const result = settleMaybePromise([1, 2, 3]);
745
+ expect(result).not.toBeInstanceOf(Promise);
746
+ expect(result).toEqual([1, 2, 3]);
747
+ });
748
+
749
+ it('returns Promise for mixed sync/async values', async () => {
750
+ const result = settleMaybePromise([1, Promise.resolve(2), 3]);
751
+ expect(result).toBeInstanceOf(Promise);
752
+ expect(await result).toEqual([1, 2, 3]);
753
+ });
754
+
755
+ it('converts rejected promises to Err', async () => {
756
+ const result = await settleMaybePromise([1, Promise.reject('fail'), 3]);
757
+ expect(isOk(result[0])).toBe(true);
758
+ expect(isErr(result[1])).toBe(true);
759
+ expect((result[1] as any).error).toBe('fail');
760
+ expect(isOk(result[2])).toBe(true);
761
+ });
762
+
763
+ it('handles all async values', async () => {
764
+ const result = await settleMaybePromise([
765
+ Promise.resolve(1),
766
+ Promise.resolve(2)
767
+ ]);
768
+ expect(result).toEqual([1, 2]);
769
+ });
770
+
771
+ it('returns empty array for empty input', () => {
772
+ const result = settleMaybePromise([]);
773
+ expect(result).not.toBeInstanceOf(Promise);
774
+ expect(result).toEqual([]);
775
+ });
776
+ });
777
+
778
+ describe('partitionMaybePromise', () => {
779
+ it('returns sync partition for all sync values', () => {
780
+ const result = partitionMaybePromise([ok(1), err('a'), ok(2)]);
781
+ expect(result).not.toBeInstanceOf(Promise);
782
+ expect(result).toEqual([[1, 2], ['a']]);
783
+ });
784
+
785
+ it('returns Promise for mixed sync/async values', async () => {
786
+ const result = partitionMaybePromise([ok(1), Promise.resolve(err('a')), ok(2)]);
787
+ expect(result).toBeInstanceOf(Promise);
788
+ expect(await result).toEqual([[1, 2], ['a']]);
789
+ });
790
+
791
+ it('handles all async values', async () => {
792
+ const result = await partitionMaybePromise([
793
+ Promise.resolve(ok(1)),
794
+ Promise.resolve(err('a'))
795
+ ]);
796
+ expect(result).toEqual([[1], ['a']]);
797
+ });
798
+
799
+ it('handles rejected promises as errors', async () => {
800
+ const result = await partitionMaybePromise([
801
+ ok(1),
802
+ Promise.reject(new Error('rejected'))
803
+ ]);
804
+ expect(result[0]).toEqual([1]);
805
+ expect(result[1]).toHaveLength(1);
806
+ expect((result[1][0] as Error).message).toBe('rejected');
807
+ });
808
+
809
+ it('returns empty arrays for empty input', () => {
810
+ const result = partitionMaybePromise([]);
811
+ expect(result).not.toBeInstanceOf(Promise);
812
+ expect(result).toEqual([[], []]);
813
+ });
814
+ });
815
+
816
+ describe('filterOk', () => {
817
+ it('extracts Ok values', () => {
818
+ expect(filterOk([ok(1), err('a'), ok(2)])).toEqual([1, 2]);
819
+ });
820
+
821
+ it('returns empty for all Err', () => {
822
+ expect(filterOk([err('a'), err('b')])).toEqual([]);
823
+ });
824
+
825
+ it('returns empty for empty input', () => {
826
+ expect(filterOk([])).toEqual([]);
827
+ });
828
+ });
829
+
830
+ describe('filterErr', () => {
831
+ it('extracts Err values', () => {
832
+ expect(filterErr([ok(1), err('a'), ok(2), err('b')])).toEqual(['a', 'b']);
833
+ });
834
+
835
+ it('returns empty for all Ok', () => {
836
+ expect(filterErr([ok(1), ok(2)])).toEqual([]);
837
+ });
838
+
839
+ it('returns empty for empty input', () => {
840
+ expect(filterErr([])).toEqual([]);
841
+ });
842
+ });
843
+
844
+ describe('safeTry', () => {
845
+ it('returns Ok for successful execution', () => {
846
+ const result = safeTry(() => {
847
+ const a = unwrap(ok(10));
848
+ const b = unwrap(ok(5));
849
+ return a + b;
850
+ });
851
+ expect(isOk(result)).toBe(true);
852
+ expect(result).toBe(15);
853
+ });
854
+
855
+ it('returns Err when unwrap throws', () => {
856
+ const e = err('failed');
857
+ const result = safeTry(() => {
858
+ unwrap(e);
859
+ return 42;
860
+ });
861
+ expect(isErr(result)).toBe(true);
862
+ expect((result as { error: string }).error).toBe('failed');
863
+ });
864
+
865
+ it('catches regular errors', () => {
866
+ const result = safeTry(() => {
867
+ throw new Error('boom');
868
+ });
869
+ expect(isErr(result)).toBe(true);
870
+ expect((result as { error: Error }).error.message).toBe('boom');
871
+ });
872
+
873
+ it('propagates Err through chain', () => {
874
+ const parse = (s: string) => s === 'bad' ? err('parse error') : ok(Number(s));
875
+ const result = safeTry(() => {
876
+ const a = unwrap(parse('10'));
877
+ const b = unwrap(parse('bad'));
878
+ const c = unwrap(parse('5'));
879
+ return a + b + c;
880
+ });
881
+ expect(isErr(result)).toBe(true);
882
+ expect((result as { error: string }).error).toBe('parse error');
883
+ });
884
+ });
885
+
886
+ describe('safeTryAsync', () => {
887
+ it('returns Ok for successful async execution', async () => {
888
+ const result = await safeTryAsync(async () => {
889
+ const a = unwrap(ok(10));
890
+ const b = unwrap(await Promise.resolve(ok(5)));
891
+ return a + b;
892
+ });
893
+ expect(isOk(result)).toBe(true);
894
+ expect(result).toBe(15);
895
+ });
896
+
897
+ it('returns Err when unwrap throws in async', async () => {
898
+ const e = err('async failed');
899
+ const result = await safeTryAsync(async () => {
900
+ unwrap(e);
901
+ return 42;
902
+ });
903
+ expect(isErr(result)).toBe(true);
904
+ expect((result as { error: string }).error).toBe('async failed');
905
+ });
906
+
907
+ it('catches rejected promises', async () => {
908
+ const result = await safeTryAsync(async () => {
909
+ await Promise.reject(new Error('rejected'));
910
+ return 42;
911
+ });
912
+ expect(isErr(result)).toBe(true);
913
+ expect((result as { error: Error }).error.message).toBe('rejected');
914
+ });
915
+ });
916
+
917
+ describe('fromPromise', () => {
918
+ it('returns Ok for resolved promise', async () => {
919
+ const result = await fromPromise(Promise.resolve(42));
920
+ expect(isOk(result)).toBe(true);
921
+ expect(result).toBe(42);
922
+ });
923
+
924
+ it('returns Err for rejected promise', async () => {
925
+ const result = await fromPromise(Promise.reject(new Error('boom')));
926
+ expect(isErr(result)).toBe(true);
927
+ expect((result as { error: Error }).error.message).toBe('boom');
928
+ });
929
+
930
+ it('uses onError mapper for rejected promise', async () => {
931
+ const result = await fromPromise(
932
+ Promise.reject(new Error('boom')),
933
+ (e) => `mapped: ${(e as Error).message}`,
934
+ );
935
+ expect(isErr(result)).toBe(true);
936
+ expect((result as { error: string }).error).toBe('mapped: boom');
937
+ });
938
+
939
+ it('handles Ok(null) as valid success', async () => {
940
+ const result = await fromPromise(Promise.resolve(null));
941
+ expect(isOk(result)).toBe(true);
942
+ expect(result).toBe(null);
943
+ });
944
+
945
+ it('returns Err with unknown type when no onError provided', async () => {
946
+ const result = await fromPromise(Promise.reject('string error'));
947
+ expect(isErr(result)).toBe(true);
948
+ expect((result as { error: string }).error).toBe('string error');
949
+ });
950
+ });
951
+
721
952
  });
@@ -24,10 +24,7 @@ import {
24
24
  isOkAnd,
25
25
  isErrAnd,
26
26
  of,
27
- ofAsync,
28
27
  tryCatch,
29
- tryAsync,
30
- fromPromise,
31
28
  unwrapOrReturn,
32
29
  assertOk,
33
30
  assertErr,
@@ -162,17 +159,11 @@ const tryResult = of(() => {
162
159
  });
163
160
  assert<Equals<typeof tryResult, Result<number, unknown>>>;
164
161
 
165
- const tryResultTyped = of<number, Error>(() => {
162
+ const tryResultTyped = of(() => {
166
163
  if (Math.random() > 0.5) throw new Error("oops");
167
164
  return 42;
168
165
  });
169
- assert<Equals<typeof tryResultTyped, Result<number, Error>>>;
170
-
171
- const asyncResult = ofAsync<number>(async () => {
172
- return 42;
173
- });
174
- assert<Equals<typeof asyncResult, Promise<Result<number, unknown>>>>;
175
-
166
+ assert<Equals<typeof tryResultTyped, Result<number, unknown>>>;
176
167
 
177
168
 
178
169
  const unwrapOrResult = unwrapOr(err<string>("error") as Result<number, string>, 42);
@@ -214,16 +205,6 @@ const tryCatchTyped = tryCatch<number, string>(() => {
214
205
  }, error => (error as Error).message);
215
206
  assert<Equals<typeof tryCatchTyped, Result<number, string>>>;
216
207
 
217
- const tryAsyncResult = tryAsync(async () => 1);
218
- assert<Equals<typeof tryAsyncResult, Promise<Result<number, unknown>>>>;
219
-
220
- const tryAsyncTyped = tryAsync<number, string>(async () => {
221
- throw new Error('boom');
222
- }, error => (error as Error).message);
223
- assert<Equals<typeof tryAsyncTyped, Promise<Result<number, string>>>>;
224
-
225
- const fromPromiseResult = fromPromise(Promise.resolve(1));
226
- assert<Equals<typeof fromPromiseResult, Promise<Result<number, unknown>>>>;
227
208
 
228
209
  const unwrapFallback = unwrapOrReturn(ok(1) as Result<number, string>, () => 'fallback');
229
210
  assert<Equals<typeof unwrapFallback, number | string>>;
@@ -237,7 +218,7 @@ assertErr(maybeErr);
237
218
  const narrowedErr: Err<string> = maybeErr;
238
219
 
239
220
  const allResult = all([ok(1), ok(2)]);
240
- assert<Equals<typeof allResult, Result<number[], unknown>>>;
221
+ assert<Equals<typeof allResult, Result<readonly number[], unknown>>>;
241
222
 
242
223
  const anyResult = any([err('a'), ok(3)]);
243
224
  assert<Equals<typeof anyResult, Result<number, string[]>>>;
@@ -1,24 +1,18 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import * as safe from '../safe.js';
3
- import { err } from '../types.js';
2
+ import { ok, some, err, isSome } from '../types.js';
4
3
 
5
- describe('nalloc/safe exports', () => {
6
- it('exports match nalloc', () => {
7
- expect(safe.some).toBeDefined();
8
- expect('none' in safe).toBe(true);
9
- expect(safe.ok).toBeDefined();
10
- expect(safe.err).toBeDefined();
11
- expect(safe.Option).toBeDefined();
12
- expect(safe.Result).toBeDefined();
4
+ describe('safe constructors', () => {
5
+ it('some validates non-nullable input', () => {
6
+ expect(isSome(some(42))).toBe(true);
13
7
  });
14
8
 
15
- it('safe some throws on null/undefined', () => {
16
- expect(() => safe.some(null as any)).toThrow();
17
- expect(() => safe.some(undefined as any)).toThrow();
9
+ it('some throws on null/undefined', () => {
10
+ expect(() => some(null as any)).toThrow('some() requires a non-nullable value');
11
+ expect(() => some(undefined as any)).toThrow('some() requires a non-nullable value');
18
12
  });
19
13
 
20
- it('safe ok throws on Err', () => {
14
+ it('ok throws on Err', () => {
21
15
  const error = err('test');
22
- expect(() => safe.ok(error)).toThrow();
16
+ expect(() => ok(error)).toThrow('ok() cannot wrap an Err value');
23
17
  });
24
18
  });
@@ -1,24 +1,23 @@
1
- import { describe, it, expect } from 'vitest';
1
+ import { describe, expect, it } from 'vitest';
2
2
  import * as unsafe from '../unsafe.js';
3
- import { err } from '../types.js';
3
+ import { err, isErr, isNone } from '../types.js';
4
4
 
5
- describe('nalloc/unsafe exports', () => {
6
- it('exports match nalloc', () => {
5
+ describe('unsafe module', () => {
6
+ it('exports constructors', () => {
7
7
  expect(unsafe.some).toBeDefined();
8
- expect('none' in unsafe).toBe(true);
9
8
  expect(unsafe.ok).toBeDefined();
10
- expect(unsafe.err).toBeDefined();
11
- expect(unsafe.Option).toBeDefined();
12
- expect(unsafe.Result).toBeDefined();
13
9
  });
14
10
 
15
- it('unsafe some does not throw on null/undefined', () => {
11
+ it('some does not validate nullish values', () => {
16
12
  expect(() => unsafe.some(null)).not.toThrow();
17
13
  expect(() => unsafe.some(undefined)).not.toThrow();
14
+ expect(isNone(unsafe.some(null))).toBe(true);
15
+ expect(isNone(unsafe.some(undefined))).toBe(true);
18
16
  });
19
17
 
20
- it('unsafe ok does not throw on Err', () => {
21
- const error = err('test');
22
- expect(() => unsafe.ok(error)).not.toThrow();
18
+ it('ok does not validate Err payloads', () => {
19
+ const payload = err('unsafe payload');
20
+ expect(() => unsafe.ok(payload)).not.toThrow();
21
+ expect(isErr(unsafe.ok(payload))).toBe(true);
23
22
  });
24
23
  });
package/src/index.ts CHANGED
@@ -1,18 +1 @@
1
- export { some, none, ok, err } from './types.js';
2
- export type {
3
- Some,
4
- None,
5
- Ok,
6
- Err,
7
- Option as OptionType,
8
- OptionValue,
9
- IsOption,
10
- InferSome,
11
- Result as ResultType,
12
- ResultValue,
13
- ResultErrorType,
14
- IsResult,
15
- InferErr,
16
- } from './types.js';
17
- export * as Option from './option.js';
18
- export * as Result from './result.js';
1
+ export * from './safe.js';