vest-utils 1.4.0 → 1.5.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.
Files changed (157) hide show
  1. package/README.md +2 -7
  2. package/dist/cjs/minifyObject.development.js +217 -0
  3. package/dist/cjs/minifyObject.development.js.map +1 -0
  4. package/dist/cjs/minifyObject.js +6 -0
  5. package/dist/cjs/minifyObject.production.js +2 -0
  6. package/dist/cjs/minifyObject.production.js.map +1 -0
  7. package/dist/cjs/package.json +1 -0
  8. package/dist/cjs/vest-utils.development.js +378 -0
  9. package/dist/cjs/vest-utils.development.js.map +1 -0
  10. package/dist/cjs/vest-utils.js +6 -0
  11. package/dist/cjs/vest-utils.production.js +2 -0
  12. package/dist/cjs/vest-utils.production.js.map +1 -0
  13. package/dist/es/minifyObject.development.js +214 -0
  14. package/dist/es/minifyObject.development.js.map +1 -0
  15. package/dist/es/minifyObject.production.js +2 -0
  16. package/dist/es/minifyObject.production.js.map +1 -0
  17. package/dist/es/package.json +1 -0
  18. package/dist/es/vest-utils.development.js +330 -0
  19. package/dist/es/vest-utils.development.js.map +1 -0
  20. package/dist/es/vest-utils.production.js +2 -0
  21. package/dist/es/vest-utils.production.js.map +1 -0
  22. package/dist/umd/minifyObject.development.js +223 -0
  23. package/dist/umd/minifyObject.development.js.map +1 -0
  24. package/dist/umd/minifyObject.production.js +2 -0
  25. package/dist/umd/minifyObject.production.js.map +1 -0
  26. package/dist/umd/vest-utils.development.js +384 -0
  27. package/dist/umd/vest-utils.development.js.map +1 -0
  28. package/dist/umd/vest-utils.production.js +2 -0
  29. package/dist/umd/vest-utils.production.js.map +1 -0
  30. package/minifyObject/package.json +8 -12
  31. package/package.json +58 -43
  32. package/types/{exports/minifyObject.d.cts → minifyObject.d.ts} +2 -4
  33. package/types/minifyObject.d.ts.map +1 -0
  34. package/types/vest-utils.d.ts +143 -245
  35. package/types/vest-utils.d.ts.map +1 -0
  36. package/vitest.config.ts +45 -9
  37. package/dist/chunk-CLMFDpHK.mjs +0 -18
  38. package/dist/exports/minifyObject.cjs +0 -114
  39. package/dist/exports/minifyObject.cjs.map +0 -1
  40. package/dist/exports/minifyObject.mjs +0 -113
  41. package/dist/exports/minifyObject.mjs.map +0 -1
  42. package/dist/exports/standardSchemaSpec.cjs +0 -0
  43. package/dist/exports/standardSchemaSpec.mjs +0 -1
  44. package/dist/isEmpty-BBxAFjjm.mjs +0 -103
  45. package/dist/isEmpty-BBxAFjjm.mjs.map +0 -1
  46. package/dist/isEmpty-BuEa-96Q.cjs +0 -235
  47. package/dist/isEmpty-BuEa-96Q.cjs.map +0 -1
  48. package/dist/vest-utils.cjs +0 -510
  49. package/dist/vest-utils.cjs.map +0 -1
  50. package/dist/vest-utils.mjs +0 -421
  51. package/dist/vest-utils.mjs.map +0 -1
  52. package/src/Brand.ts +0 -9
  53. package/src/IO.ts +0 -2
  54. package/src/Predicates.ts +0 -13
  55. package/src/Result.ts +0 -121
  56. package/src/SimpleStateMachine.ts +0 -157
  57. package/src/StringObject.ts +0 -6
  58. package/src/__tests__/Architecture.test.ts +0 -69
  59. package/src/__tests__/Predicates.test.ts +0 -118
  60. package/src/__tests__/Result.test.ts +0 -284
  61. package/src/__tests__/SimpleStateMachine.test.ts +0 -425
  62. package/src/__tests__/StringObject.test.ts +0 -18
  63. package/src/__tests__/asArray.test.ts +0 -14
  64. package/src/__tests__/bindNot.test.ts +0 -39
  65. package/src/__tests__/bus.test.ts +0 -135
  66. package/src/__tests__/cache.test.ts +0 -139
  67. package/src/__tests__/callEach.test.ts +0 -20
  68. package/src/__tests__/defaultTo.test.ts +0 -52
  69. package/src/__tests__/deferThrow.test.ts +0 -26
  70. package/src/__tests__/either.test.ts +0 -17
  71. package/src/__tests__/freezeAssign.test.ts +0 -24
  72. package/src/__tests__/greaterThan.test.ts +0 -68
  73. package/src/__tests__/invariant.test.ts +0 -47
  74. package/src/__tests__/isArray.test.ts +0 -16
  75. package/src/__tests__/isBoolean.test.ts +0 -16
  76. package/src/__tests__/isEmpty.test.ts +0 -55
  77. package/src/__tests__/isEmptySet.test.ts +0 -22
  78. package/src/__tests__/isNull.test.ts +0 -26
  79. package/src/__tests__/isNumeric.test.ts +0 -27
  80. package/src/__tests__/isPositive.test.ts +0 -38
  81. package/src/__tests__/isPromise.test.ts +0 -17
  82. package/src/__tests__/isString.test.ts +0 -13
  83. package/src/__tests__/isUndefined.test.ts +0 -27
  84. package/src/__tests__/isUnsafeKey.test.ts +0 -22
  85. package/src/__tests__/lengthEquals.test.ts +0 -58
  86. package/src/__tests__/longerThan.test.ts +0 -58
  87. package/src/__tests__/mapFirst.test.ts +0 -31
  88. package/src/__tests__/nonnullish.test.ts +0 -25
  89. package/src/__tests__/noop.test.ts +0 -12
  90. package/src/__tests__/numberEquals.test.ts +0 -67
  91. package/src/__tests__/optionalFunctionValue.test.ts +0 -29
  92. package/src/__tests__/seq.test.ts +0 -29
  93. package/src/__tests__/text.test.ts +0 -41
  94. package/src/__tests__/tinyState.test.ts +0 -68
  95. package/src/__tests__/toNumber.test.ts +0 -39
  96. package/src/__tests__/vest-utils.test.ts +0 -13
  97. package/src/__tests__/withCatch.test.ts +0 -17
  98. package/src/__tests__/withResolvers.test.ts +0 -45
  99. package/src/asArray.ts +0 -3
  100. package/src/assign.ts +0 -1
  101. package/src/bindNot.ts +0 -3
  102. package/src/bus.ts +0 -52
  103. package/src/cache.ts +0 -68
  104. package/src/callEach.ts +0 -5
  105. package/src/defaultTo.ts +0 -9
  106. package/src/deferThrow.ts +0 -7
  107. package/src/dynamicValue.ts +0 -9
  108. package/src/either.ts +0 -3
  109. package/src/exports/__tests__/minifyObject.security.test.ts +0 -65
  110. package/src/exports/__tests__/minifyObject.test.ts +0 -281
  111. package/src/exports/minifyObject.ts +0 -198
  112. package/src/exports/standardSchemaSpec.ts +0 -70
  113. package/src/freezeAssign.ts +0 -5
  114. package/src/globals.d.ts +0 -3
  115. package/src/greaterThan.ts +0 -8
  116. package/src/hasOwnProperty.ts +0 -9
  117. package/src/invariant.ts +0 -19
  118. package/src/isArrayValue.ts +0 -11
  119. package/src/isBooleanValue.ts +0 -3
  120. package/src/isEmpty.ts +0 -18
  121. package/src/isEmptySet.ts +0 -15
  122. package/src/isFunction.ts +0 -5
  123. package/src/isNull.ts +0 -7
  124. package/src/isNullish.ts +0 -10
  125. package/src/isNumeric.ts +0 -11
  126. package/src/isPositive.ts +0 -5
  127. package/src/isPromise.ts +0 -5
  128. package/src/isStringValue.ts +0 -3
  129. package/src/isUndefined.ts +0 -7
  130. package/src/isUnsafeKey.ts +0 -3
  131. package/src/lengthEquals.ts +0 -11
  132. package/src/longerThan.ts +0 -8
  133. package/src/mapFirst.ts +0 -25
  134. package/src/nonnullish.ts +0 -9
  135. package/src/noop.ts +0 -1
  136. package/src/numberEquals.ts +0 -11
  137. package/src/seq.ts +0 -16
  138. package/src/text.ts +0 -20
  139. package/src/tinyState.ts +0 -28
  140. package/src/toNumber.ts +0 -11
  141. package/src/utilityTypes.ts +0 -25
  142. package/src/valueIsObject.ts +0 -5
  143. package/src/vest-utils.ts +0 -73
  144. package/src/withCatch.ts +0 -11
  145. package/src/withResolvers.ts +0 -33
  146. package/standardSchemaSpec/package.json +0 -14
  147. package/types/exports/minifyObject.d.cts.map +0 -1
  148. package/types/exports/minifyObject.d.mts +0 -7
  149. package/types/exports/minifyObject.d.mts.map +0 -1
  150. package/types/exports/standardSchemaSpec.d.cts +0 -59
  151. package/types/exports/standardSchemaSpec.d.cts.map +0 -1
  152. package/types/exports/standardSchemaSpec.d.mts +0 -59
  153. package/types/exports/standardSchemaSpec.d.mts.map +0 -1
  154. package/types/vest-utils.d.cts +0 -296
  155. package/types/vest-utils.d.cts.map +0 -1
  156. package/types/vest-utils.d.mts +0 -295
  157. package/types/vest-utils.d.mts.map +0 -1
