functionalscript 0.32.3 → 0.33.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 (41) hide show
  1. package/fs/bnf/data/proof.f.d.ts +3 -0
  2. package/fs/bnf/data/proof.f.js +7 -0
  3. package/fs/cas/mcp/module.f.d.ts +4 -4
  4. package/fs/cas/mcp/module.f.js +21 -17
  5. package/fs/cas/mcp/proof.f.d.ts +1 -0
  6. package/fs/cas/mcp/proof.f.js +62 -42
  7. package/fs/cas/module.f.d.ts +13 -21
  8. package/fs/cas/module.f.js +100 -54
  9. package/fs/cas/proof.f.js +15 -24
  10. package/fs/ci/config/module.f.d.ts +6 -6
  11. package/fs/ci/config/module.f.js +6 -6
  12. package/fs/ci/proof.f.js +8 -6
  13. package/fs/cli/proof.f.js +2 -12
  14. package/fs/djs/parser/module.f.d.ts +0 -5
  15. package/fs/djs/proof.f.js +5 -6
  16. package/fs/djs/serializer/module.f.d.ts +1 -3
  17. package/fs/djs/tokenizer-new/module.f.js +2 -1
  18. package/fs/djs/tokenizer-new/proof.f.d.ts +1 -0
  19. package/fs/djs/tokenizer-new/proof.f.js +101 -67
  20. package/fs/djs/transpiler/proof.f.js +10 -10
  21. package/fs/effects/node/module.f.d.ts +8 -2
  22. package/fs/effects/node/module.f.js +3 -0
  23. package/fs/effects/node/module.js +21 -1
  24. package/fs/effects/node/proof.f.d.ts +15 -0
  25. package/fs/effects/node/proof.f.js +137 -26
  26. package/fs/effects/node/virtual/module.f.d.ts +18 -2
  27. package/fs/effects/node/virtual/module.f.js +185 -10
  28. package/fs/effects/node/virtual/proof.f.d.ts +14 -0
  29. package/fs/effects/node/virtual/proof.f.js +98 -5
  30. package/fs/emergent_testing/proof.f.js +3 -11
  31. package/fs/fjs/module.f.js +3 -3
  32. package/fs/fjs/proof.f.js +2 -11
  33. package/fs/js/tokenizer/module.f.d.ts +5 -0
  34. package/fs/js/tokenizer/module.f.js +13 -0
  35. package/fs/json/serializer/module.f.js +0 -1
  36. package/fs/text/sgr/proof.f.js +2 -11
  37. package/fs/types/bigint/module.f.d.ts +8 -15
  38. package/fs/types/bigint/module.f.js +9 -22
  39. package/fs/types/bigint/proof.f.d.ts +0 -2
  40. package/fs/types/bigint/proof.f.js +6 -16
  41. package/package.json +2 -2
@@ -1,11 +1,11 @@
1
1
  import { assertEq } from "../../../asserts/module.f.js";
2
- import { awaitIfPromise, fetch, rm, writeFile, readFile, readdir, import_ } from "../module.f.js";
3
- import { vec8 } from "../../../types/bit_vec/module.f.js";
2
+ import { awaitIfPromise, fetch, rm, writeFile, readFile, readdir, import_, rename, readBytes } from "../module.f.js";
3
+ import { maxLengthBytes, vec, vec8 } from "../../../types/bit_vec/module.f.js";
4
4
  import { emptyState, virtual } from "./module.f.js";
