nalloc 0.2.2 → 0.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 (67) hide show
  1. package/README.md +326 -178
  2. package/build/codemod-cli.cjs +153 -0
  3. package/build/codemod-cli.cjs.map +1 -0
  4. package/build/codemod-cli.d.ts +2 -0
  5. package/build/codemod-cli.js +103 -0
  6. package/build/codemod-cli.js.map +1 -0
  7. package/build/codemod.cjs +652 -0
  8. package/build/codemod.cjs.map +1 -0
  9. package/build/codemod.d.ts +29 -0
  10. package/build/codemod.js +634 -0
  11. package/build/codemod.js.map +1 -0
  12. package/build/eslint.cjs +221 -0
  13. package/build/eslint.cjs.map +1 -0
  14. package/build/eslint.d.ts +36 -0
  15. package/build/eslint.js +198 -0
  16. package/build/eslint.js.map +1 -0
  17. package/build/http.cjs +31 -0
  18. package/build/http.cjs.map +1 -0
  19. package/build/http.d.ts +31 -0
  20. package/build/http.js +13 -0
  21. package/build/http.js.map +1 -0
  22. package/build/nonempty.cjs +35 -0
  23. package/build/nonempty.cjs.map +1 -0
  24. package/build/nonempty.d.ts +34 -0
  25. package/build/nonempty.js +14 -0
  26. package/build/nonempty.js.map +1 -0
  27. package/build/option.cjs +1 -1
  28. package/build/option.cjs.map +1 -1
  29. package/build/option.d.ts +2 -2
  30. package/build/option.js +1 -1
  31. package/build/option.js.map +1 -1
  32. package/build/result.cjs +10 -18
  33. package/build/result.cjs.map +1 -1
  34. package/build/result.d.ts +3 -34
  35. package/build/result.js +10 -15
  36. package/build/result.js.map +1 -1
  37. package/build/safe.cjs +8 -0
  38. package/build/safe.cjs.map +1 -1
  39. package/build/safe.d.ts +3 -0
  40. package/build/safe.js +2 -0
  41. package/build/safe.js.map +1 -1
  42. package/build/schema.cjs +32 -0
  43. package/build/schema.cjs.map +1 -0
  44. package/build/schema.d.ts +44 -0
  45. package/build/schema.js +14 -0
  46. package/build/schema.js.map +1 -0
  47. package/package.json +63 -10
  48. package/src/__tests__/codemod.ts +211 -0
  49. package/src/__tests__/eslint.ts +99 -0
  50. package/src/__tests__/fixtures/tsconfig.json +10 -0
  51. package/src/__tests__/http.ts +64 -0
  52. package/src/__tests__/iter.ts +18 -0
  53. package/src/__tests__/nonempty.ts +46 -0
  54. package/src/__tests__/nonempty.types.ts +38 -0
  55. package/src/__tests__/option.ts +4 -0
  56. package/src/__tests__/result.ts +104 -129
  57. package/src/__tests__/result.types.ts +2 -2
  58. package/src/__tests__/schema.ts +58 -0
  59. package/src/codemod-cli.ts +108 -0
  60. package/src/codemod.ts +623 -0
  61. package/src/eslint.ts +145 -0
  62. package/src/http.ts +42 -0
  63. package/src/nonempty.ts +48 -0
  64. package/src/option.ts +3 -4
  65. package/src/result.ts +18 -49
  66. package/src/safe.ts +3 -0
  67. package/src/schema.ts +52 -0
@@ -0,0 +1,64 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
+ import { fromResponse, fromFetch } from '../http.js';
3
+ import { isOk, isErr } from '../types.js';
4
+
5
+ describe('http', () => {
6
+ describe('fromResponse', () => {
7
+ it('returns Ok carrying the response for a 2xx status', () => {
8
+ const response = new Response('ok', { status: 200 });
9
+ const result = fromResponse(response);
10
+ expect(isOk(result)).toBe(true);
11
+ expect(result).toBe(response);
12
+ });
13
+
14
+ it('returns Err carrying the response for a non-2xx status', () => {
15
+ const response = new Response('nope', { status: 404 });
16
+ const result = fromResponse(response);
17
+ expect(isErr(result)).toBe(true);
18
+ expect((result as { error: Response }).error).toBe(response);
19
+ });
20
+ });
21
+
22
+ describe('fromFetch', () => {
23
+ afterEach(() => {
24
+ vi.unstubAllGlobals();
25
+ });
26
+
27
+ it('returns Ok carrying the response for a 2xx status', async () => {
28
+ const response = new Response('ok', { status: 200 });
29
+ const fetchMock = vi.fn().mockResolvedValue(response);
30
+ vi.stubGlobal('fetch', fetchMock);
31
+ const init = { method: 'POST' };
32
+ const result = await fromFetch('https://example.test', init);
33
+ expect(isOk(result)).toBe(true);
34
+ expect(result).toBe(response);
35
+ expect(fetchMock).toHaveBeenCalledWith('https://example.test', init);
36
+ });
37
+
38
+ it('returns Err carrying the response for a non-2xx status', async () => {
39
+ const response = new Response('nope', { status: 500 });
40
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue(response));
41
+ const result = await fromFetch('https://example.test');
42
+ expect(isErr(result)).toBe(true);
43
+ expect((result as { error: Response }).error).toBe(response);
44
+ });
45
+
46
+ it('returns Err carrying the thrown value on transport failure', async () => {
47
+ const failure = new TypeError('fetch failed');
48
+ vi.stubGlobal('fetch', vi.fn().mockRejectedValue(failure));
49
+ const result = await fromFetch('https://example.test');
50
+ expect(isErr(result)).toBe(true);
51
+ expect((result as { error: unknown }).error).toBe(failure);
52
+ });
53
+
54
+ it('returns Err with an AbortError DOMException for a pre-aborted signal', async () => {
55
+ const controller = new AbortController();
56
+ controller.abort();
57
+ const result = await fromFetch('http://127.0.0.1:1', { signal: controller.signal });
58
+ expect(isErr(result)).toBe(true);
59
+ const error = (result as { error: unknown }).error;
60
+ expect(error).toBeInstanceOf(DOMException);
61
+ expect((error as DOMException).name).toBe('AbortError');
62
+ });
63
+ });
64
+ });
@@ -96,6 +96,24 @@ describe('Iter', () => {
96
96
  expect(returned).toBe(true);
97
97
  });