@@ -1,157 +0,0 @@
1
- import { isFailure, makeResult, Result } from './Result';
2
- import { CB } from './utilityTypes';
3
-
4
- const STATE_WILD_CARD = '*';
5
- type TStateWildCard = typeof STATE_WILD_CARD;
6
-
7
- type TransitionTarget<S extends string> = S | [S, CB<boolean, [payload?: any]>];
8
- type StatesMap<S extends string = string, A extends string = string> = Record<
9
- S | TStateWildCard,
10
- Partial<Record<A, TransitionTarget<S>>>
11
- >;
12
-
13
- export type TStateMachine<
14
- S extends string = string,
15
- A extends string = string,
16
- > = {
17
- initial: S;
18
- states: Partial<StatesMap<S, A>>;
19
- };
20
-
21
- export type TStateMachineApi<
22
- S extends string = string,
23
- A extends string = string,
24
- > = {
25
- getState: CB<S>;
26
- initial: CB<S>;
27
- staticTransition: (from: S, action: A, payload?: any) => S;
28
- transition: (action: A, payload?: any) => Result<void, string>;
29
- };
30
-
31
- type TransitionValue<V> = V extends [infer T, any]
32
- ? T extends string
33
- ? T
34
- : never
35
- : V extends string
36
- ? V
37
- : never;
38
-
39
- type Values<T> = T[keyof T];
40
-
41
- type StateConfigs<M extends { states: Record<string, any> }> = Values<
42
- M['states']
43
- >;
44
-
45
- type ActionFromConfig<M extends { states: Record<string, any> }> =
46
- StateConfigs<M> extends infer SC
47
- ? SC extends any
48
- ? Extract<keyof SC, string>
49
- : never
50
- : never;
51
-
52
- type TargetStatesFromConfig<M extends { states: Record<string, any> }> =
53
- StateConfigs<M> extends infer SC
54
- ? SC extends any
55
- ? TransitionValue<Values<SC>>
56
- : never
57
- : never;
58
-
59
- type StateFromConfig<
60
- M extends { initial: string; states: Record<string, any> },
61
- > =
62
- | M['initial']
63
- | Extract<keyof M['states'], string>
64
- | TargetStatesFromConfig<M>;
65
-
66
- export function StateMachine<
67
- M extends { initial: string; states: Record<string, any> },
68
- >(machine: M): TStateMachineApi<StateFromConfig<M>, ActionFromConfig<M>> {
69
- type SMState = StateFromConfig<M>;
70
- type SMAction = ActionFromConfig<M>;
71
-
72
- const typedMachine = machine as TStateMachine<SMState, SMAction>;
73
-
74
- let state = typedMachine.initial;
75
-
76
- const api = { getState, initial, staticTransition, transition };
77
-
78
- return api;
79
-
80
- function getState(): SMState {
81
- return state;
82
- }
83
-
84
- function initial(): SMState {
85
- return machine.initial;
86
- }
87
-
88
- function transition(action: SMAction, payload?: any): Result<void, string> {
89
- const result = calculateNextState(typedMachine, state, action, payload);
90
-
91
- if (isFailure(result)) {
92
- return makeResult.Err(result.error);
93
- }
94
-
95
- state = result.value;
96
- return makeResult.Ok(undefined);
97
- }
98
-
99
- function staticTransition(
100
- from: SMState,
101
- action: SMAction,
102
- payload?: any,
103
- ): SMState {
104
- const transitionTo = getTransitionTarget(typedMachine, from, action);
105
- const target = Array.isArray(transitionTo)
106
- ? evaluateConditionalTarget(transitionTo, from, payload)
107
- : transitionTo;
108
-
109
- return !target || target === from ? from : (target as SMState);
110
- }
111
- }
112
-
113
- function getTransitionTarget<S extends string, A extends string>(
114
- machine: TStateMachine<S, A>,
115
- from: S,
116
- action: A,
117
- ): TransitionTarget<S> | undefined {
118
- return (
119
- machine.states[from]?.[action] ?? machine.states[STATE_WILD_CARD]?.[action]
120
- );
121
- }
122
-
123
- function evaluateConditionalTarget<S extends string>(
124
- target: [S, CB<boolean, [payload?: any]>],
125
- from: S,
126
- payload?: any,
127
- ): S {
128
- const [nextState, conditional] = target;
129
- return conditional(payload) ? nextState : from;
130
- }
131
-
132
- function calculateNextState<S extends string, A extends string>(
133
- machine: TStateMachine<S, A>,
134
- from: S,
135
- action: A,
136
- payload?: any,
137
- ): Result<S, string> {
138
- const transitionTo = getTransitionTarget(machine, from, action);
139
-
140
- if (!transitionTo) {
141
- return makeResult.Err(
142
- `Invalid transition: "${action}" from state "${from}"`,
143
- );
144
- }
145
-
146
- if (Array.isArray(transitionTo)) {
147
- const [candidateState, conditional] = transitionTo;
148
- if (!conditional(payload)) {
149
- return makeResult.Err(
150
- `Invalid transition: "${action}" from state "${from}" (conditional failed)`,
151
- );
152
- }
153
- return makeResult.Ok(candidateState);
154
- }
155
-
156
- return makeResult.Ok(transitionTo as S);
157
- }
@@ -1,6 +0,0 @@
1
- import dynamicValue from './dynamicValue';
2
- import type { Stringable } from './utilityTypes';
3
-
4
- export function StringObject(value?: Stringable): String {
5
- return new String(dynamicValue(value));
6
- }
@@ -1,69 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
-
3
- import { Brand, makeBrand } from '../Brand';
4
- import { IO } from '../IO';
5
- import { makeResult, isResult, isSuccess, isFailure } from '../Result';
6
-
7
- // --- CONTRACT: Branded Types ---
8
- describe('Architecture: Branded Types', () => {
9
- type UserId = Brand<string, 'UserId'>;
10
- type PostId = Brand<string, 'PostId'>;
11
-
12
- it('should not allow assignment of raw string to Branded type (Static Check)', () => {
13
- const raw = 'user_123';
14
- const userId = makeBrand<UserId>(raw);
15
- // @ts-expect-error PostId is not assignable to UserId
16
- const _postId: PostId = userId;
17
-
18
- expect(userId).toBe(raw);
19
- });
20
- });
21
-
22
- // --- CONTRACT: Result/Error Handling ---
23
- describe('Architecture: Result Monad', () => {
24
- it('should encapsulate errors as values', () => {
25
- const errorResult = makeResult.Err('Something went wrong');
26
- expect(isFailure(errorResult)).toBe(true);
27
- expect(errorResult.error).toBe('Something went wrong');
28
- });
29
-
30
- it('should encapsulate success values', () => {
31
- const successResult = makeResult.Ok(42);
32
- expect(isSuccess(successResult)).toBe(true);
33
- expect(successResult.value).toBe(42);
34
- });
35
-
36
- it('should support mapping without throwing', () => {
37
- const val = makeResult.Ok(10);
38
- const newResult = val.map(x => x * 2);
39
-
40
- expect(isSuccess(newResult)).toBe(true);
41
- // @ts-ignore
42
- expect(newResult.value).toBe(20);
43
- });
44
-
45
- it('should identify generic result shapes', () => {
46
- const okShape = makeResult.Ok('ok');
47
- const errShape = makeResult.Err('err');
48
- expect(isResult(okShape)).toBe(true);
49
- expect(isResult(errShape)).toBe(true);
50
- expect(isResult({})).toBe(false);
51
- });
52
- });
53
-
54
- // --- CONTRACT: Explicit Side Effects (IO) ---
55
- describe('Architecture: IO / Effect', () => {
56
- it('should not execute side effect immediately', () => {
57
- const spy = vi.fn();
58
-
59
- const sideEffectFn = (): IO<void> => {
60
- return () => spy();
61
- };
62
-
63
- const effect = sideEffectFn();
64
- expect(spy).not.toHaveBeenCalled();
65
-
66
- effect();
67
- expect(spy).toHaveBeenCalled();
68
- });
69
- });
@@ -1,118 +0,0 @@
1
- import { all, any } from '../Predicates';
2
- import { describe, it, vi, expect } from 'vitest';
3
-
4
- describe('Predicates', () => {
5
- describe('all', () => {
6
- it('Should return a predicate function', () => {
7
- expect(typeof all()).toBe('function');
8
- });
9
-
10
- it('Should return true if all predicates return true', () => {
11
- const predicate = all(
12
- value => value > 0,
13
- value => value < 10,
14
- );
15
-
16
- expect(predicate(5)).toBe(true);
17
- });
18
-
19
- it('Should return false if any predicate returns false', () => {
20
- const predicate = all(
21
- value => value > 0,
22
- value => value < 10,
23
- );
24
-
25
- expect(predicate(15)).toBe(false);
26
- });
27
-
28
- it('Should return false if no predicates are passed', () => {
29
- const predicate = all();
30
-
31
- expect(predicate(15)).toBe(false);
32
- });
33
-
34
- it('Should return false if predicates are not functions', () => {
35
- const predicate = all(
36
- value => value > 0,
37
- value => value < 10,
38
- // @ts-ignore - Testing invalid input
39
- 'not a function',
40
- );
41
-
42
- expect(predicate(15)).toBe(false);
43
- });
44
-
45
- it('Should pass each predicate the value', () => {
46
- const spy1 = vi.fn(value => value > 0);
47
- const spy2 = vi.fn(value => value < 10);
48
-
49
- const predicate = all(spy1, spy2);
50
-
51
- predicate(5);
52
-
53
- expect(spy1).toHaveBeenCalledWith(5);
54
- expect(spy2).toHaveBeenCalledWith(5);
55
- });
56
-
57
- it('When passing explicit true as a predicate, should return true', () => {
58
- expect(all(true, true, true)(5)).toBe(true);
59
- });
60
-
61
- it('When passing explicit false as a predicate, should return false', () => {
62
- expect(all(true, false, false)(5)).toBe(false);
63
- });
64
- });
65
-
66
- describe('any', () => {
67
- it('Shold return a predicate function', () => {
68
- expect(typeof any()).toBe('function');
69
- });
70
-
71
- it('Should return true if any predicate returns true', () => {
72
- expect(
73
- any(
74
- value => value > 0,
75
- value => value === 10,
76
- )(5),
77
- ).toBe(true);
78
- expect(
79
- any(
80
- value => value === 10,
81
- value => value > 0,
82
- )(5),
83
- ).toBe(true);
84
- });
85
-
86
- it('Should return true if all predicates return true', () => {
87
- const predicate = any(
88
- value => value > 0,
89
- value => value === 10,
90
- );
91
-
92
- expect(predicate(10)).toBe(true);
93
- });
94
-
95
- it('Should return false if all predicates return false', () => {
96
- const predicate = any(
97
- value => value > 0,
98
- value => value === 10,
99
- );
100
-
101
- expect(predicate(-5)).toBe(false);
102
- });
103
-
104
- it('Should return false if no predicates are passed', () => {
105
- const predicate = any();
106
-
107
- expect(predicate(15)).toBe(false);
108
- });
109
-
110
- it('When passing explicit true as a predicate, should return true', () => {
111
- expect(any(true, false, false)(5)).toBe(true);
112
- });
113
-
114
- it('When passing explicit false as a predicate, should return false', () => {
115
- expect(any(false, false, false)(5)).toBe(false);
116
- });
117
- });
118
- });
@@ -1,284 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
-
3
- import { isFailure, isResult, isSuccess, makeResult, unwrap } from '../Result';
4
-
5
- describe('Result', () => {
6
- describe('makeResult', () => {
7
- describe('Ok', () => {
8
- it('should return a Success result', () => {
9
- const result = makeResult.Ok(1);
10
- expect(result.type).toBe('ok');
11
- expect(result.value).toBe(1);
12
- });
13
-
14
- it('should have correct methods', () => {
15
- const result = makeResult.Ok(1);
16
- expect(typeof result.map).toBe('function');
17
- expect(typeof result.chain).toBe('function');
18
- expect(typeof result.mapError).toBe('function');
19
- expect(typeof result.match).toBe('function');
20
- });
21
- });
22
-
23
- describe('Err', () => {
24
- it('should return a Failure result', () => {
25
- const result = makeResult.Err('error');
26
- expect(result.type).toBe('err');
27
- expect(result.error).toBe('error');
28
- });
29
-
30
- it('should have correct methods', () => {
31
- const result = makeResult.Err('error');
32
- expect(typeof result.map).toBe('function');
33
- expect(typeof result.chain).toBe('function');
34
- expect(typeof result.mapError).toBe('function');
35
- expect(typeof result.match).toBe('function');
36
- });
37
- });
38
- });
39
-
40
- describe('isResult', () => {
41
- it('should return true for Success result', () => {
42
- expect(isResult(makeResult.Ok(1))).toBe(true);
43
- });
44
-
45
- it('should return true for Failure result', () => {
46
- expect(isResult(makeResult.Err('error'))).toBe(true);
47
- });
48
-
49
- it('should return false for non-result objects', () => {
50
- expect(isResult({})).toBe(false);
51
- expect(isResult(null)).toBe(false);
52
- expect(isResult(undefined)).toBe(false);
53
- expect(isResult(1)).toBe(false);
54
- expect(isResult('string')).toBe(false);
55
- expect(isResult({ type: 'ok' })).toBe(false); // Missing value
56
- expect(isResult({ type: 'err' })).toBe(false); // Missing error
57
- expect(isResult({ value: 1 })).toBe(false); // Missing type
58
- });
59
- });
60
-
61
- describe('isSuccess', () => {
62
- it('should return true for Success result', () => {
63
- expect(isSuccess(makeResult.Ok(1))).toBe(true);
64
- });
65
-
66
- it('should return false for Failure result', () => {
67
- expect(isSuccess(makeResult.Err('error'))).toBe(false);
68
- });
69
- });
70
-
71
- describe('isFailure', () => {
72
- it('should return true for Failure result', () => {
73
- expect(isFailure(makeResult.Err('error'))).toBe(true);
74
- });
75
-
76
- it('should return false for Success result', () => {
77
- expect(isFailure(makeResult.Ok(1))).toBe(false);
78
- });
79
- });
80
-
81
- describe('unwrap', () => {
82
- it('should return value if result is Success', () => {
83
- const result = makeResult.Ok(100);
84
- expect(unwrap(result)).toBe(100);
85
- expect(result.unwrap()).toBe(100);
86
- });
87
-
88
- it('should throw error if result is Failure', () => {
89
- const error = new Error('fail');
90
- const result = makeResult.Err(error);
91
- expect(() => unwrap(result)).toThrow(error);
92
- expect(() => result.unwrap()).toThrow(error);
93
- });
94
-
95
- it('should throw Error object if failure contains non-Error', () => {
96
- const result = makeResult.Err('string error');
97
- expect(() => unwrap(result)).toThrow('string error');
98
- expect(() => result.unwrap()).toThrow('string error');
99
- try {
100
- result.unwrap();
101
- } catch (e) {
102
- expect(e).toBeInstanceOf(Error);
103
- expect((e as Error).message).toBe('string error');
104
- }
105
- });
106
- });
107
-
108
- describe('unwrapOr', () => {
109
- it('should return value if result is Success', () => {
110
- const result = makeResult.Ok(100);
111
- expect(result.unwrapOr(200)).toBe(100);
112
- });
113
-
114
- it('should return default value if result is Failure', () => {
115
- const result = makeResult.Err<number>('error');
116
- expect(result.unwrapOr(200)).toBe(200);
117
- });
118
- });
119
-
120
- describe('Success methods', () => {
121
- describe('map', () => {
122
- it('should transform the value', () => {
123
- const result = makeResult.Ok(1).map(x => x + 1);
124
- expect(unwrap(result)).toBe(2);
125
- });
126
- });
127
-
128
- describe('chain', () => {
129
- it('should chain with another Result', () => {
130
- const result = makeResult.Ok(1).chain(x => makeResult.Ok(x + 1));
131
- expect(unwrap(result)).toBe(2);
132
- });
133
-
134
- it('should chain with a Failure', () => {
135
- const result = makeResult.Ok(1).chain(() => makeResult.Err('fail'));
136
- expect(isFailure(result)).toBe(true);
137
- expect((result as any).error).toBe('fail');
138
- });
139
- });
140
-
141
- describe('mapError', () => {
142
- it('should not transform the error (no-op for Success)', () => {
143
- const result = makeResult.Ok(1).mapError(() => 'new error');
144
- expect(unwrap(result)).toBe(1);
145
- });
146
- });
147
-
148
- describe('match', () => {
149
- it('should call ok handler', () => {
150
- const result = makeResult.Ok(1);
151
- const output = result.match({
152
- ok: val => `ok: ${val}`,
153
- err: err => `err: ${err}`,
154
- });
155
- expect(output).toBe('ok: 1');
156
- });
157
- });
158
- });
159
-
160
- describe('Failure methods', () => {
161
- describe('map', () => {
162
- it('should not transform the value (no-op for Failure)', () => {
163
- const result = makeResult.Err('error').map((x: any) => x + 1);
164
- expect(isFailure(result)).toBe(true);
165
- expect((result as any).error).toBe('error');
166
- });
167
- });
168
-
169
- describe('chain', () => {
170
- it('should not call the function (no-op for Failure)', () => {
171
- const fn = vi.fn();
172
- const result = makeResult.Err('error').chain(fn);
173
- expect(fn).not.toHaveBeenCalled();
174
- expect(isFailure(result)).toBe(true);
175
- });
176
- });
177
-
178
- describe('mapError', () => {
179
- it('should transform the error', () => {
180
- const result = makeResult.Err('error').mapError(e => e.toUpperCase());
181
- expect(isFailure(result)).toBe(true);
182
- expect((result as any).error).toBe('ERROR');
183
- });
184
- });
185
-
186
- describe('match', () => {
187
- it('should call err handler', () => {
188
- const result = makeResult.Err('error');
189
- const output = result.match({
190
- ok: val => `ok: ${val}`,
191
- err: err => `err: ${err}`,
192
- });
193
- expect(output).toBe('err: error');
194
- });
195
- });
196
- });
197
-
198
- describe('Edge Cases: Nullish values', () => {
199
- it('should handle null as a valid Success value', () => {
200
- const result = makeResult.Ok(null);
201
- expect(isSuccess(result)).toBe(true);
202
- expect(unwrap(result)).toBeNull();
203
- });
204
-
205
- it('should handle undefined as a valid Success value', () => {
206
- const result = makeResult.Ok(undefined);
207
- expect(isSuccess(result)).toBe(true);
208
- expect(unwrap(result)).toBeUndefined();
209
- });
210
-
211
- it('should allow mapping over null values', () => {
212
- const result = makeResult
213
- .Ok(null)
214
- .map(val => (val === null ? 'was null' : 'not null'));
215
- expect(unwrap(result)).toBe('was null');
216
- });
217
- });
218
-
219
- describe('Control Flow: Exceptions', () => {
220
- it('should NOT catch errors thrown inside map (Sync/Pure behavior)', () => {
221
- const result = makeResult.Ok(1);
222
-
223
- // If your architecture intends to catch this, change .toThrow() to checking for Err
224
- expect(() => {
225
- result.map(() => {
226
- throw new Error('Boom');
227
- });
228
- }).toThrow('Boom');
229
- });
230
-
231
- it('should NOT catch errors thrown inside chain', () => {
232
- const result = makeResult.Ok(1);
233
-
234
- expect(() => {
235
- result.chain(() => {
236
- throw new Error('Boom');
237
- });
238
- }).toThrow('Boom');
239
- });
240
- });
241
-
242
- describe('isResult Edge Cases', () => {
243
- it('should return false if type discriminator is invalid', () => {
244
- // Has correct shape keys, but wrong 'type' value
245
- const fakeResult = { type: 'banana', value: 1 };
246
- expect(isResult(fakeResult)).toBe(false);
247
- });
248
-
249
- it('should return false for extra properties mimicking result', () => {
250
- // Depends on how strict your guard is.
251
- // Usually, duck typing accepts this, but good to know.
252
- const complicatedObj = { type: 'ok', value: 1, extra: 'stuff' };
253
- expect(isResult(complicatedObj)).toBe(true); // Should likely be true
254
- });
255
- });
256
-
257
- describe('Integration: Pipelining', () => {
258
- it('should handle a sequence of maps and chains', () => {
259
- const result = makeResult
260
- .Ok(10)
261
- .map(x => x * 2) // 20
262
- .chain(x => makeResult.Ok(x + 5)) // 25
263
- .mapError(() => 'new error') // Ignored
264
- .map(x => `Value: ${x}`); // "Value: 25"
265
-
266
- expect(unwrap(result)).toBe('Value: 25');
267
- });
268
-
269
- it('should short-circuit the pipeline on first error', () => {
270
- const fn = vi.fn();
271
-
272
- const result = makeResult
273
- .Ok(10)
274
- .map(x => x * 2) // 20
275
- .chain(() => makeResult.Err('First Failure')) // Breaks here
276
- .map(fn) // Should skip
277
- .chain(x => makeResult.Ok(x)); // Should skip
278
-
279
- expect(fn).not.toHaveBeenCalled();
280
- expect(isFailure(result)).toBe(true);
281
- expect((result as any).error).toBe('First Failure');
282
- });
283
- });
284
- });