5
5
  export const proof = {
6
6
  rm: {
7
7
  success: () => {
8
- const root = { 'a.txt': vec8(0x42n) };
8
+ const root = { 'a.txt': [vec8(0x42n)] };
9
9
  const [, result] = virtual({ ...emptyState, root })(rm('a.txt'));
10
10
  assertEq(result[0], 'ok');
11
11
  },
@@ -27,7 +27,7 @@ export const proof = {
27
27
  assertEq(result[0], 'error');
28
28
  },
29
29
  readdirRecursive: () => {
30
- const file = vec8(0x42n);
30
+ const file = [vec8(0x42n)];
31
31
  const sub = { 'file.txt': file };
32
32
  const outer = { 'sub': sub };
33
33
  const root = { 'mydir': outer };
@@ -65,7 +65,7 @@ export const proof = {
65
65
  },
66
66
  importNonModule: () => {
67
67
  // import_ on a Vec (not a JsModule) covers typeof entry !== 'function' branch
68
- const root = { 'module.f.ts': vec8(0x42n) };
68
+ const root = { 'module.f.ts': [vec8(0x42n)] };
69
69
  const [, result] = virtual({ ...emptyState, root })(import_('module.f.ts'));
70
70
  assertEq(result[0], 'error');
71
71
  },
@@ -76,4 +76,97 @@ export const proof = {
76
76
  virtual({ ...emptyState, root })(readFile('a.f.ts'));
77
77
  },
78
78
  },
79
+ renameSamePath: () => {
80
+ // rename('a', 'a') should succeed as a no-op, not reject
81
+ const root = { 'a': [vec8(0x42n)] };
82
+ const [, result] = virtual({ ...emptyState, root })(rename('a', 'a'));
83
+ assertEq(result[0], 'ok');
84
+ },
85
+ renameIntoOwnSubtree: () => {
86
+ // rename('a', 'a/b') should fail (dst inside src's subtree)
87
+ const root = { 'a': { 'b': [vec8(0x42n)] } };
88
+ const [, result] = virtual({ ...emptyState, root })(rename('a', 'a/b'));
89
+ assertEq(result[0], 'error');
90
+ },
91
+ renameOntoOwnAncestor: () => {
92
+ // rename('a/b', 'a') should fail (src inside dst's subtree)
93
+ const root = { 'a': { 'b': [vec8(0x42n)] } };
94
+ const [, result] = virtual({ ...emptyState, root })(rename('a/b', 'a'));
95
+ assertEq(result[0], 'error');
96
+ },
97
+ renameNonEmptyDirOverEmptyDir: () => {
98
+ // rename a directory onto an empty directory should succeed
99
+ const root = { 'src': { 'file': [vec8(0x42n)] }, 'dst': {} };
100
+ const [, result] = virtual({ ...emptyState, root })(rename('src', 'dst'));
101
+ assertEq(result[0], 'ok');
102
+ },
103
+ renameEmptyDirOverNonEmptyDir: () => {
104
+ // rename an empty directory onto a non-empty directory should fail
105
+ const root = { 'src': {}, 'dst': { 'file': [vec8(0x42n)] } };
106
+ const [, result] = virtual({ ...emptyState, root })(rename('src', 'dst'));
107
+ assertEq(result[0], 'error');
108
+ },
109
+ renameFileOntoDirectory: () => {
110
+ // rename a file to a path that is already an existing directory should fail
111
+ const root = { 'myfile': [vec8(0x42n)], 'mydir': {} };
112
+ const [, result] = virtual({ ...emptyState, root })(rename('myfile', 'mydir'));
113
+ assertEq(result[0], 'error');
114
+ },
115
+ readFileTooLarge: () => {
116
+ // a file stored as two max-size chunks exceeds the limit; readFile must return an error
117
+ const chunk0 = vec(maxLengthBytes * 8n)(0n);
118
+ const chunk1 = vec(1n)(1n);
119
+ const root = { 'big': [chunk0, chunk1] };
120
+ const [, result] = virtual({ ...emptyState, root })(readFile('big'));
121
+ assertEq(result[0], 'error');
122
+ },
123
+ readBytesNegativeSize: () => {
124
+ // readBytes with negative size should fail
125
+ const root = { 'file': [vec8(0x42n)] };
126
+ const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, -1));
127
+ assertEq(result[0], 'error');
128
+ },
129
+ readBytesZeroSize: () => {
130
+ // readBytes with zero size should succeed and return empty vec
131
+ const root = { 'file': [vec8(0x42n)] };
132
+ const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, 0));
133
+ assertEq(result[0], 'ok');
134
+ },
135
+ readBytesNegativeOffset: () => {
136
+ // readBytes with negative offset should fail
137
+ const root = { 'file': [vec8(0x42n)] };
138
+ const [, result] = virtual({ ...emptyState, root })(readBytes('file', -1, 1));
139
+ assertEq(result[0], 'error');
140
+ },
141
+ readBytesFractionalSize: () => {
142
+ // readBytes with fractional size should fail rather than throw RangeError
143
+ const root = { 'file': [vec8(0x42n)] };
144
+ const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, 1.5));
145
+ assertEq(result[0], 'error');
146
+ },
147
+ readBytesFractionalOffset: () => {
148
+ // readBytes with fractional offset should fail rather than throw RangeError
149
+ const root = { 'file': [vec8(0x42n)] };
150
+ const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0.5, 1));
151
+ assertEq(result[0], 'error');
152
+ },
153
+ readBytesAcrossChunkBoundary: () => {
154
+ // Two 128 KiB chunks; read 2 bytes spanning the boundary (last byte of chunk 0, first of chunk 1).
155
+ const chunkSize = Number(maxLengthBytes);
156
+ const chunk0 = vec(maxLengthBytes * 8n)(0xaan);
157
+ const chunk1 = vec(maxLengthBytes * 8n)(0xbbn);
158
+ const root = { 'big': [chunk0, chunk1] };
159
+ const [, result] = virtual({ ...emptyState, root })(readBytes('big', chunkSize - 1, 2));
160
+ assertEq(result[0], 'ok');
161
+ },
162
+ largeFileReadBytes: () => {
163
+ // A file stored as two 128 KiB chunks is larger than maxLengthBytes.
164
+ // readBytes within the second chunk (offset = 128 KiB, size = 1) should succeed.
165
+ const chunkSize = Number(maxLengthBytes);
166
+ const chunk0 = vec(maxLengthBytes * 8n)(0n);
167
+ const chunk1 = vec(maxLengthBytes * 8n)(0xffn);
168
+ const root = { 'large': [chunk0, chunk1] };
169
+ const [, result] = virtual({ ...emptyState, root })(readBytes('large', chunkSize, 1));
170
+ assertEq(result[0], 'ok');
171
+ },
79
172
  };
