functionalscript 0.17.0 → 0.19.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.
- package/fs/asn.1/module.f.js +7 -8
- package/fs/asn.1/test.f.js +11 -12
- package/fs/ci/common/module.f.d.ts +4 -5
- package/fs/ci/common/module.f.js +4 -4
- package/fs/ci/config/module.f.d.ts +5 -5
- package/fs/ci/config/module.f.js +5 -5
- package/fs/ci/test.f.js +2 -4
- package/fs/crypto/sign/module.f.js +3 -3
- package/fs/dev/module.f.d.ts +3 -3
- package/fs/dev/module.f.js +12 -9
- package/fs/dev/tf/module.d.ts +1 -1
- package/fs/dev/tf/module.f.d.ts +76 -7
- package/fs/dev/tf/module.f.js +166 -87
- package/fs/dev/tf/module.js +3 -53
- package/fs/dev/tf/scenarios/all.d.ts +1 -0
- package/fs/dev/tf/scenarios/all.js +3 -0
- package/fs/dev/tf/scenarios/fail.fail.f.d.ts +1 -0
- package/fs/dev/tf/scenarios/fail.fail.f.js +1 -0
- package/fs/dev/tf/scenarios/return-value.pass.f.d.ts +1 -0
- package/fs/dev/tf/scenarios/return-value.pass.f.js +2 -0
- package/fs/dev/tf/scenarios/throw.pass.f.d.ts +6 -0
- package/fs/dev/tf/scenarios/throw.pass.f.js +3 -0
- package/fs/dev/tf/test.f.d.ts +21 -20
- package/fs/dev/tf/test.f.js +254 -31
- package/fs/djs/module.f.d.ts +2 -2
- package/fs/djs/module.f.js +8 -5
- package/fs/djs/test.f.js +5 -6
- package/fs/djs/tokenizer-new/test.f.js +126 -78
- package/fs/djs/transpiler/module.f.js +2 -2
- package/fs/djs/transpiler/test.f.js +11 -12
- package/fs/fjs/module.f.d.ts +2 -7
- package/fs/fjs/module.f.js +16 -22
- package/fs/fjs/module.js +2 -2
- package/fs/io/module.d.ts +3 -3
- package/fs/io/module.f.d.ts +9 -2
- package/fs/io/module.f.js +13 -3
- package/fs/io/module.js +68 -17
- package/fs/path/module.f.d.ts +6 -0
- package/fs/path/module.f.js +6 -0
- package/fs/path/test.f.d.ts +3 -5
- package/fs/path/test.f.js +67 -49
- package/fs/sul/id/module.f.js +3 -4
- package/fs/sul/level/literal/module.f.js +3 -3
- package/fs/text/sgr/module.f.d.ts +9 -1
- package/fs/text/sgr/module.f.js +16 -5
- package/fs/text/sgr/test.f.js +16 -1
- package/fs/types/bit_vec/module.f.d.ts +9 -4
- package/fs/types/bit_vec/module.f.js +7 -9
- package/fs/types/btree/remove/module.f.d.ts +1 -1
- package/fs/types/btree/remove/module.f.js +7 -2
- package/fs/types/btree/set/module.f.d.ts +1 -1
- package/fs/types/btree/set/module.f.js +7 -2
- package/fs/types/btree/types/module.f.d.ts +1 -0
- package/fs/types/btree/types/module.f.js +1 -1
- package/fs/types/effects/node/module.f.d.ts +30 -17
- package/fs/types/effects/node/module.f.js +21 -2
- package/fs/types/effects/node/test.f.js +8 -5
- package/fs/types/effects/node/virtual/module.f.d.ts +12 -2
- package/fs/types/effects/node/virtual/module.f.js +31 -17
- package/fs/types/function/compare/module.f.d.ts +12 -0
- package/fs/types/function/compare/module.f.js +33 -0
- package/fs/types/function/operator/test.f.d.ts +10 -0
- package/fs/types/function/operator/test.f.js +81 -0
- package/fs/types/nullable/test.f.js +10 -1
- package/fs/types/range_map/module.f.js +3 -18
- package/fs/types/result/module.f.d.ts +4 -0
- package/fs/types/result/module.f.js +4 -0
- package/fs/types/result/test.f.d.ts +2 -4
- package/fs/types/result/test.f.js +24 -16
- package/fs/types/rtti/common/module.f.d.ts +10 -1
- package/fs/types/rtti/common/module.f.js +7 -2
- package/fs/types/rtti/parse/module.f.js +35 -46
- package/fs/types/rtti/validate/module.f.js +9 -12
- package/fs/types/sorted_list/module.f.d.ts +1 -2
- package/fs/types/sorted_list/module.f.js +8 -21
- package/fs/types/sorted_set/module.f.d.ts +1 -3
- package/fs/types/ts/test.f.d.ts +18 -0
- package/fs/types/ts/test.f.js +111 -0
- package/fs/types/uint8array/module.f.js +7 -1
- package/fs/types/uint8array/test.f.d.ts +1 -0
- package/fs/types/uint8array/test.f.js +5 -1
- package/package.json +4 -4
package/fs/io/module.js
CHANGED
|
@@ -10,12 +10,72 @@ import http from 'node:http';
|
|
|
10
10
|
import childProcess from 'node:child_process';
|
|
11
11
|
import fs from 'node:fs';
|
|
12
12
|
import process from 'node:process';
|
|
13
|
-
import { fromIo, run } from "./module.f.js";
|
|
14
13
|
import { concat } from "../path/module.f.js";
|
|
14
|
+
import { once } from 'node:events';
|
|
15
|
+
import { fromIo, runProgram } from "./module.f.js";
|
|
15
16
|
import { error, ok } from "../types/result/module.f.js";
|
|
17
|
+
import { fromVec } from "../types/uint8array/module.f.js";
|
|
18
|
+
import * as testContext from 'node:test';
|
|
19
|
+
const isPlaywright = 'PLAYWRIGHT_TEST' in (process?.env ?? {});
|
|
20
|
+
const pwTest = isPlaywright
|
|
21
|
+
? (await import('@playwright/test')).test
|
|
22
|
+
: undefined;
|
|
23
|
+
const inlineTest = async (name, { expectFailure }, fn) => {
|
|
24
|
+
if (expectFailure) {
|
|
25
|
+
try {
|
|
26
|
+
await fn(inlineContext);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`expected to throw: ${name}`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
await fn(inlineContext);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const inlineContext = { test: inlineTest };
|
|
38
|
+
const bunTestContext = {
|
|
39
|
+
test: (name, opts, fn) => testContext.test(name, () => inlineTest(name, opts, fn))
|
|
40
|
+
};
|
|
41
|
+
const playwrightTestContext = {
|
|
42
|
+
test: (name, opts, fn) => pwTest(name, () => inlineTest(name, opts, fn))
|
|
43
|
+
};
|
|
16
44
|
const prefix = 'file:///';
|
|
17
45
|
const { now } = Date;
|
|
46
|
+
/** Maps `WriteConsoles` names to the corresponding Node.js writable streams. */
|
|
47
|
+
const streams = {
|
|
48
|
+
stdout: process.stdout,
|
|
49
|
+
stderr: process.stderr,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Writes `data` to `stream` respecting Node.js backpressure.
|
|
53
|
+
*
|
|
54
|
+
* `stream.write()` returns `false` when the internal buffer is full; the data
|
|
55
|
+
* is already buffered at that point (no retry needed) but the caller must not
|
|
56
|
+
* issue more writes until the `'drain'` event fires. Waiting here throttles the
|
|
57
|
+
* producer to the speed of the OS consumer, preventing unbounded memory growth
|
|
58
|
+
* when many large messages arrive faster than they can be flushed.
|
|
59
|
+
*
|
|
60
|
+
* When the buffer is not full `write()` returns `true` and we return
|
|
61
|
+
* immediately, so large computations with occasional prints never stall.
|
|
62
|
+
*
|
|
63
|
+
* @see {@link https://nodejs.org/api/stream.html#writablewritechunk}
|
|
64
|
+
*/
|
|
65
|
+
const writeAll = async (stream, data) => {
|
|
66
|
+
if (!stream.write(data)) {
|
|
67
|
+
await once(stream, 'drain');
|
|
68
|
+
}
|
|
69
|
+
};
|
|
18
70
|
export const asyncImport = (v) => import(__rewriteRelativeImportExtension(v));
|
|
71
|
+
export const tryCatch = f => {
|
|
72
|
+
try {
|
|
73
|
+
return ok(f());
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
return error(e);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
19
79
|
export const io = {
|
|
20
80
|
console,
|
|
21
81
|
fs,
|
|
@@ -27,14 +87,7 @@ export const io = {
|
|
|
27
87
|
},
|
|
28
88
|
performance,
|
|
29
89
|
fetch,
|
|
30
|
-
tryCatch
|
|
31
|
-
try {
|
|
32
|
-
return ok(f());
|
|
33
|
-
}
|
|
34
|
-
catch (e) {
|
|
35
|
-
return error(e);
|
|
36
|
-
}
|
|
37
|
-
},
|
|
90
|
+
tryCatch,
|
|
38
91
|
asyncTryCatch: async (f) => {
|
|
39
92
|
try {
|
|
40
93
|
return ok(await f());
|
|
@@ -61,13 +114,11 @@ export const io = {
|
|
|
61
114
|
}
|
|
62
115
|
return { result, duration: after - before };
|
|
63
116
|
},
|
|
117
|
+
write: (stream, data) => writeAll(streams[stream], fromVec(data)),
|
|
118
|
+
testContext,
|
|
119
|
+
bunTestContext,
|
|
120
|
+
playwrightTestContext,
|
|
121
|
+
engine: isPlaywright ? 'playwright' : 'Bun' in globalThis ? 'bun' : 'node',
|
|
64
122
|
};
|
|
65
|
-
|
|
66
|
-
export const ioRun = (io) => {
|
|
67
|
-
const r = fromIo(io);
|
|
68
|
-
const { argv, env } = io.process;
|
|
69
|
-
const options = { args: argv.slice(2), env };
|
|
70
|
-
return p => r(p(options));
|
|
71
|
-
};
|
|
72
|
-
const effectRun = ioRun(io);
|
|
123
|
+
const effectRun = runProgram(io)(io.process.argv.slice(2));
|
|
73
124
|
export default effectRun;
|
package/fs/path/module.f.d.ts
CHANGED
|
@@ -20,3 +20,9 @@ export declare const normalize: Unary<string, string>;
|
|
|
20
20
|
* Concatenates two path fragments and returns a normalized path.
|
|
21
21
|
*/
|
|
22
22
|
export declare const concat: Reduce<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns `path` relative to `base` with a `./` prefix, or `path` unchanged
|
|
25
|
+
* if it does not start with `base` or `base` is empty.
|
|
26
|
+
* E.g. `relativize('/repo', '/repo/fs/a.ts')` → `'./fs/a.ts'`.
|
|
27
|
+
*/
|
|
28
|
+
export declare const relativize: (base: string, path: string) => string;
|
package/fs/path/module.f.js
CHANGED
|
@@ -46,3 +46,9 @@ export const concat = a => b => {
|
|
|
46
46
|
const s = stringConcat([a, '/', b]);
|
|
47
47
|
return normalize(s);
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Returns `path` relative to `base` with a `./` prefix, or `path` unchanged
|
|
51
|
+
* if it does not start with `base` or `base` is empty.
|
|
52
|
+
* E.g. `relativize('/repo', '/repo/fs/a.ts')` → `'./fs/a.ts'`.
|
|
53
|
+
*/
|
|
54
|
+
export const relativize = (base, path) => base !== '' && path.startsWith(base) ? `.${path.slice(base.length)}` : path;
|
package/fs/path/test.f.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
declare const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
export default _default;
|
|
1
|
+
export declare const normalizeTest: (() => void)[];
|
|
2
|
+
export declare const concatTest: (() => void)[];
|
|
3
|
+
export declare const relativizeTest: (() => void)[];
|
package/fs/path/test.f.js
CHANGED
|
@@ -1,49 +1,67 @@
|
|
|
1
|
-
import { concat, normalize } from "./module.f.js";
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
()
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
()
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
()
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
1
|
+
import { concat, normalize, relativize } from "./module.f.js";
|
|
2
|
+
export const normalizeTest = [
|
|
3
|
+
() => {
|
|
4
|
+
const norm = normalize("dir/file.json");
|
|
5
|
+
if (norm !== "dir/file.json") {
|
|
6
|
+
throw norm;
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
() => {
|
|
10
|
+
const norm = normalize("dir//file.json");
|
|
11
|
+
if (norm !== "dir/file.json") {
|
|
12
|
+
throw norm;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
() => {
|
|
16
|
+
const norm = normalize("../../dir/file.json");
|
|
17
|
+
if (norm !== "../../dir/file.json") {
|
|
18
|
+
throw norm;
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
() => {
|
|
22
|
+
const norm = normalize("../../dir/../file.json");
|
|
23
|
+
if (norm !== "../../file.json") {
|
|
24
|
+
throw norm;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
export const concatTest = [
|
|
29
|
+
() => {
|
|
30
|
+
const c = concat("a")("b");
|
|
31
|
+
if (c !== "a/b") {
|
|
32
|
+
throw c;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
() => {
|
|
36
|
+
const c = concat("a///b/")("c");
|
|
37
|
+
if (c !== "a/b/c") {
|
|
38
|
+
throw c;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
() => {
|
|
42
|
+
const c = concat("a/../b/..")("c");
|
|
43
|
+
if (c !== "c") {
|
|
44
|
+
throw c;
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
export const relativizeTest = [
|
|
49
|
+
() => {
|
|
50
|
+
const r = relativize('/repo', '/repo/fs/a.ts');
|
|
51
|
+
if (r !== './fs/a.ts') {
|
|
52
|
+
throw r;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
() => {
|
|
56
|
+
const r = relativize('/repo', '/other/a.ts');
|
|
57
|
+
if (r !== '/other/a.ts') {
|
|
58
|
+
throw r;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
() => {
|
|
62
|
+
const r = relativize('', './fs/a.ts');
|
|
63
|
+
if (r !== './fs/a.ts') {
|
|
64
|
+
throw r;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
];
|
package/fs/sul/id/module.f.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
import { toArray } from "../../types/list/module.f.js";
|
|
9
|
-
import { length,
|
|
9
|
+
import { length, msb, uint, uintChunkList, unpack, vec } from "../../types/bit_vec/module.f.js";
|
|
10
10
|
import { assertEq } from "../../dev/module.f.js";
|
|
11
11
|
import { utf8 } from "../../text/module.f.js";
|
|
12
12
|
import { secp256r1 } from "../../crypto/secp/module.f.js";
|
|
@@ -77,9 +77,8 @@ export const isHash = (v) => asBase(v) >> hashPrefixOffset === 1n;
|
|
|
77
77
|
export const hashId = (hash) => asNominal(hashPrefix | hash);
|
|
78
78
|
const hash2 = base32.compress(iv);
|
|
79
79
|
const vecX20 = vec(0x20n);
|
|
80
|
-
const
|
|
81
|
-
const hashMerge = (a, b) => hashId(uint(
|
|
82
|
-
const { concat } = msb;
|
|
80
|
+
const { concat, listToVec } = msb;
|
|
81
|
+
const hashMerge = (a, b) => hashId(uint(listToVec(hash2((asBase(a) << 0x100n) | asBase(b)).map(vecX20))));
|
|
83
82
|
export const compress = (a, b) => {
|
|
84
83
|
if (isHash(a) || isHash(b)) {
|
|
85
84
|
return hashMerge(a, b);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
7
|
import { log2 } from "../../../types/bigint/module.f.js";
|
|
8
|
-
import {
|
|
8
|
+
import { msb, vec } from "../../../types/bit_vec/module.f.js";
|
|
9
9
|
import { strictEqual } from "../../../types/function/operator/module.f.js";
|
|
10
10
|
import { equal, map } from "../../../types/list/module.f.js";
|
|
11
11
|
import { join } from "../../../types/string/module.f.js";
|
|
@@ -73,12 +73,12 @@ export const pipelineStep = (bit, [l1s, l2s, l3s]) => {
|
|
|
73
73
|
const [l3Out, newL3s] = l3.encode(l2Out, l3s);
|
|
74
74
|
return [l3Out, [newL1s, newL2s, newL3s]];
|
|
75
75
|
};
|
|
76
|
-
const concat = listToVec(msb);
|
|
77
76
|
const vec1 = vec(1n);
|
|
77
|
+
const { listToVec } = msb;
|
|
78
78
|
const literalToVec = (prior, e) => {
|
|
79
79
|
const m = map(prior);
|
|
80
80
|
const { decode } = level(e);
|
|
81
|
-
return literal =>
|
|
81
|
+
return literal => listToVec(m(decode(literal)));
|
|
82
82
|
};
|
|
83
83
|
/** Decodes a level-1 symbol to its canonical MSB bit vector. */
|
|
84
84
|
export const literal1ToVec = literalToVec(vec1, 0n);
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
7
|
import type { Io, Writable } from "../../io/module.f.ts";
|
|
8
|
+
import { type Write, type WriteConsoles, type NodeProgramOptions } from '../../types/effects/node/module.f.ts';
|
|
9
|
+
import { type Effect } from '../../types/effects/module.f.ts';
|
|
8
10
|
export declare const backspace: string;
|
|
9
11
|
type End = 'm';
|
|
10
12
|
type Csi = (code: number | string) => string;
|
|
@@ -44,7 +46,7 @@ export type WriteText = (text: string) => WriteText;
|
|
|
44
46
|
export declare const createConsoleText: (stdout: Stdout) => WriteText;
|
|
45
47
|
export type CsiConsole = (s: string) => void;
|
|
46
48
|
/**
|
|
47
|
-
* Creates a TTY-aware console function.
|
|
49
|
+
* Creates a TTY-aware console function. Appends `\n` to each string before writing.
|
|
48
50
|
*
|
|
49
51
|
* For TTY destinations, ANSI SGR sequences are preserved.
|
|
50
52
|
* For non-TTY destinations, ANSI SGR sequences are stripped.
|
|
@@ -57,4 +59,10 @@ export declare const console: ({ fs: { writeSync } }: Io) => (w: Writable) => Cs
|
|
|
57
59
|
export declare const stdio: (io: Io) => CsiConsole;
|
|
58
60
|
/** Writes to process stderr using a TTY-aware CSI console. */
|
|
59
61
|
export declare const stderr: (io: Io) => CsiConsole;
|
|
62
|
+
/**
|
|
63
|
+
* Effect-based TTY-aware write. Strips ANSI SGR sequences when the target
|
|
64
|
+
* stream is not a TTY, then encodes to UTF-8 and emits a `Write` effect.
|
|
65
|
+
* Does NOT append `\n` — callers are responsible for line termination.
|
|
66
|
+
*/
|
|
67
|
+
export declare const csiWrite: ({ std }: NodeProgramOptions) => (stream: WriteConsoles) => (s: string) => Effect<Write, void>;
|
|
60
68
|
export {};
|
package/fs/text/sgr/module.f.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
|
+
import { write } from "../../types/effects/node/module.f.js";
|
|
8
|
+
import {} from "../../types/effects/module.f.js";
|
|
9
|
+
import { utf8 } from "../module.f.js";
|
|
7
10
|
export const backspace = '\x08';
|
|
8
11
|
const begin = '\x1b[';
|
|
9
12
|
/**
|
|
@@ -46,8 +49,9 @@ export const createConsoleText = (stdout) => {
|
|
|
46
49
|
};
|
|
47
50
|
return f('');
|
|
48
51
|
};
|
|
52
|
+
const str = (isTTY) => (s) => isTTY ? s : s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
49
53
|
/**
|
|
50
|
-
* Creates a TTY-aware console function.
|
|
54
|
+
* Creates a TTY-aware console function. Appends `\n` to each string before writing.
|
|
51
55
|
*
|
|
52
56
|
* For TTY destinations, ANSI SGR sequences are preserved.
|
|
53
57
|
* For non-TTY destinations, ANSI SGR sequences are stripped.
|
|
@@ -56,12 +60,19 @@ export const createConsoleText = (stdout) => {
|
|
|
56
60
|
* @returns A function that targets a writable stream.
|
|
57
61
|
*/
|
|
58
62
|
export const console = ({ fs: { writeSync } }) => (w) => {
|
|
59
|
-
const
|
|
60
|
-
return
|
|
61
|
-
? (s) => writeSync(w.fd, s + '\n')
|
|
62
|
-
: (s) => writeSync(w.fd, s.replace(/\x1b\[[0-9;]*m/g, '') + '\n');
|
|
63
|
+
const toStr = str(w.isTTY);
|
|
64
|
+
return (s) => writeSync(w.fd, toStr(s) + '\n');
|
|
63
65
|
};
|
|
64
66
|
/** Writes to process stdout using a TTY-aware CSI console. */
|
|
65
67
|
export const stdio = (io) => console(io)(io.process.stdout);
|
|
66
68
|
/** Writes to process stderr using a TTY-aware CSI console. */
|
|
67
69
|
export const stderr = (io) => console(io)(io.process.stderr);
|
|
70
|
+
/**
|
|
71
|
+
* Effect-based TTY-aware write. Strips ANSI SGR sequences when the target
|
|
72
|
+
* stream is not a TTY, then encodes to UTF-8 and emits a `Write` effect.
|
|
73
|
+
* Does NOT append `\n` — callers are responsible for line termination.
|
|
74
|
+
*/
|
|
75
|
+
export const csiWrite = ({ std }) => (stream) => {
|
|
76
|
+
const toStr = str(std[stream].isTTY);
|
|
77
|
+
return (s) => write(stream, utf8(toStr(s)));
|
|
78
|
+
};
|
package/fs/text/sgr/test.f.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import { fgRed } from "./module.f.js";
|
|
1
|
+
import { fgRed, createConsoleText, backspace } from "./module.f.js";
|
|
2
2
|
export default [
|
|
3
3
|
() => {
|
|
4
4
|
if (fgRed !== '\x1b[31m') {
|
|
5
5
|
throw new Error('Test failed: sgr(0)');
|
|
6
6
|
}
|
|
7
|
+
},
|
|
8
|
+
() => {
|
|
9
|
+
const output = [];
|
|
10
|
+
const stdout = { write: (s) => { output.push(s); } };
|
|
11
|
+
const writer1 = createConsoleText(stdout);
|
|
12
|
+
const writer2 = writer1('hello');
|
|
13
|
+
if (output[0] !== 'hello') {
|
|
14
|
+
throw output[0];
|
|
15
|
+
}
|
|
16
|
+
// replacing 'hello' (len=5) with 'hi' (len=2): suffixLength=3
|
|
17
|
+
writer2('hi');
|
|
18
|
+
const expected = backspace.repeat(5) + 'hi' + ' '.repeat(3) + backspace.repeat(3);
|
|
19
|
+
if (output[1] !== expected) {
|
|
20
|
+
throw output[1];
|
|
21
|
+
}
|
|
7
22
|
}
|
|
8
23
|
];
|
|
@@ -146,6 +146,15 @@ export type BitOrder = {
|
|
|
146
146
|
* ```
|
|
147
147
|
*/
|
|
148
148
|
readonly concat: Reduce;
|
|
149
|
+
/**
|
|
150
|
+
* Folds a list of vectors into a single vector in this bit order.
|
|
151
|
+
*
|
|
152
|
+
* Unlike `concat`, which joins exactly two vectors, this joins a whole list.
|
|
153
|
+
*
|
|
154
|
+
* @returns The concatenation of every vector in the list, or `empty` when the
|
|
155
|
+
* list is empty.
|
|
156
|
+
*/
|
|
157
|
+
readonly listToVec: (list: List<Vec>) => Vec;
|
|
149
158
|
/**
|
|
150
159
|
* Computes the bitwise exclusive OR of two vectors after normalizing their lengths.
|
|
151
160
|
*
|
|
@@ -219,10 +228,6 @@ export declare const chunkList: (bo: BitOrder) => (n: bigint) => (v: Vec) => Thu
|
|
|
219
228
|
* @returns A thunk that produces a list of unsigned 8-bit integers.
|
|
220
229
|
*/
|
|
221
230
|
export declare const u8List: (bo: BitOrder) => (v: Vec) => Thunk<number>;
|
|
222
|
-
/**
|
|
223
|
-
* Concatenates a list of vectors using the provided bit order.
|
|
224
|
-
*/
|
|
225
|
-
export declare const listToVec: ({ concat }: BitOrder) => (list: List<Vec>) => Vec;
|
|
226
231
|
/**
|
|
227
232
|
* Repeats a vector to create a padded block of the desired length.
|
|
228
233
|
*/
|
|
@@ -127,14 +127,16 @@ const bo = ({ front, removeFront, norm, uintCmp, unpackSplit, unpackConcatUint }
|
|
|
127
127
|
return [uint, pack(u)];
|
|
128
128
|
};
|
|
129
129
|
};
|
|
130
|
+
const concat = a => b => {
|
|
131
|
+
const au = unpack(a);
|
|
132
|
+
const bu = unpack(b);
|
|
133
|
+
return pack(unpackConcat(au)(bu));
|
|
134
|
+
};
|
|
130
135
|
return {
|
|
131
136
|
front,
|
|
132
137
|
removeFront,
|
|
133
|
-
concat
|
|
134
|
-
|
|
135
|
-
const bu = unpack(b);
|
|
136
|
-
return pack(unpackConcat(au)(bu));
|
|
137
|
-
},
|
|
138
|
+
concat,
|
|
139
|
+
listToVec: fold(flip(concat))(empty),
|
|
138
140
|
xor: op(norm)(xor),
|
|
139
141
|
unpackPopFront,
|
|
140
142
|
popFront,
|
|
@@ -301,10 +303,6 @@ const vecToU8 = ({ unpackSplit }) => {
|
|
|
301
303
|
* @returns A thunk that produces a list of unsigned 8-bit integers.
|
|
302
304
|
*/
|
|
303
305
|
export const u8List = (bo) => (v) => map(vecToU8(bo))(chunkList(bo)(8n)(v));
|
|
304
|
-
/**
|
|
305
|
-
* Concatenates a list of vectors using the provided bit order.
|
|
306
|
-
*/
|
|
307
|
-
export const listToVec = ({ concat }) => fold(flip(concat))(empty);
|
|
308
306
|
/**
|
|
309
307
|
* Repeats a vector to create a padded block of the desired length.
|
|
310
308
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import type
|
|
6
|
+
import { type TNode, type Tree } from '../types/module.f.ts';
|
|
7
7
|
import type { Compare } from '../../function/compare/module.f.ts';
|
|
8
8
|
export declare const nodeRemove: <T>(c: Compare<T>) => (node: TNode<T>) => Tree<T>;
|
|
9
9
|
export declare const remove: <T>(c: Compare<T>) => (tree: Tree<T>) => Tree<T>;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removal operations for persistent B-tree structures.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { collapseRoot } from "../types/module.f.js";
|
|
1
7
|
import { find } from "../find/module.f.js";
|
|
2
8
|
import { fold, concat, next } from "../../list/module.f.js";
|
|
3
9
|
import { map } from "../../nullable/module.f.js";
|
|
@@ -163,7 +169,6 @@ export const nodeRemove = (c) => (node) => {
|
|
|
163
169
|
return first;
|
|
164
170
|
}
|
|
165
171
|
const { first: tf, tail: tt } = tailR;
|
|
166
|
-
|
|
167
|
-
return result.length === 1 ? result[0] : result;
|
|
172
|
+
return collapseRoot(reduce(initReduce(tf)(first))(tt));
|
|
168
173
|
};
|
|
169
174
|
export const remove = c => map(nodeRemove(c));
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import type
|
|
6
|
+
import { type TNode, type Tree } from '../types/module.f.ts';
|
|
7
7
|
import type { Compare } from '../../function/compare/module.f.ts';
|
|
8
8
|
export declare const set: <T>(c: Compare<T>) => (f: (value: T | null) => T) => (tree: Tree<T>) => TNode<T>;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insertion and update operations for persistent B-tree structures.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { collapseRoot } from "../types/module.f.js";
|
|
1
7
|
import { find } from "../find/module.f.js";
|
|
2
8
|
import { fold } from "../../list/module.f.js";
|
|
3
9
|
const b57 = b => b.length === 5 ? [b] : [[b[0], b[1], b[2]], b[3], [b[4], b[5], b[6]]];
|
|
@@ -114,7 +120,6 @@ const nodeSet = (c) => (g) => (node) => {
|
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
};
|
|
117
|
-
|
|
118
|
-
return r.length === 1 ? r[0] : r;
|
|
123
|
+
return collapseRoot(reduceBranch(f())(tail));
|
|
119
124
|
};
|
|
120
125
|
export const set = c => f => tree => tree === null ? [f(null)] : nodeSet(c)(f)(tree);
|
|
@@ -12,3 +12,4 @@ export type TNode<T> = Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>;
|
|
|
12
12
|
export type Tree<T> = TNode<T> | null;
|
|
13
13
|
export type Branch1<T> = readonly [TNode<T>];
|
|
14
14
|
export type Branch7<T> = readonly [...Branch5<T>, T, TNode<T>];
|
|
15
|
+
export declare const collapseRoot: <T>(b: Branch1<T> | Branch3<T> | Branch5<T>) => TNode<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export const collapseRoot = b => b.length === 1 ? b[0] : b;
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Node.js effect operations: filesystem (`mkdir`, `readFile`, `readdir`,
|
|
3
|
-
* `writeFile`, `rm`, `access`), networking (`fetch`, `createServer`, `listen`),
|
|
4
|
-
* subprocess `exec`, console (`log`, `error`), `import_`, `now`, `sandbox`, `forever`,
|
|
5
|
-
* and `all`/`both` parallelism; defines the `NodeOp`/`NodeProgram` types used
|
|
6
|
-
* by the Node runner.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
1
|
import type { Vec } from '../../bit_vec/module.f.ts';
|
|
11
2
|
import type { Nominal } from '../../nominal/module.f.ts';
|
|
12
3
|
import type { Result } from '../../result/module.f.ts';
|
|
@@ -58,11 +49,6 @@ export declare const exec: Func<Exec>;
|
|
|
58
49
|
export type Access = readonly ['access', (path: string) => IoResult<void>];
|
|
59
50
|
export declare const access: Func<Access>;
|
|
60
51
|
export type Fs = Mkdir | ReadFile | Readdir | WriteFile | Rm | Exec | Access;
|
|
61
|
-
export type Error = ['error', (message: string) => void];
|
|
62
|
-
export declare const error: Func<Error>;
|
|
63
|
-
export type Log = ['log', (message: string) => void];
|
|
64
|
-
export declare const log: Func<Log>;
|
|
65
|
-
export type Console = Log | Error;
|
|
66
52
|
export type Server = Nominal<'server', `160855c4f69310fece3273c1853ac32de43dee1eb41bf59d821917f8eebe9272`, unknown>;
|
|
67
53
|
export type Headers = {
|
|
68
54
|
readonly [k in string]: string;
|
|
@@ -87,10 +73,18 @@ export type Http = CreateServer | Listen;
|
|
|
87
73
|
export type Forever = ['forever', () => never];
|
|
88
74
|
export declare const forever: Func<Forever>;
|
|
89
75
|
export type Module = {
|
|
90
|
-
readonly
|
|
76
|
+
readonly [k in string]: unknown;
|
|
91
77
|
};
|
|
92
78
|
export type Import = ['import', (path: string) => IoResult<Module>];
|
|
93
79
|
export declare const import_: Func<Import>;
|
|
80
|
+
export type WriteConsoles = 'stdout' | 'stderr';
|
|
81
|
+
export type Write = readonly ['write', (stream: WriteConsoles, data: Vec) => void];
|
|
82
|
+
export declare const write: Func<Write>;
|
|
83
|
+
export type Console = (s: string) => Effect<Write, void>;
|
|
84
|
+
/** Writes a line to `stdout`. Replaces the retired `Log` effect. */
|
|
85
|
+
export declare const log: Console;
|
|
86
|
+
/** Writes a line to `stderr`. Replaces the retired `Error` effect. */
|
|
87
|
+
export declare const error: Console;
|
|
94
88
|
export type Now = readonly ['now', () => number];
|
|
95
89
|
export declare const now: Func<Now>;
|
|
96
90
|
export type SandboxResult<T> = {
|
|
@@ -122,7 +116,15 @@ export type Sandbox = readonly ['sandbox', <T>(f: () => T) => SandboxResult<T>];
|
|
|
122
116
|
* @see {@link SandboxResult}
|
|
123
117
|
*/
|
|
124
118
|
export declare const sandbox: Func<Sandbox>;
|
|
125
|
-
export type
|
|
119
|
+
export type TestFn = (name: string, options: {
|
|
120
|
+
readonly expectFailure: boolean;
|
|
121
|
+
}, fn: (t: TestContext) => Promise<void>) => Promise<void>;
|
|
122
|
+
export type TestContext = {
|
|
123
|
+
readonly test: TestFn;
|
|
124
|
+
};
|
|
125
|
+
export type Test = readonly ['test', (ctx: TestContext, name: string, expectFailure: boolean, test: (t: TestContext) => Effect<Test | All, void>) => void];
|
|
126
|
+
export declare const test: Func<Test>;
|
|
127
|
+
export type NodeOp = All | Fetch | Fs | Http | Forever | Import | Now | Sandbox | Write | Test;
|
|
126
128
|
export type NodeEffect<T> = Effect<NodeOp, T>;
|
|
127
129
|
export type NodeOperationMap = ToAsyncOperationMap<NodeOp>;
|
|
128
130
|
/**
|
|
@@ -131,8 +133,19 @@ export type NodeOperationMap = ToAsyncOperationMap<NodeOp>;
|
|
|
131
133
|
export type Env = {
|
|
132
134
|
readonly [k: string]: string | undefined;
|
|
133
135
|
};
|
|
136
|
+
export type Engine = 'node' | 'bun' | 'playwright';
|
|
134
137
|
export type NodeProgramOptions = {
|
|
135
138
|
readonly args: readonly string[];
|
|
136
139
|
readonly env: Env;
|
|
140
|
+
readonly std: {
|
|
141
|
+
readonly [k in WriteConsoles]: {
|
|
142
|
+
readonly isTTY: boolean;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
readonly testContext: TestContext;
|
|
146
|
+
readonly bunTestContext: TestContext;
|
|
147
|
+
readonly playwrightTestContext: TestContext;
|
|
148
|
+
readonly engine: Engine;
|
|
137
149
|
};
|
|
138
|
-
export type
|
|
150
|
+
export type Program<O extends Operation> = (options: NodeProgramOptions) => Effect<O, number>;
|
|
151
|
+
export type NodeProgram = Program<NodeOp>;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js effect operations: filesystem (`mkdir`, `readFile`, `readdir`,
|
|
3
|
+
* `writeFile`, `rm`, `access`), networking (`fetch`, `createServer`, `listen`),
|
|
4
|
+
* subprocess `exec`, `log`/`error` (wrappers over `write`), `import_`, `now`,
|
|
5
|
+
* `sandbox`, `forever`, and `all`/`both` parallelism; defines the
|
|
6
|
+
* `NodeOp`/`NodeProgram` types used by the Node runner.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { utf8 } from "../../../text/module.f.js";
|
|
1
11
|
import { do_ } from "../module.f.js";
|
|
2
12
|
const doAll = do_('all');
|
|
3
13
|
/**
|
|
@@ -17,12 +27,20 @@ export const writeFile = do_('writeFile');
|
|
|
17
27
|
export const rm = do_('rm');
|
|
18
28
|
export const exec = do_('exec');
|
|
19
29
|
export const access = do_('access');
|
|
20
|
-
export const error = do_('error');
|
|
21
|
-
export const log = do_('log');
|
|
22
30
|
export const createServer = do_('createServer');
|
|
23
31
|
export const listen = do_('listen');
|
|
24
32
|
export const forever = do_('forever');
|
|
25
33
|
export const import_ = do_('import');
|
|
34
|
+
export const write = do_('write');
|
|
35
|
+
/**
|
|
36
|
+
* Encodes `s + '\n'` as UTF-8 and emits a `Write` effect to `stream`.
|
|
37
|
+
* Shared implementation for `log` and `error`.
|
|
38
|
+
*/
|
|
39
|
+
const writeString = (stream) => (s) => write(stream, utf8(s + '\n'));
|
|
40
|
+
/** Writes a line to `stdout`. Replaces the retired `Log` effect. */
|
|
41
|
+
export const log = writeString('stdout');
|
|
42
|
+
/** Writes a line to `stderr`. Replaces the retired `Error` effect. */
|
|
43
|
+
export const error = writeString('stderr');
|
|
26
44
|
export const now = do_('now');
|
|
27
45
|
/**
|
|
28
46
|
* Runs a plain synchronous function in an isolated, measured environment.
|
|
@@ -43,3 +61,4 @@ export const now = do_('now');
|
|
|
43
61
|
* @see {@link SandboxResult}
|
|
44
62
|
*/
|
|
45
63
|
export const sandbox = do_('sandbox');
|
|
64
|
+
export const test = do_('test');
|