98
98
 
99
+ it('return() after exhaustion is a no-op', () => {
100
+ let returnCalls = 0;
101
+ const iter: Iterable<number> = {
102
+ [Symbol.iterator]: () => {
103
+ let i = 0;
104
+ return {
105
+ next() { return i++ < 1 ? { value: i, done: false } : { value: undefined as unknown as number, done: true }; },
106
+ return() { returnCalls++; return { value: undefined, done: true }; },
107
+ };
108
+ },
109
+ };
110
+ const gen = safeIter(iter);
111
+ expect([...gen]).toHaveLength(1);
112
+ const final = gen.return!(undefined as never);
113
+ expect(final.done).toBe(true);
114
+ expect(returnCalls).toBe(0);
115
+ });
116
+
99
117
  it('yields values then stops on throw', () => {
100
118
  function* twoThenThrow() {
101
119
  yield 1;
@@ -0,0 +1,46 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { isNonEmpty, assertNonEmpty, fromArray } from '../nonempty.js';
3
+ import { isSome, isNone } from '../types.js';
4
+
5
+ describe('NonEmpty', () => {
6
+ describe('isNonEmpty', () => {
7
+ it('returns false for an empty array', () => {
8
+ expect(isNonEmpty([])).toBe(false);
9
+ });
10
+
11
+ it('returns true for a single-element array', () => {
12
+ expect(isNonEmpty([1])).toBe(true);
13
+ });
14
+
15
+ it('returns true for a multi-element array', () => {
16
+ expect(isNonEmpty([1, 2, 3])).toBe(true);
17
+ });
18
+ });
19
+
20
+ describe('assertNonEmpty', () => {
21
+ it('throws on an empty array', () => {
22
+ expect(() => assertNonEmpty([])).toThrow('Expected array to be non-empty');
23
+ });
24
+
25
+ it('throws with a custom message', () => {
26
+ expect(() => assertNonEmpty([], 'nope')).toThrow('nope');
27
+ });
28
+
29
+ it('does not throw on a non-empty array', () => {
30
+ expect(() => assertNonEmpty([1])).not.toThrow();
31
+ });
32
+ });
33
+
34
+ describe('fromArray', () => {
35
+ it('returns None for an empty array', () => {
36
+ expect(isNone(fromArray([]))).toBe(true);
37
+ });
38
+
39
+ it('returns Some wrapping the same array value for a non-empty array', () => {
40
+ const input = [1, 2];
41
+ const result = fromArray(input);
42
+ expect(isSome(result)).toBe(true);
43
+ expect(result).toBe(input);
44
+ });
45
+ });
46
+ });
@@ -0,0 +1,38 @@
1
+ import { assert, type Equals } from 'tsafe';
2
+ import {
3
+ isNonEmpty,
4
+ assertNonEmpty,
5
+ fromArray,
6
+ type NonEmptyArray,
7
+ type ReadonlyNonEmptyArray,
8
+ } from '../nonempty.js';
9
+ import type { Option } from '../types.js';
10
+
11
+ const readonlyValues: readonly number[] = [1, 2, 3];
12
+ const mutableValues: number[] = [1, 2, 3];
13
+
14
+ if (isNonEmpty(readonlyValues)) {
15
+ assert<Equals<typeof readonlyValues, ReadonlyNonEmptyArray<number>>>;
16
+ const _head: number = readonlyValues[0];
17
+ }
18
+
19
+ if (isNonEmpty(mutableValues)) {
20
+ const _head: number = mutableValues[0];
21
+ }
22
+
23
+ const asserted: readonly number[] = [1];
24
+ assertNonEmpty(asserted);
25
+ assert<Equals<typeof asserted, ReadonlyNonEmptyArray<number>>>;
26
+ const _assertedHead: number = asserted[0];
27
+
28
+ const maybeNonEmpty = fromArray<number>([1, 2]);
29
+ assert<Equals<typeof maybeNonEmpty, Option<ReadonlyNonEmptyArray<number>>>>;
30
+
31
+ const fromEmpty = fromArray([] as const);
32
+ assert<Equals<typeof fromEmpty, Option<ReadonlyNonEmptyArray<never>>>>;
33
+
34
+ type _MutableShape = Equals<NonEmptyArray<number>, [number, ...number[]]>;
35
+ assert<_MutableShape>;
36
+
37
+ type _ReadonlyShape = Equals<ReadonlyNonEmptyArray<number>, readonly [number, ...number[]]>;
38
+ assert<_ReadonlyShape>;
@@ -426,6 +426,10 @@ describe('Option', () => {
426
426
  it('returns false for None', () => {
427
427
  expect(contains(none, 42)).toBe(false);
428
428
  });
429
+
430
+ it('treats NaN as equal to NaN', () => {
431
+ expect(contains(of(NaN), NaN)).toBe(true);
432
+ });
429
433
  });
430
434
 
431
435
  describe('isSomeAnd', () => {