@@ -1,8 +1,7 @@
1
- import { pure } from "../effects/module.f.js";
2
1
  import { log } from "../effects/node/module.f.js";
3
- import { emptyState } from "../effects/node/virtual/module.f.js";
2
+ import { defaultNodeProgramOptions, emptyState } from "../effects/node/virtual/module.f.js";
4
3
  import { virtual } from "../effects/node/virtual/module.f.js";
5
- import { assert, assertEq, todo } from "../asserts/module.f.js";
4
+ import { assert, assertEq } from "../asserts/module.f.js";
6
5
  import { testAll, defaultReporter, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier, registerModule, parseTestSet, defaultTest, } from "./module.f.js";
7
6
  import { run as mockRun } from "../effects/mock/module.f.js";
8
7
  import { shouldLoad } from "../dev/module.f.js";
@@ -13,16 +12,9 @@ const makeReporter = () => ({
13
12
  summary: (pass, fail, time) => writeEvent(['summary', pass, fail, time]),
14
13
  test: defaultTest,
15
14
  });
16
- const noopTestContext = { test: todo };
17
15
  const options = (initCwd, github = false) => ({
18
- args: [],
16
+ ...defaultNodeProgramOptions,
19
17
  env: { INIT_CWD: initCwd, ...(github ? { GITHUB_ACTIONS: 'true' } : {}) },
20
- home: '.',
21
- std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
22
- testContext: noopTestContext,
23
- bunTestContext: noopTestContext,
24
- playwrightTestContext: noopTestContext,
25
- engine: 'node',
26
18
  });
27
19
  const ok0 = () => ({ result: ['ok', undefined], duration: 0 });
28
20
  const fail0 = () => ({ result: ['error', 'oops'], duration: 0 });
@@ -5,12 +5,12 @@
5
5
  */
6
6
  import { compile } from "../djs/module.f.js";
7
7
  import { main as testMain } from "../emergent_testing/module.f.js";
