nalloc 0.0.1 → 0.0.2
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 +124 -38
- package/build/index.cjs +12 -68
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +1 -4
- package/build/index.js +1 -3
- package/build/index.js.map +1 -1
- package/build/iter.cjs +105 -0
- package/build/iter.cjs.map +1 -0
- package/build/iter.d.ts +61 -0
- package/build/iter.js +78 -0
- package/build/iter.js.map +1 -0
- package/build/option.cjs +19 -5
- package/build/option.cjs.map +1 -1
- package/build/option.d.ts +22 -1
- package/build/option.js +14 -6
- package/build/option.js.map +1 -1
- package/build/result.cjs +125 -54
- package/build/result.cjs.map +1 -1
- package/build/result.d.ts +83 -53
- package/build/result.js +100 -38
- package/build/result.js.map +1 -1
- package/build/safe.cjs +34 -15
- package/build/safe.cjs.map +1 -1
- package/build/safe.d.ts +4 -27
- package/build/safe.js +3 -14
- package/build/safe.js.map +1 -1
- package/build/types.cjs +38 -7
- package/build/types.cjs.map +1 -1
- package/build/types.d.ts +26 -4
- package/build/types.js +23 -7
- package/build/types.js.map +1 -1
- package/build/unsafe.cjs +14 -61
- package/build/unsafe.cjs.map +1 -1
- package/build/unsafe.d.ts +2 -27
- package/build/unsafe.js +2 -9
- package/build/unsafe.js.map +1 -1
- package/package.json +13 -16
- package/src/__tests__/index.ts +42 -0
- package/src/__tests__/iter.ts +218 -0
- package/src/__tests__/option.ts +48 -19
- package/src/__tests__/result.ts +286 -91
- package/src/__tests__/result.types.ts +3 -22
- package/src/__tests__/safe.ts +9 -15
- package/src/__tests__/unsafe.ts +11 -12
- package/src/index.ts +1 -18
- package/src/iter.ts +129 -0
- package/src/option.ts +36 -7
- package/src/result.ts +216 -113
- package/src/safe.ts +5 -42
- package/src/types.ts +52 -14
- package/src/unsafe.ts +2 -47
- package/build/devtools.cjs +0 -79
- package/build/devtools.cjs.map +0 -1
- package/build/devtools.d.ts +0 -82
- package/build/devtools.js +0 -43
- package/build/devtools.js.map +0 -1
- package/build/testing.cjs +0 -111
- package/build/testing.cjs.map +0 -1
- package/build/testing.d.ts +0 -85
- package/build/testing.js +0 -81
- package/build/testing.js.map +0 -1
- package/src/__tests__/tooling.ts +0 -86
- package/src/devtools.ts +0 -97
- package/src/testing.ts +0 -159
package/build/testing.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { isOk, isErr, isSome, isNone } from "./types.js";
|
|
2
|
-
import { formatOption, formatResult } from "./devtools.js";
|
|
3
|
-
export function expectOk(result, message) {
|
|
4
|
-
if (isOk(result)) {
|
|
5
|
-
return result;
|
|
6
|
-
}
|
|
7
|
-
const fallback = message ?? `Expected Ok(...) but received ${formatResult(result)}`;
|
|
8
|
-
throw new Error(fallback);
|
|
9
|
-
}
|
|
10
|
-
export function expectErr(result, message) {
|
|
11
|
-
if (isErr(result)) {
|
|
12
|
-
return result.error;
|
|
13
|
-
}
|
|
14
|
-
const fallback = message ?? `Expected Err(...) but received ${formatResult(result)}`;
|
|
15
|
-
throw new Error(fallback);
|
|
16
|
-
}
|
|
17
|
-
export function expectSome(opt, message) {
|
|
18
|
-
if (isSome(opt)) {
|
|
19
|
-
return opt;
|
|
20
|
-
}
|
|
21
|
-
const fallback = message ?? `Expected Some(...) but received ${formatOption(opt)}`;
|
|
22
|
-
throw new Error(fallback);
|
|
23
|
-
}
|
|
24
|
-
export function expectNone(opt, message) {
|
|
25
|
-
if (isNone(opt)) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const fallback = message ?? `Expected None but received ${formatOption(opt)}`;
|
|
29
|
-
throw new Error(fallback);
|
|
30
|
-
}
|
|
31
|
-
const resultMatchers = {
|
|
32
|
-
toBeOk (received) {
|
|
33
|
-
const pass = isOk(received);
|
|
34
|
-
return {
|
|
35
|
-
pass,
|
|
36
|
-
message: ()=>pass ? 'Result is Ok as expected.' : `Expected Ok(...) but received ${formatResult(received)}`
|
|
37
|
-
};
|
|
38
|
-
},
|
|
39
|
-
toBeErr (received) {
|
|
40
|
-
const pass = isErr(received);
|
|
41
|
-
return {
|
|
42
|
-
pass,
|
|
43
|
-
message: ()=>pass ? 'Result is Err as expected.' : `Expected Err(...) but received ${formatResult(received)}`
|
|
44
|
-
};
|
|
45
|
-
},
|
|
46
|
-
toContainErr (received, expected) {
|
|
47
|
-
const pass = isErr(received) && received.error === expected;
|
|
48
|
-
return {
|
|
49
|
-
pass,
|
|
50
|
-
message: ()=>{
|
|
51
|
-
if (pass) return `Err matched expected value ${String(expected)}.`;
|
|
52
|
-
return `Expected Err(${String(expected)}) but received ${formatResult(received)}`;
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
const optionMatchers = {
|
|
58
|
-
toBeSome (received) {
|
|
59
|
-
const pass = isSome(received);
|
|
60
|
-
return {
|
|
61
|
-
pass,
|
|
62
|
-
message: ()=>pass ? 'Option is Some as expected.' : `Expected Some(...) but received ${formatOption(received)}`
|
|
63
|
-
};
|
|
64
|
-
},
|
|
65
|
-
toBeNone (received) {
|
|
66
|
-
const pass = isNone(received);
|
|
67
|
-
return {
|
|
68
|
-
pass,
|
|
69
|
-
message: ()=>pass ? 'Option is None as expected.' : `Expected None but received ${formatOption(received)}`
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
export const matchers = {
|
|
74
|
-
...resultMatchers,
|
|
75
|
-
...optionMatchers
|
|
76
|
-
};
|
|
77
|
-
export function extendExpect(expectLike) {
|
|
78
|
-
expectLike.extend(matchers);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
//# sourceMappingURL=testing.js.map
|
package/build/testing.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing.ts"],"sourcesContent":["import { isOk, isErr, isSome, isNone, Result, Err, Option } from './types.js';\nimport { formatOption, formatResult } from './devtools.js';\n\n/** Result shape returned by custom matchers. */\ntype MatcherResult = { pass: boolean; message(): string };\n\n/**\n * Asserts that a Result is Ok and returns the value.\n * Throws if the Result is Err.\n * @param result - The Result to check\n * @param message - Optional custom error message\n * @returns The Ok value\n * @throws {Error} If the Result is Err\n * @example\n * expectOk(ok(42)) // returns 42\n * expectOk(err('fail')) // throws Error\n */\nexport function expectOk<T, E>(result: Result<T, E>, message?: string): T {\n if (isOk(result)) {\n return result;\n }\n\n const fallback = message ?? `Expected Ok(...) but received ${formatResult(result)}`;\n throw new Error(fallback);\n}\n\n/**\n * Asserts that a Result is Err and returns the error.\n * Throws if the Result is Ok.\n * @param result - The Result to check\n * @param message - Optional custom error message\n * @returns The error value\n * @throws {Error} If the Result is Ok\n * @example\n * expectErr(err('fail')) // returns 'fail'\n * expectErr(ok(42)) // throws Error\n */\nexport function expectErr<T, E>(result: Result<T, E>, message?: string): E {\n if (isErr(result)) {\n return (result as Err<E>).error;\n }\n\n const fallback = message ?? `Expected Err(...) but received ${formatResult(result)}`;\n throw new Error(fallback);\n}\n\n/**\n * Asserts that an Option is Some and returns the value.\n * Throws if the Option is None.\n * @param opt - The Option to check\n * @param message - Optional custom error message\n * @returns The Some value\n * @throws {Error} If the Option is None\n * @example\n * expectSome(42) // returns 42\n * expectSome(null) // throws Error\n */\nexport function expectSome<T>(opt: Option<T>, message?: string): T {\n if (isSome(opt)) {\n return opt;\n }\n const fallback = message ?? `Expected Some(...) but received ${formatOption(opt)}`;\n throw new Error(fallback);\n}\n\n/**\n * Asserts that an Option is None.\n * Throws if the Option is Some.\n * @param opt - The Option to check\n * @param message - Optional custom error message\n * @throws {Error} If the Option is Some\n * @example\n * expectNone(null) // succeeds\n * expectNone(42) // throws Error\n */\nexport function expectNone<T>(opt: Option<T>, message?: string): void {\n if (isNone(opt)) {\n return;\n }\n const fallback = message ?? `Expected None but received ${formatOption(opt)}`;\n throw new Error(fallback);\n}\n\nconst resultMatchers = {\n toBeOk(this: unknown, received: Result<unknown, unknown>): MatcherResult {\n const pass = isOk(received);\n return {\n pass,\n message: () => (pass ? 'Result is Ok as expected.' : `Expected Ok(...) but received ${formatResult(received)}`),\n };\n },\n toBeErr(this: unknown, received: Result<unknown, unknown>): MatcherResult {\n const pass = isErr(received);\n return {\n pass,\n message: () => (pass ? 'Result is Err as expected.' : `Expected Err(...) but received ${formatResult(received)}`),\n };\n },\n toContainErr(this: unknown, received: Result<unknown, unknown>, expected: unknown): MatcherResult {\n const pass = isErr(received) && (received as Err<unknown>).error === expected;\n return {\n pass,\n message: () => {\n if (pass) return `Err matched expected value ${String(expected)}.`;\n return `Expected Err(${String(expected)}) but received ${formatResult(received)}`;\n },\n };\n },\n};\n\nconst optionMatchers = {\n toBeSome(this: unknown, received: Option<unknown>): MatcherResult {\n const pass = isSome(received);\n return {\n pass,\n message: () => (pass ? 'Option is Some as expected.' : `Expected Some(...) but received ${formatOption(received)}`),\n };\n },\n toBeNone(this: unknown, received: Option<unknown>): MatcherResult {\n const pass = isNone(received);\n return {\n pass,\n message: () => (pass ? 'Option is None as expected.' : `Expected None but received ${formatOption(received)}`),\n };\n },\n};\n\n/**\n * Custom matchers for Jest/Vitest.\n * Includes toBeOk, toBeErr, toContainErr, toBeSome, toBeNone.\n * Use with expect.extend(matchers) or extendExpect(expect).\n */\nexport const matchers = {\n ...resultMatchers,\n ...optionMatchers,\n};\n\n/** Interface for test frameworks with an extend method (Jest, Vitest). */\nexport type ExpectLike = {\n extend(matchers: Record<string, (...args: any[]) => MatcherResult>): void;\n};\n\n/**\n * Extends a test framework's expect with Option and Result matchers.\n * @param expectLike - The expect object to extend (Jest/Vitest)\n * @example\n * import { expect } from 'vitest';\n * import { extendExpect } from 'nalloc/testing';\n * extendExpect(expect);\n *\n * // Now you can use:\n * expect(result).toBeOk();\n * expect(result).toBeErr();\n * expect(option).toBeSome();\n * expect(option).toBeNone();\n */\nexport function extendExpect(expectLike: ExpectLike): void {\n expectLike.extend(matchers);\n}\n"],"names":["isOk","isErr","isSome","isNone","formatOption","formatResult","expectOk","result","message","fallback","Error","expectErr","error","expectSome","opt","expectNone","resultMatchers","toBeOk","received","pass","toBeErr","toContainErr","expected","String","optionMatchers","toBeSome","toBeNone","matchers","extendExpect","expectLike","extend"],"mappings":"AAAA,SAASA,IAAI,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,QAA6B,aAAa;AAC9E,SAASC,YAAY,EAAEC,YAAY,QAAQ,gBAAgB;AAgB3D,OAAO,SAASC,SAAeC,MAAoB,EAAEC,OAAgB;IACnE,IAAIR,KAAKO,SAAS;QAChB,OAAOA;IACT;IAEA,MAAME,WAAWD,WAAW,CAAC,8BAA8B,EAAEH,aAAaE,SAAS;IACnF,MAAM,IAAIG,MAAMD;AAClB;AAaA,OAAO,SAASE,UAAgBJ,MAAoB,EAAEC,OAAgB;IACpE,IAAIP,MAAMM,SAAS;QACjB,OAAO,AAACA,OAAkBK,KAAK;IACjC;IAEA,MAAMH,WAAWD,WAAW,CAAC,+BAA+B,EAAEH,aAAaE,SAAS;IACpF,MAAM,IAAIG,MAAMD;AAClB;AAaA,OAAO,SAASI,WAAcC,GAAc,EAAEN,OAAgB;IAC5D,IAAIN,OAAOY,MAAM;QACf,OAAOA;IACT;IACA,MAAML,WAAWD,WAAW,CAAC,gCAAgC,EAAEJ,aAAaU,MAAM;IAClF,MAAM,IAAIJ,MAAMD;AAClB;AAYA,OAAO,SAASM,WAAcD,GAAc,EAAEN,OAAgB;IAC5D,IAAIL,OAAOW,MAAM;QACf;IACF;IACA,MAAML,WAAWD,WAAW,CAAC,2BAA2B,EAAEJ,aAAaU,MAAM;IAC7E,MAAM,IAAIJ,MAAMD;AAClB;AAEA,MAAMO,iBAAiB;IACrBC,QAAsBC,QAAkC;QACtD,MAAMC,OAAOnB,KAAKkB;QAClB,OAAO;YACLC;YACAX,SAAS,IAAOW,OAAO,8BAA8B,CAAC,8BAA8B,EAAEd,aAAaa,WAAW;QAChH;IACF;IACAE,SAAuBF,QAAkC;QACvD,MAAMC,OAAOlB,MAAMiB;QACnB,OAAO;YACLC;YACAX,SAAS,IAAOW,OAAO,+BAA+B,CAAC,+BAA+B,EAAEd,aAAaa,WAAW;QAClH;IACF;IACAG,cAA4BH,QAAkC,EAAEI,QAAiB;QAC/E,MAAMH,OAAOlB,MAAMiB,aAAa,AAACA,SAA0BN,KAAK,KAAKU;QACrE,OAAO;YACLH;YACAX,SAAS;gBACP,IAAIW,MAAM,OAAO,CAAC,2BAA2B,EAAEI,OAAOD,UAAU,CAAC,CAAC;gBAClE,OAAO,CAAC,aAAa,EAAEC,OAAOD,UAAU,eAAe,EAAEjB,aAAaa,WAAW;YACnF;QACF;IACF;AACF;AAEA,MAAMM,iBAAiB;IACrBC,UAAwBP,QAAyB;QAC/C,MAAMC,OAAOjB,OAAOgB;QACpB,OAAO;YACLC;YACAX,SAAS,IAAOW,OAAO,gCAAgC,CAAC,gCAAgC,EAAEf,aAAac,WAAW;QACpH;IACF;IACAQ,UAAwBR,QAAyB;QAC/C,MAAMC,OAAOhB,OAAOe;QACpB,OAAO;YACLC;YACAX,SAAS,IAAOW,OAAO,gCAAgC,CAAC,2BAA2B,EAAEf,aAAac,WAAW;QAC/G;IACF;AACF;AAOA,OAAO,MAAMS,WAAW;IACtB,GAAGX,cAAc;IACjB,GAAGQ,cAAc;AACnB,EAAE;AAqBF,OAAO,SAASI,aAAaC,UAAsB;IACjDA,WAAWC,MAAM,CAACH;AACpB"}
|
package/src/__tests__/tooling.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
-
import { ok, err, none, some } from '../types.js';
|
|
3
|
-
import {
|
|
4
|
-
expectOk,
|
|
5
|
-
expectErr,
|
|
6
|
-
expectSome,
|
|
7
|
-
expectNone,
|
|
8
|
-
extendExpect,
|
|
9
|
-
} from '../testing.js';
|
|
10
|
-
import {
|
|
11
|
-
formatOption,
|
|
12
|
-
formatResult,
|
|
13
|
-
inspectOption,
|
|
14
|
-
inspectResult,
|
|
15
|
-
logOption,
|
|
16
|
-
logResult,
|
|
17
|
-
toJSONOption,
|
|
18
|
-
toJSONResult,
|
|
19
|
-
} from '../devtools.js';
|
|
20
|
-
|
|
21
|
-
describe('testing utilities', () => {
|
|
22
|
-
beforeAll(() => {
|
|
23
|
-
extendExpect(expect as any);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('expectOk returns Ok payload or throws', () => {
|
|
27
|
-
const value = expectOk(ok(5));
|
|
28
|
-
expect(value).toBe(5);
|
|
29
|
-
expect(() => expectOk(err('nope'))).toThrow(/Err/);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('expectErr returns error payload or throws', () => {
|
|
33
|
-
const error = expectErr(err('boom'));
|
|
34
|
-
expect(error).toBe('boom');
|
|
35
|
-
expect(() => expectErr(ok(1))).toThrow(/Ok/);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('expectSome / expectNone validate Option', () => {
|
|
39
|
-
const value = expectSome(some(3));
|
|
40
|
-
expect(value).toBe(3);
|
|
41
|
-
expect(() => expectSome(none)).toThrow(/None/);
|
|
42
|
-
expect(() => expectNone(some(2))).toThrow(/Some/);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('adds matchers to expect', () => {
|
|
46
|
-
expect(ok(1)).toBeOk();
|
|
47
|
-
expect(err('oops')).toBeErr();
|
|
48
|
-
expect(some(4)).toBeSome();
|
|
49
|
-
expect(none).toBeNone();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('devtools utilities', () => {
|
|
54
|
-
it('formats option', () => {
|
|
55
|
-
expect(formatOption(some('x'))).toBe('Some(x)');
|
|
56
|
-
expect(formatOption(none)).toBe('None');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('formats result', () => {
|
|
60
|
-
expect(formatResult(ok(7))).toBe('Ok(7)');
|
|
61
|
-
expect(formatResult(err('fail'))).toBe('Err(fail)');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('inspects option/result', () => {
|
|
65
|
-
expect(inspectOption(some('x'))).toEqual({ kind: 'some', value: 'x' });
|
|
66
|
-
expect(inspectOption(none)).toEqual({ kind: 'none' });
|
|
67
|
-
expect(inspectResult(ok('y'))).toEqual({ status: 'ok', value: 'y' });
|
|
68
|
-
expect(inspectResult(err('fail'))).toEqual({ status: 'err', error: 'fail' });
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('logs option/result via logger', () => {
|
|
72
|
-
const calls: unknown[][] = [];
|
|
73
|
-
const logger = (...args: unknown[]) => calls.push(args);
|
|
74
|
-
logOption(some(1), logger);
|
|
75
|
-
logResult(err('fail'), logger);
|
|
76
|
-
expect(calls[0]).toEqual(['Some(1)']);
|
|
77
|
-
expect(calls[1]).toEqual(['Err', 'fail']);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('serialises option/result to JSON friendly data', () => {
|
|
81
|
-
expect(toJSONOption(some(2))).toEqual({ kind: 'some', value: 2 });
|
|
82
|
-
expect(toJSONOption(none)).toEqual({ kind: 'none' });
|
|
83
|
-
expect(toJSONResult(ok(3))).toEqual({ status: 'ok', value: 3 });
|
|
84
|
-
expect(toJSONResult(err('fail'))).toEqual({ status: 'err', error: 'fail' });
|
|
85
|
-
});
|
|
86
|
-
});
|
package/src/devtools.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { Option, Result, isSome, isOk } from './types.js';
|
|
2
|
-
|
|
3
|
-
/** Logger function signature for custom logging. */
|
|
4
|
-
type Logger = (message: string, ...args: unknown[]) => void;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Formats an Option as a human-readable string.
|
|
8
|
-
* @param opt - The Option to format
|
|
9
|
-
* @returns "Some(value)" or "None"
|
|
10
|
-
* @example
|
|
11
|
-
* formatOption(42) // "Some(42)"
|
|
12
|
-
* formatOption(null) // "None"
|
|
13
|
-
* formatOption(undefined) // "None"
|
|
14
|
-
*/
|
|
15
|
-
export function formatOption<T>(opt: Option<T>): string {
|
|
16
|
-
return isSome(opt) ? `Some(${String(opt)})` : 'None';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Formats a Result as a human-readable string.
|
|
21
|
-
* For Err containing an Error, displays the error message.
|
|
22
|
-
* @param result - The Result to format
|
|
23
|
-
* @returns "Ok(value)" or "Err(error)"
|
|
24
|
-
* @example
|
|
25
|
-
* formatResult(42) // "Ok(42)"
|
|
26
|
-
* formatResult(err('fail')) // "Err(fail)"
|
|
27
|
-
* formatResult(err(new Error('oops'))) // "Err(oops)"
|
|
28
|
-
*/
|
|
29
|
-
export function formatResult<T, E>(result: Result<T, E>): string {
|
|
30
|
-
if (isOk(result)) {
|
|
31
|
-
return `Ok(${String(result)})`;
|
|
32
|
-
}
|
|
33
|
-
const error = (result as { error: E }).error;
|
|
34
|
-
return `Err(${error instanceof Error ? error.message : String(error)})`;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Inspects an Option, returning a tagged object for debugging or serialization.
|
|
39
|
-
* @param opt - The Option to inspect
|
|
40
|
-
* @returns `{ kind: 'some', value: T }` or `{ kind: 'none' }`
|
|
41
|
-
* @example
|
|
42
|
-
* inspectOption(42) // { kind: 'some', value: 42 }
|
|
43
|
-
* inspectOption(null) // { kind: 'none' }
|
|
44
|
-
*/
|
|
45
|
-
export function inspectOption<T>(opt: Option<T>) {
|
|
46
|
-
return isSome(opt) ? { kind: 'some' as const, value: opt } : { kind: 'none' as const };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Inspects a Result, returning a tagged object for debugging or serialization.
|
|
51
|
-
* @param result - The Result to inspect
|
|
52
|
-
* @returns `{ status: 'ok', value: T }` or `{ status: 'err', error: E }`
|
|
53
|
-
* @example
|
|
54
|
-
* inspectResult(42) // { status: 'ok', value: 42 }
|
|
55
|
-
* inspectResult(err('fail')) // { status: 'err', error: 'fail' }
|
|
56
|
-
*/
|
|
57
|
-
export function inspectResult<T, E>(result: Result<T, E>) {
|
|
58
|
-
return isOk(result) ? { status: 'ok' as const, value: result } : { status: 'err' as const, error: (result as { error: E }).error };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Logs an Option using the provided logger (defaults to console.log).
|
|
63
|
-
* @param opt - The Option to log
|
|
64
|
-
* @param logger - The logging function to use
|
|
65
|
-
* @example
|
|
66
|
-
* logOption(42) // logs "Some(42)"
|
|
67
|
-
* logOption(null) // logs "None"
|
|
68
|
-
* logOption(42, console.warn) // logs "Some(42)" as warning
|
|
69
|
-
*/
|
|
70
|
-
export function logOption<T>(opt: Option<T>, logger: Logger = console.log): void {
|
|
71
|
-
logger(formatOption(opt));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Logs a Result using the provided logger (defaults to console.log).
|
|
76
|
-
* Logs "Ok" with the value or "Err" with the error.
|
|
77
|
-
* @param result - The Result to log
|
|
78
|
-
* @param logger - The logging function to use
|
|
79
|
-
* @example
|
|
80
|
-
* logResult(42) // logs "Ok", 42
|
|
81
|
-
* logResult(err('fail')) // logs "Err", "fail"
|
|
82
|
-
* logResult(42, console.warn) // logs "Ok", 42 as warning
|
|
83
|
-
*/
|
|
84
|
-
export function logResult<T, E>(result: Result<T, E>, logger: Logger = console.log): void {
|
|
85
|
-
const tagged = inspectResult(result);
|
|
86
|
-
if (tagged.status === 'ok') {
|
|
87
|
-
logger(`Ok`, tagged.value);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
logger(`Err`, tagged.error);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** Alias for inspectOption. Returns a JSON-serializable representation. */
|
|
94
|
-
export const toJSONOption = inspectOption;
|
|
95
|
-
|
|
96
|
-
/** Alias for inspectResult. Returns a JSON-serializable representation. */
|
|
97
|
-
export const toJSONResult = inspectResult;
|
package/src/testing.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { isOk, isErr, isSome, isNone, Result, Err, Option } from './types.js';
|
|
2
|
-
import { formatOption, formatResult } from './devtools.js';
|
|
3
|
-
|
|
4
|
-
/** Result shape returned by custom matchers. */
|
|
5
|
-
type MatcherResult = { pass: boolean; message(): string };
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Asserts that a Result is Ok and returns the value.
|
|
9
|
-
* Throws if the Result is Err.
|
|
10
|
-
* @param result - The Result to check
|
|
11
|
-
* @param message - Optional custom error message
|
|
12
|
-
* @returns The Ok value
|
|
13
|
-
* @throws {Error} If the Result is Err
|
|
14
|
-
* @example
|
|
15
|
-
* expectOk(ok(42)) // returns 42
|
|
16
|
-
* expectOk(err('fail')) // throws Error
|
|
17
|
-
*/
|
|
18
|
-
export function expectOk<T, E>(result: Result<T, E>, message?: string): T {
|
|
19
|
-
if (isOk(result)) {
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const fallback = message ?? `Expected Ok(...) but received ${formatResult(result)}`;
|
|
24
|
-
throw new Error(fallback);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Asserts that a Result is Err and returns the error.
|
|
29
|
-
* Throws if the Result is Ok.
|
|
30
|
-
* @param result - The Result to check
|
|
31
|
-
* @param message - Optional custom error message
|
|
32
|
-
* @returns The error value
|
|
33
|
-
* @throws {Error} If the Result is Ok
|
|
34
|
-
* @example
|
|
35
|
-
* expectErr(err('fail')) // returns 'fail'
|
|
36
|
-
* expectErr(ok(42)) // throws Error
|
|
37
|
-
*/
|
|
38
|
-
export function expectErr<T, E>(result: Result<T, E>, message?: string): E {
|
|
39
|
-
if (isErr(result)) {
|
|
40
|
-
return (result as Err<E>).error;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const fallback = message ?? `Expected Err(...) but received ${formatResult(result)}`;
|
|
44
|
-
throw new Error(fallback);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Asserts that an Option is Some and returns the value.
|
|
49
|
-
* Throws if the Option is None.
|
|
50
|
-
* @param opt - The Option to check
|
|
51
|
-
* @param message - Optional custom error message
|
|
52
|
-
* @returns The Some value
|
|
53
|
-
* @throws {Error} If the Option is None
|
|
54
|
-
* @example
|
|
55
|
-
* expectSome(42) // returns 42
|
|
56
|
-
* expectSome(null) // throws Error
|
|
57
|
-
*/
|
|
58
|
-
export function expectSome<T>(opt: Option<T>, message?: string): T {
|
|
59
|
-
if (isSome(opt)) {
|
|
60
|
-
return opt;
|
|
61
|
-
}
|
|
62
|
-
const fallback = message ?? `Expected Some(...) but received ${formatOption(opt)}`;
|
|
63
|
-
throw new Error(fallback);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Asserts that an Option is None.
|
|
68
|
-
* Throws if the Option is Some.
|
|
69
|
-
* @param opt - The Option to check
|
|
70
|
-
* @param message - Optional custom error message
|
|
71
|
-
* @throws {Error} If the Option is Some
|
|
72
|
-
* @example
|
|
73
|
-
* expectNone(null) // succeeds
|
|
74
|
-
* expectNone(42) // throws Error
|
|
75
|
-
*/
|
|
76
|
-
export function expectNone<T>(opt: Option<T>, message?: string): void {
|
|
77
|
-
if (isNone(opt)) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const fallback = message ?? `Expected None but received ${formatOption(opt)}`;
|
|
81
|
-
throw new Error(fallback);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const resultMatchers = {
|
|
85
|
-
toBeOk(this: unknown, received: Result<unknown, unknown>): MatcherResult {
|
|
86
|
-
const pass = isOk(received);
|
|
87
|
-
return {
|
|
88
|
-
pass,
|
|
89
|
-
message: () => (pass ? 'Result is Ok as expected.' : `Expected Ok(...) but received ${formatResult(received)}`),
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
toBeErr(this: unknown, received: Result<unknown, unknown>): MatcherResult {
|
|
93
|
-
const pass = isErr(received);
|
|
94
|
-
return {
|
|
95
|
-
pass,
|
|
96
|
-
message: () => (pass ? 'Result is Err as expected.' : `Expected Err(...) but received ${formatResult(received)}`),
|
|
97
|
-
};
|
|
98
|
-
},
|
|
99
|
-
toContainErr(this: unknown, received: Result<unknown, unknown>, expected: unknown): MatcherResult {
|
|
100
|
-
const pass = isErr(received) && (received as Err<unknown>).error === expected;
|
|
101
|
-
return {
|
|
102
|
-
pass,
|
|
103
|
-
message: () => {
|
|
104
|
-
if (pass) return `Err matched expected value ${String(expected)}.`;
|
|
105
|
-
return `Expected Err(${String(expected)}) but received ${formatResult(received)}`;
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const optionMatchers = {
|
|
112
|
-
toBeSome(this: unknown, received: Option<unknown>): MatcherResult {
|
|
113
|
-
const pass = isSome(received);
|
|
114
|
-
return {
|
|
115
|
-
pass,
|
|
116
|
-
message: () => (pass ? 'Option is Some as expected.' : `Expected Some(...) but received ${formatOption(received)}`),
|
|
117
|
-
};
|
|
118
|
-
},
|
|
119
|
-
toBeNone(this: unknown, received: Option<unknown>): MatcherResult {
|
|
120
|
-
const pass = isNone(received);
|
|
121
|
-
return {
|
|
122
|
-
pass,
|
|
123
|
-
message: () => (pass ? 'Option is None as expected.' : `Expected None but received ${formatOption(received)}`),
|
|
124
|
-
};
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Custom matchers for Jest/Vitest.
|
|
130
|
-
* Includes toBeOk, toBeErr, toContainErr, toBeSome, toBeNone.
|
|
131
|
-
* Use with expect.extend(matchers) or extendExpect(expect).
|
|
132
|
-
*/
|
|
133
|
-
export const matchers = {
|
|
134
|
-
...resultMatchers,
|
|
135
|
-
...optionMatchers,
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
/** Interface for test frameworks with an extend method (Jest, Vitest). */
|
|
139
|
-
export type ExpectLike = {
|
|
140
|
-
extend(matchers: Record<string, (...args: any[]) => MatcherResult>): void;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Extends a test framework's expect with Option and Result matchers.
|
|
145
|
-
* @param expectLike - The expect object to extend (Jest/Vitest)
|
|
146
|
-
* @example
|
|
147
|
-
* import { expect } from 'vitest';
|
|
148
|
-
* import { extendExpect } from 'nalloc/testing';
|
|
149
|
-
* extendExpect(expect);
|
|
150
|
-
*
|
|
151
|
-
* // Now you can use:
|
|
152
|
-
* expect(result).toBeOk();
|
|
153
|
-
* expect(result).toBeErr();
|
|
154
|
-
* expect(option).toBeSome();
|
|
155
|
-
* expect(option).toBeNone();
|
|
156
|
-
*/
|
|
157
|
-
export function extendExpect(expectLike: ExpectLike): void {
|
|
158
|
-
expectLike.extend(matchers);
|
|
159
|
-
}
|