8
- import { commands as casCommands } from "../cas/module.f.js";
8
+ import { commands as casCommands, fileCas } from "../cas/module.f.js";
9
9
  import { main as ciMain } from "../ci/module.f.js";
10
10
  import { import_ } from "../effects/node/module.f.js";
11
11
  import { dispatch } from "../cli/module.f.js";
12
12
  import { casMcpServer } from "../cas/mcp/module.f.js";
13
- import { cas, fileKvStore, toPath } from "../cas/module.f.js";
13
+ import { toPath } from "../cas/module.f.js";
14
14
  import { sha256 } from "../crypto/sha2/module.f.js";
15
15
  import { join } from "../path/module.f.js";
16
16
  import { pure } from "../effects/module.f.js";
@@ -34,7 +34,7 @@ const commands = [
34
34
  names: ['mcp', 'm'],
35
35
  description: 'Run an MCP server over stdio exposing the CAS as tools',
36
36
  handler: ({ home }) => {
37
- const c = cas(sha256)(fileKvStore(home));
37
+ const c = fileCas(sha256)(home);
38
38
  return casMcpServer(c, home, hash => join(home, toPath(hash))).step(() => pure(0));
39
39
  },
40
40
  },
package/fs/fjs/proof.f.js CHANGED
@@ -1,17 +1,8 @@
1
1
  import { assert, assertEq } from "../asserts/module.f.js";
2
2
  import { pure } from "../effects/module.f.js";
3
- import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
3
+ import { defaultNodeProgramOptions, emptyState, virtual } from "../effects/node/virtual/module.f.js";
4
4
  import { main } from "./module.f.js";
5
- const makeOptions = (args) => ({
6
- args,
7
- env: {},
8
- home: '.',
9
- std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
10
- testContext: { test: async () => { } },
11
- bunTestContext: { test: async () => { } },
12
- playwrightTestContext: { test: async () => { } },
13
- engine: 'node',
14
- });
5
+ const makeOptions = (args) => ({ ...defaultNodeProgramOptions, args });
15
6
  const run = (root) => (args) => virtual({ ...emptyState, root })(main(makeOptions(args)));
16
7
  const appMain = ({ args }) => pure(args.length);
17
8
  export const proof = {
@@ -95,4 +95,9 @@ export type JsTokenWithMetadata = {
95
95
  type ErrorMessage = '" are missing' | 'unescaped character' | 'invalid hex value' | 'unexpected character' | 'invalid number' | 'invalid token' | '*\/ expected' | 'unterminated string literal' | 'eof';
96
96
  export declare const isKeywordToken: (token: JsToken) => boolean;
97
97
  export declare const tokenize: (input: List<number>) => (path: string) => List<JsTokenWithMetadata>;
98
+ export declare const proof: {
99
+ throw: {
100
+ unionConflict: () => void;
101
+ };
102
+ };
98
103
  export {};
@@ -27,6 +27,7 @@ leftSquareBracket, reverseSolidus, rightSquareBracket, lowLine,
27
27
  latinSmallLetterRange, latinSmallLetterA, latinSmallLetterB, latinSmallLetterE, latinSmallLetterF, latinSmallLetterN, latinSmallLetterR, latinSmallLetterT, latinSmallLetterU,
28
28
  //
29
29
  leftCurlyBracket, rightCurlyBracket, dollarSign } from "../../text/ascii/module.f.js";
30
+ import { todo } from "../../asserts/module.f.js";
30
31
  const { fromCharCode } = String;
31
32
  const rangeOneNine = range('19');
32
33
  const rangeSetNewLine = [
@@ -519,3 +520,15 @@ export const tokenize = input => path => {
519
520
  const scan = scanTokenize({ state: { kind: 'initial' }, metadata: { path, line: 1, column: 1 } });
520
521
  return flat(scan(flat([input /*satisfies List<CharCodeOrEof>*/, [null]])));
521
522
  };
523
+ export const proof = {
524
+ throw: {
525
+ // union throws when two distinct non-default handlers are merged for the same range;
526
+ // this path is unreachable through the public API (no overlapping ranges in practice).
527
+ unionConflict: () => {
528
+ const def = (_) => todo;
529
+ const a = (_) => todo;
530
+ const b = (_) => todo;
531
+ union(def)(a)(b);
532
+ }
533
+ }
534
+ };
@@ -4,7 +4,6 @@
4
4
  * @module
5
5
  */
6
6
  import { flat, reduce, empty } from "../../types/list/module.f.js";
7
- import {} from "../../types/object/module.f.js";
8
7
  import {} from "../../types/function/operator/module.f.js";
9
8
  const jsonStringify = JSON.stringify;
10
9
  /**
@@ -1,15 +1,6 @@
1
1
  import { fgRed, reset, createConsoleText, backspace, csiWrite } from "./module.f.js";
2
- import { virtual, emptyState } from "../../effects/node/virtual/module.f.js";
3
- const makeOptions = (isTTY) => ({
4
- args: [],
5
- env: {},
6
- home: '.',
7
- std: { stdout: { isTTY }, stderr: { isTTY } },
8
- testContext: { test: async () => { } },
9
- bunTestContext: { test: async () => { } },
10
- playwrightTestContext: { test: async () => { } },
11
- engine: 'node',
12
- });
2
+ import { virtual, emptyState, defaultNodeProgramOptions } from "../../effects/node/virtual/module.f.js";
3
+ const makeOptions = (isTTY) => ({ ...defaultNodeProgramOptions, std: { stdout: { isTTY }, stderr: { isTTY } } });
13
4
  export const proof = [
14
5
  () => {
15
6
  if (fgRed !== '\x1b[31m') {
@@ -156,24 +156,17 @@ export declare const xor: Reduce;
156
156
  export declare const divUp: (b: bigint) => Unary;
157
157
  export declare const roundUp: (b: bigint) => Unary;
158
158
  /**
159
- * Divides a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
159
+ * Converts a bit count to a byte count, rounding up divides by `8`.
160
160
  *
161
- * @param e - The exponent (divisor = 2^e).
162
- * @returns A function that rounds a value up by the given power of two.
163
- */
164
- export declare const divUpE2: (e: bigint) => Unary;
165
- /**
166
- * Rounds a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
167
- *
168
- * @param e - The exponent (multiple = 2^e).
169
- * @returns A function that rounds a value up to the nearest multiple of the given power of two.
170
- */
171
- export declare const roundUpE2: (e: bigint) => Unary;
172
- /**
173
- * Converts a bit count to a byte count, rounding up — divides by `8` (`2^3` bits per byte).
161
+ * Domain: non-negative inputs (bit/byte counts). On negative inputs `divUp`
162
+ * truncates toward zero rather than flooring toward −∞, so the rounding
163
+ * direction is only meaningful for `v >= 0n`.
174
164
  */
175
165
  export declare const divUp8: Unary;
176
166
  /**
177
- * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8` (`2^3` bits per byte).
167
+ * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8`.
168
+ *
169
+ * Domain: non-negative inputs (bit/byte counts). See `divUp8` for the
170
+ * truncate-vs-floor caveat on negative values.
178
171
  */
179
172
  export declare const roundUp8: Unary;
@@ -234,30 +234,17 @@ export const roundUp = (b) => {
234
234
  return v => d(v) * b;
235
235
  };
236
236
  /**
237
- * Divides a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
237
+ * Converts a bit count to a byte count, rounding up divides by `8`.
238
238
  *
239
- * @param e - The exponent (divisor = 2^e).
240
- * @returns A function that rounds a value up by the given power of two.
239
+ * Domain: non-negative inputs (bit/byte counts). On negative inputs `divUp`
240
+ * truncates toward zero rather than flooring toward −∞, so the rounding
241
+ * direction is only meaningful for `v >= 0n`.
241
242
  */
242
- export const divUpE2 = (e) => {
243
- const m = mask(e);
244
- return v => (v + m) >> e;
245
- };
243
+ export const divUp8 = divUp(8n);
246
244
  /**
247
- * Rounds a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
245
+ * Rounds a bit count up to the nearest whole byte the nearest multiple of `8`.
248
246
  *
249
- * @param e - The exponent (multiple = 2^e).
250
- * @returns A function that rounds a value up to the nearest multiple of the given power of two.
251
- */
252
- export const roundUpE2 = (e) => {
253
- const d = divUpE2(e);
254
- return v => d(v) << e;
255
- };
256
- /**
257
- * Converts a bit count to a byte count, rounding up — divides by `8` (`2^3` bits per byte).
258
- */
259
- export const divUp8 = divUpE2(3n);
260
- /**
261
- * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8` (`2^3` bits per byte).
247
+ * Domain: non-negative inputs (bit/byte counts). See `divUp8` for the
248
+ * truncate-vs-floor caveat on negative values.
262
249
  */
263
- export const roundUp8 = roundUpE2(3n);
250
+ export const roundUp8 = roundUp(8n);
@@ -29,8 +29,6 @@ export declare const proof: {
29
29
  combination3: () => void;
30
30
  divUp: () => void;
31
31
  roundUp: () => void;
32
- divUpE2: () => void;
33
- roundUpE2: () => void;
34
32
  divUp8: () => void;
35
33
  roundUp8: () => void;
36
34
  xor: () => void;
@@ -1,4 +1,4 @@
1
- import { sum, abs, serialize, log2, bitLength, mask, combination, factorial, xor, multiple, product, divUp, roundUp, divUpE2, roundUpE2, divUp8, roundUp8 } from "./module.f.js";
1
+ import { sum, abs, serialize, log2, bitLength, mask, combination, factorial, xor, multiple, product, divUp, roundUp, divUp8, roundUp8 } from "./module.f.js";
2
2
  import { assertEq } from "../../asserts/module.f.js";
3
3
  import { min } from "../function/compare/module.f.js";
4
4
  const oldLog2 = (v) => {
@@ -463,32 +463,22 @@ export const proof = {
463
463
  assertEq(roundUp(8n)(15n), 16n);
464
464
  assertEq(roundUp(8n)(3n), 8n);
465
465
  },
466
- divUpE2: () => {
467
- assertEq(divUpE2(3n)(8n), 1n);
468
- assertEq(divUpE2(3n)(15n), 2n);
469
- assertEq(divUpE2(3n)(0n), 0n);
470
- assertEq(divUpE2(3n)(8n), 1n);
471
- assertEq(divUpE2(3n)(9n), 2n);
472
- },
473
- roundUpE2: () => {
474
- assertEq(roundUpE2(3n)(8n), 8n);
475
- assertEq(roundUpE2(3n)(15n), 16n);
476
- assertEq(roundUpE2(3n)(3n), 8n);
477
- assertEq(roundUpE2(3n)(0n), 0n);
478
- assertEq(roundUpE2(3n)(8n), 8n);
479
- assertEq(roundUpE2(3n)(9n), 16n);
480
- },
481
466
  divUp8: () => {
482
467
  assertEq(divUp8(0n), 0n);
483
468
  assertEq(divUp8(1n), 1n);
484
469
  assertEq(divUp8(8n), 1n);
470
+ assertEq(divUp8(8n), 1n);
485
471
  assertEq(divUp8(9n), 2n);
472
+ assertEq(divUp8(15n), 2n);
486
473
  },
487
474
  roundUp8: () => {
488
475
  assertEq(roundUp8(0n), 0n);
489
476
  assertEq(roundUp8(1n), 8n);
477
+ assertEq(roundUp8(3n), 8n);
478
+ assertEq(roundUp8(8n), 8n);
490
479
  assertEq(roundUp8(8n), 8n);
491
480
  assertEq(roundUp8(9n), 16n);
481
+ assertEq(roundUp8(15n), 16n);
492
482
  },
493
483
  xor: () => {
494
484
  assertEq(xor(5n)(3n), 6n);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.32.3",
3
+ "version": "0.33.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -44,7 +44,7 @@
44
44
  "homepage": "https://github.com/functionalscript/functionalscript#readme",
45
45
  "devDependencies": {
46
46
  "@playwright/test": "1.61.0",
47
- "@types/node": "25.9.3",
47
+ "@types/node": "26.0.0",
48
48
  "typescript": "6.0.3"
49
49
  }
50
50
  }