functionalscript 0.30.0 → 0.31.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 +18 -22
- package/fs/asn.1/proof.f.d.ts +5 -0
- package/fs/asn.1/proof.f.js +38 -2
- package/fs/base64/module.f.d.ts +9 -0
- package/fs/base64/module.f.js +60 -0
- package/fs/base64/proof.f.d.ts +11 -0
- package/fs/base64/proof.f.js +117 -0
- package/fs/base_n/module.f.d.ts +44 -0
- package/fs/base_n/module.f.js +54 -0
- package/fs/base_n/proof.f.d.ts +10 -0
- package/fs/base_n/proof.f.js +86 -0
- package/fs/bnf/data/module.f.d.ts +4 -9
- package/fs/bnf/data/module.f.js +4 -3
- package/fs/bnf/module.f.d.ts +3 -4
- package/fs/bnf/module.f.js +3 -2
- package/fs/bnf/proof.f.d.ts +9 -0
- package/fs/bnf/proof.f.js +98 -1
- package/fs/cas/mcp/module.f.d.ts +40 -0
- package/fs/cas/mcp/module.f.js +223 -0
- package/fs/cas/mcp/proof.f.d.ts +30 -0
- package/fs/cas/mcp/proof.f.js +310 -0
- package/fs/cas/module.f.d.ts +9 -3
- package/fs/cas/module.f.js +104 -69
- package/fs/cas/proof.f.d.ts +2 -0
- package/fs/cas/proof.f.js +30 -1
- package/fs/cbase32/module.f.d.ts +1 -1
- package/fs/cbase32/module.f.js +19 -40
- package/fs/cbase32/proof.f.d.ts +1 -0
- package/fs/cbase32/proof.f.js +15 -0
- package/fs/ci/config/module.f.d.ts +6 -6
- package/fs/ci/config/module.f.js +6 -6
- package/fs/ci/deno/module.f.js +2 -2
- package/fs/ci/module.f.d.ts +5 -0
- package/fs/ci/module.f.js +2 -3
- package/fs/ci/proof.f.d.ts +1 -0
- package/fs/ci/proof.f.js +9 -3
- package/fs/cli/module.f.d.ts +3 -1
- package/fs/cli/module.f.js +22 -12
- package/fs/cli/proof.f.d.ts +5 -0
- package/fs/cli/proof.f.js +76 -0
- package/fs/crypto/hmac/proof.f.d.ts +1 -0
- package/fs/crypto/hmac/proof.f.js +8 -0
- package/fs/crypto/secp/proof.f.d.ts +1 -0
- package/fs/crypto/secp/proof.f.js +10 -0
- package/fs/crypto/sign/module.f.js +1 -4
- package/fs/dev/module.f.d.ts +5 -3
- package/fs/dev/module.f.js +13 -2
- package/fs/dev/package_json/proof.f.d.ts +1 -0
- package/fs/dev/package_json/proof.f.js +5 -0
- package/fs/dev/proof.f.d.ts +1 -0
- package/fs/dev/proof.f.js +12 -1
- package/fs/djs/ast/module.f.d.ts +1 -1
- package/fs/djs/ast/proof.f.d.ts +5 -0
- package/fs/djs/ast/proof.f.js +17 -0
- package/fs/djs/module.f.d.ts +1 -1
- package/fs/djs/module.f.js +2 -3
- package/fs/djs/serializer/module.f.js +24 -11
- package/fs/djs/transpiler/module.f.js +3 -4
- package/fs/effects/memory/module.f.d.ts +37 -0
- package/fs/effects/memory/module.f.js +24 -0
- package/fs/effects/memory/proof.f.d.ts +6 -0
- package/fs/effects/memory/proof.f.js +64 -0
- package/fs/effects/mock/module.f.d.ts +7 -2
- package/fs/effects/mock/module.f.js +12 -8
- package/fs/effects/module.d.ts +1 -1
- package/fs/effects/module.f.d.ts +41 -0
- package/fs/effects/module.f.js +25 -0
- package/fs/effects/module.js +6 -7
- package/fs/effects/node/memory/module.d.ts +20 -0
- package/fs/effects/node/memory/module.js +44 -0
- package/fs/effects/node/memory/proof.d.ts +10 -0
- package/fs/effects/node/memory/proof.js +35 -0
- package/fs/effects/node/module.d.ts +1 -1
- package/fs/effects/node/module.f.d.ts +54 -8
- package/fs/effects/node/module.f.js +55 -4
- package/fs/effects/node/module.js +166 -135
- package/fs/effects/node/proof.f.d.ts +10 -0
- package/fs/effects/node/proof.f.js +88 -21
- package/fs/effects/node/virtual/module.f.d.ts +6 -0
- package/fs/effects/node/virtual/module.f.js +48 -16
- package/fs/effects/node/virtual/proof.f.d.ts +17 -0
- package/fs/effects/node/virtual/proof.f.js +79 -0
- package/fs/effects/proof.f.d.ts +5 -0
- package/fs/effects/proof.f.js +54 -34
- package/fs/emergent_testing/module.f.d.ts +6 -1
- package/fs/emergent_testing/module.f.js +8 -3
- package/fs/emergent_testing/proof.f.d.ts +11 -0
- package/fs/emergent_testing/proof.f.js +52 -16
- package/fs/fjs/module.f.js +2 -2
- package/fs/fjs/proof.f.d.ts +8 -0
- package/fs/fjs/proof.f.js +39 -0
- package/fs/fsc/module.f.d.ts +5 -0
- package/fs/fsc/module.f.js +17 -27
- package/fs/fsc/proof.f.d.ts +8 -0
- package/fs/fsc/proof.f.js +48 -2
- package/fs/fsm/module.f.d.ts +2 -3
- package/fs/fsm/module.f.js +1 -1
- package/fs/html/module.f.d.ts +2 -3
- package/fs/html/module.f.js +7 -6
- package/fs/html/proof.f.d.ts +1 -0
- package/fs/html/proof.f.js +7 -0
- package/fs/js/tokenizer/module.f.js +1 -1
- package/fs/js/tokenizer/proof.f.js +7 -0
- package/fs/json/module.f.d.ts +9 -2
- package/fs/json/module.f.js +9 -7
- package/fs/json/parser/module.f.js +4 -6
- package/fs/json/parser/proof.f.js +19 -10
- package/fs/json/proof.f.d.ts +2 -1
- package/fs/json/proof.f.js +33 -6
- package/fs/json/rpc/module.f.d.ts +5 -0
- package/fs/json/rpc/module.f.js +16 -11
- package/fs/json/schema/module.f.d.ts +15 -14
- package/fs/json/schema/proof.f.d.ts +3 -0
- package/fs/json/schema/proof.f.js +16 -1
- package/fs/mcp/module.f.d.ts +103 -5
- package/fs/mcp/module.f.js +139 -2
- package/fs/mcp/proof.f.d.ts +34 -0
- package/fs/mcp/proof.f.js +207 -0
- package/fs/mcp/stdio/module.f.d.ts +39 -0
- package/fs/mcp/stdio/module.f.js +54 -0
- package/fs/mcp/stdio/proof.f.d.ts +10 -0
- package/fs/mcp/stdio/proof.f.js +92 -0
- package/fs/mime/module.f.d.ts +39 -0
- package/fs/mime/module.f.js +78 -0
- package/fs/mime/proof.f.d.ts +15 -0
- package/fs/mime/proof.f.js +30 -0
- package/fs/path/module.f.d.ts +8 -0
- package/fs/path/module.f.js +10 -3
- package/fs/path/proof.f.d.ts +1 -0
- package/fs/path/proof.f.js +40 -2
- package/fs/text/sgr/proof.f.js +30 -2
- package/fs/text/utf8/module.f.d.ts +7 -0
- package/fs/text/utf8/module.f.js +85 -31
- package/fs/text/utf8/proof.f.d.ts +1 -0
- package/fs/text/utf8/proof.f.js +60 -1
- package/fs/types/bigfloat/module.f.d.ts +3 -0
- package/fs/types/bigfloat/module.f.js +30 -31
- package/fs/types/bigint/module.f.d.ts +24 -2
- package/fs/types/bigint/module.f.js +30 -2
- package/fs/types/bigint/proof.f.d.ts +7 -0
- package/fs/types/bigint/proof.f.js +47 -16
- package/fs/types/bit_vec/module.f.d.ts +18 -0
- package/fs/types/bit_vec/module.f.js +18 -0
- package/fs/types/bit_vec/proof.f.d.ts +1 -0
- package/fs/types/bit_vec/proof.f.js +13 -1
- package/fs/types/function/operator/proof.f.d.ts +2 -0
- package/fs/types/function/operator/proof.f.js +20 -2
- package/fs/types/list/module.f.js +1 -4
- package/fs/types/list/proof.f.d.ts +1 -1
- package/fs/types/list/proof.f.js +14 -6
- package/fs/types/map/proof.f.d.ts +1 -0
- package/fs/types/map/proof.f.js +10 -1
- package/fs/types/nibble_set/module.f.d.ts +13 -0
- package/fs/types/nibble_set/module.f.js +16 -0
- package/fs/types/object/module.f.d.ts +12 -8
- package/fs/types/object/module.f.js +9 -2
- package/fs/types/object/proof.f.d.ts +14 -0
- package/fs/types/object/proof.f.js +4 -0
- package/fs/types/ordered_map/proof.f.d.ts +1 -0
- package/fs/types/ordered_map/proof.f.js +39 -79
- package/fs/types/phantom/module.f.d.ts +22 -0
- package/fs/types/phantom/module.f.js +11 -0
- package/fs/types/prime_field/proof.f.d.ts +7 -0
- package/fs/types/prime_field/proof.f.js +63 -122
- package/fs/types/rtti/common/module.f.d.ts +4 -4
- package/fs/types/rtti/common/module.f.js +1 -1
- package/fs/types/rtti/module.f.d.ts +2 -3
- package/fs/types/rtti/parse/module.f.js +0 -1
- package/fs/types/rtti/ts/module.f.d.ts +26 -32
- package/fs/types/rtti/ts/module.f.js +2 -2
- package/fs/types/rtti/ts/proof.f.js +3 -3
- package/fs/types/rtti/validate/module.f.js +0 -1
- package/fs/types/sorted_list/module.f.d.ts +6 -0
- package/fs/types/sorted_list/module.f.js +11 -0
- package/fs/types/sorted_set/module.f.js +2 -8
- package/fs/types/ts/module.f.d.ts +1 -1
- package/fs/types/ts/module.f.js +3 -1
- package/fs/types/ts/proof.f.js +3 -2
- package/fs/website/proof.f.d.ts +1 -0
- package/fs/website/proof.f.js +8 -1
- package/package.json +3 -3
package/fs/fsc/module.f.js
CHANGED
|
@@ -44,36 +44,26 @@ const create = (a) => {
|
|
|
44
44
|
};
|
|
45
45
|
export const terminal = -1;
|
|
46
46
|
const toInit = () => () => [[], init];
|
|
47
|
+
const single = (c) => range(c)(() => () => [[c], unexpectedSymbol]);
|
|
48
|
+
const punctuation = "!\"%&'()*+,-./:;<=>?[]^`{|}~";
|
|
47
49
|
export const init = create([
|
|
48
50
|
codePointRange(one(terminal))(toInit),
|
|
49
51
|
rangeSet(['\t', ' ', '\n', '\r'])(toInit),
|
|
50
|
-
range('!')(() => () => [['!'], unexpectedSymbol]),
|
|
51
|
-
range('"')(() => () => [['"'], unexpectedSymbol]),
|
|
52
52
|
rangeSet(['$', '_', 'AZ', 'az'])(() => c => [[fromCharCode(c)], unexpectedSymbol]),
|
|
53
|
-
range('%')(() => () => [['%'], unexpectedSymbol]),
|
|
54
|
-
range('&')(() => () => [['&'], unexpectedSymbol]),
|
|
55
|
-
range("'")(() => () => [["'"], unexpectedSymbol]),
|
|
56
|
-
range('(')(() => () => [['('], unexpectedSymbol]),
|
|
57
|
-
range(')')(() => () => [[')'], unexpectedSymbol]),
|
|
58
|
-
range('*')(() => () => [['*'], unexpectedSymbol]),
|
|
59
|
-
range('+')(() => () => [['+'], unexpectedSymbol]),
|
|
60
|
-
range(',')(() => () => [[','], unexpectedSymbol]),
|
|
61
|
-
range('-')(() => () => [['-'], unexpectedSymbol]),
|
|
62
|
-
range('.')(() => () => [['.'], unexpectedSymbol]),
|
|
63
|
-
range('/')(() => () => [['/'], unexpectedSymbol]),
|
|
64
53
|
range('09')(() => a => [[fromCharCode(a)], unexpectedSymbol]),
|
|
65
|
-
|
|
66
|
-
range(';')(() => () => [[';'], unexpectedSymbol]),
|
|
67
|
-
range('<')(() => () => [['<'], unexpectedSymbol]),
|
|
68
|
-
range('=')(() => () => [['='], unexpectedSymbol]),
|
|
69
|
-
range('>')(() => () => [['>'], unexpectedSymbol]),
|
|
70
|
-
range('?')(() => () => [['?'], unexpectedSymbol]),
|
|
71
|
-
range('[')(() => () => [['['], unexpectedSymbol]),
|
|
72
|
-
range(']')(() => () => [[']'], unexpectedSymbol]),
|
|
73
|
-
range('^')(() => () => [['^'], unexpectedSymbol]),
|
|
74
|
-
range('`')(() => () => [['`'], unexpectedSymbol]),
|
|
75
|
-
range('{')(() => () => [['{'], unexpectedSymbol]),
|
|
76
|
-
range('|')(() => () => [['|'], unexpectedSymbol]),
|
|
77
|
-
range('}')(() => () => [['}'], unexpectedSymbol]),
|
|
78
|
-
range('~')(() => () => [['~'], unexpectedSymbol]),
|
|
54
|
+
...[...punctuation].map(single),
|
|
79
55
|
])(undefined);
|
|
56
|
+
export const proof = {
|
|
57
|
+
// union throws when two distinct non-def handlers are merged for the same range;
|
|
58
|
+
// this path is unreachable through the public API (init has no overlapping ranges),
|
|
59
|
+
// so we exercise it here where the private union function is in scope.
|
|
60
|
+
throw: {
|
|
61
|
+
unionConflict: () => {
|
|
62
|
+
const a = _s => unexpectedSymbol;
|
|
63
|
+
const b = _s => unexpectedSymbol;
|
|
64
|
+
a(undefined);
|
|
65
|
+
b(undefined);
|
|
66
|
+
union(a)(b);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
package/fs/fsc/proof.f.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export declare const proof: {
|
|
2
2
|
a: () => void;
|
|
3
|
+
b: () => void;
|
|
4
|
+
c: () => void;
|
|
3
5
|
fn: () => void;
|
|
4
6
|
f1: () => void;
|
|
5
7
|
f2: () => void;
|
|
6
8
|
f3: () => void;
|
|
7
9
|
f4: () => void;
|
|
10
|
+
chars: {
|
|
11
|
+
whitespace: () => void;
|
|
12
|
+
punctuation: () => void;
|
|
13
|
+
identifier_start: () => void;
|
|
14
|
+
digits: () => void;
|
|
15
|
+
};
|
|
8
16
|
};
|
package/fs/fsc/proof.f.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { init } from "./module.f.js";
|
|
1
|
+
import { init, terminal } from "./module.f.js";
|
|
2
2
|
import { one } from "../text/ascii/module.f.js";
|
|
3
3
|
import { stringify } from "../json/module.f.js";
|
|
4
|
+
import { assertEq } from "../asserts/module.f.js";
|
|
4
5
|
const s = stringify(i => i);
|
|
5
6
|
const f = v => {
|
|
6
7
|
const n = one(v);
|
|
@@ -18,6 +19,21 @@ export const proof = {
|
|
|
18
19
|
throw x;
|
|
19
20
|
}
|
|
20
21
|
},
|
|
22
|
+
b: () => {
|
|
23
|
+
// exercises toInit: terminal returns empty output and loops back to init
|
|
24
|
+
const result = init(terminal);
|
|
25
|
+
if (result[0].length !== 0) {
|
|
26
|
+
throw result[0];
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
c: () => {
|
|
30
|
+
// exercises unexpectedSymbol: next state after a token returns an error message
|
|
31
|
+
const next = init(one('1'))[1];
|
|
32
|
+
const result = next(42);
|
|
33
|
+
if (result[0][0] !== 'unexpected symbol 42') {
|
|
34
|
+
throw result[0][0];
|
|
35
|
+
}
|
|
36
|
+
},
|
|
21
37
|
fn: () => {
|
|
22
38
|
const o = {
|
|
23
39
|
["hello world!"]: () => undefined
|
|
@@ -76,5 +92,35 @@ export const proof = {
|
|
|
76
92
|
if (f.name !== "") {
|
|
77
93
|
throw f.name;
|
|
78
94
|
}
|
|
79
|
-
}
|
|
95
|
+
},
|
|
96
|
+
chars: {
|
|
97
|
+
whitespace: () => {
|
|
98
|
+
for (const ch of ['\t', ' ', '\n', '\r']) {
|
|
99
|
+
const [tokens, next] = init(one(ch));
|
|
100
|
+
assertEq(tokens.length, 0);
|
|
101
|
+
assertEq(next, init);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
punctuation: () => {
|
|
105
|
+
for (const ch of ['!', '"', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '^', '`', '{', '|', '}', '~']) {
|
|
106
|
+
const [tokens] = init(one(ch));
|
|
107
|
+
assertEq(tokens.length, 1);
|
|
108
|
+
assertEq(tokens[0], ch);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
identifier_start: () => {
|
|
112
|
+
for (const ch of ['$', '_', 'A', 'Z', 'a', 'z']) {
|
|
113
|
+
const [tokens] = init(one(ch));
|
|
114
|
+
assertEq(tokens.length, 1);
|
|
115
|
+
assertEq(tokens[0], ch);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
digits: () => {
|
|
119
|
+
for (const ch of ['0', '5', '9']) {
|
|
120
|
+
const [tokens] = init(one(ch));
|
|
121
|
+
assertEq(tokens.length, 1);
|
|
122
|
+
assertEq(tokens[0], ch);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
},
|
|
80
126
|
};
|
package/fs/fsm/module.f.d.ts
CHANGED
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import { type List } from '../types/list/module.f.ts';
|
|
7
|
+
import type { StringMap } from '../types/object/module.f.ts';
|
|
7
8
|
import { type ByteSet } from '../types/byte_set/module.f.ts';
|
|
8
9
|
import { type RangeMapArray } from '../types/range_map/module.f.ts';
|
|
9
10
|
type Rule = readonly [string, ByteSet, string];
|
|
10
11
|
export type Grammar = List<Rule>;
|
|
11
|
-
type Dfa =
|
|
12
|
-
readonly [state in string]: RangeMapArray<string>;
|
|
13
|
-
};
|
|
12
|
+
type Dfa = StringMap<string, RangeMapArray<string>>;
|
|
14
13
|
export declare const toRange: (s: string) => ByteSet;
|
|
15
14
|
export declare const toUnion: (s: string) => ByteSet;
|
|
16
15
|
export declare const dfa: (grammar: Grammar) => Dfa;
|
package/fs/fsm/module.f.js
CHANGED
|
@@ -51,5 +51,5 @@ const initialState = [''];
|
|
|
51
51
|
const initialStateStringify = stringifyIdentity(initialState);
|
|
52
52
|
export const dfa = grammar => addEntry(grammar)(initialState)({});
|
|
53
53
|
const get = rangeMapGet(emptyStateStringify);
|
|
54
|
-
const runOp = dfa => input => s => get(input)(dfa[s]);
|
|
54
|
+
const runOp = dfa => input => s => get(input)(dfa[s] ?? []);
|
|
55
55
|
export const run = (dfa) => (input) => foldScan(runOp(dfa))(initialStateStringify)(input);
|
package/fs/html/module.f.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
7
|
import { type List } from '../types/list/module.f.ts';
|
|
8
|
+
import { type StringMap } from '../types/object/module.f.ts';
|
|
8
9
|
import { type Vec } from '../types/bit_vec/module.f.ts';
|
|
9
10
|
type Tag = string;
|
|
10
11
|
type Element1 = readonly [Tag, ...Node[]];
|
|
@@ -16,9 +17,7 @@ type Element2 = readonly [Tag, Attributes, ...Node[]];
|
|
|
16
17
|
* - `[tag, attributes, ...children]` for elements with attributes.
|
|
17
18
|
*/
|
|
18
19
|
export type Element = Element1 | Element2;
|
|
19
|
-
type Attributes =
|
|
20
|
-
readonly [k in string]: string;
|
|
21
|
-
};
|
|
20
|
+
type Attributes = StringMap<string, string>;
|
|
22
21
|
export type Node = Element | string;
|
|
23
22
|
/**
|
|
24
23
|
* Converts a FunctionalScript element into a list of HTML string chunks.
|
package/fs/html/module.f.js
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { map, flatMap, flat, concat as listConcat } from "../types/list/module.f.js";
|
|
8
8
|
import { concat, concat as stringConcat } from "../types/string/module.f.js";
|
|
9
|
+
import { definedEntries } from "../types/object/module.f.js";
|
|
9
10
|
import { compose } from "../types/function/module.f.js";
|
|
10
11
|
import { stringToList } from "../text/utf16/module.f.js";
|
|
11
12
|
import { includes } from "../types/array/module.f.js";
|
|
12
13
|
import {} from "../types/bit_vec/module.f.js";
|
|
13
14
|
import { utf8 } from "../text/module.f.js";
|
|
15
|
+
import { quotationMark, ampersand, lessThanSign, greaterThanSign } from "../text/ascii/module.f.js";
|
|
14
16
|
const { fromCharCode } = String;
|
|
15
|
-
const { entries } = Object;
|
|
16
17
|
/**
|
|
17
18
|
* Void Elements
|
|
18
19
|
*
|
|
@@ -47,10 +48,10 @@ const rawText = [
|
|
|
47
48
|
*/
|
|
48
49
|
const escapeCharCode = (code) => {
|
|
49
50
|
switch (code) {
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
case
|
|
51
|
+
case quotationMark: return '"';
|
|
52
|
+
case ampersand: return '&';
|
|
53
|
+
case lessThanSign: return '<';
|
|
54
|
+
case greaterThanSign: return '>';
|
|
54
55
|
default: return fromCharCode(code);
|
|
55
56
|
}
|
|
56
57
|
};
|
|
@@ -62,7 +63,7 @@ const mr = map(raw);
|
|
|
62
63
|
// Escape closing tags in raw text elements
|
|
63
64
|
const rawMap = (n) => concat(mr(n)).replaceAll('</', '<\\/');
|
|
64
65
|
const attribute = ([name, value]) => flat([[' ', name, '="'], escape(value), ['"']]);
|
|
65
|
-
const attributes =
|
|
66
|
+
const attributes = (a) => flatMap(attribute)(definedEntries(a));
|
|
66
67
|
const parseElement = (e) => {
|
|
67
68
|
const [tag, item1, ...list] = e;
|
|
68
69
|
return item1 === undefined ?
|
package/fs/html/proof.f.d.ts
CHANGED
package/fs/html/proof.f.js
CHANGED
|
@@ -517,5 +517,5 @@ const tokenizeWithPositionOp = (input, { state, metadata }) => {
|
|
|
517
517
|
const scanTokenize = stateScan(tokenizeWithPositionOp);
|
|
518
518
|
export const tokenize = input => path => {
|
|
519
519
|
const scan = scanTokenize({ state: { kind: 'initial' }, metadata: { path, line: 1, column: 1 } });
|
|
520
|
-
return flat(scan(flat([input
|
|
520
|
+
return flat(scan(flat([input /*satisfies List<CharCodeOrEof>*/, [null]])));
|
|
521
521
|
};
|
|
@@ -177,6 +177,13 @@ export const proof = {
|
|
|
177
177
|
throw result;
|
|
178
178
|
}
|
|
179
179
|
},
|
|
180
|
+
() => {
|
|
181
|
+
// terminal char after invalidNumber state (covers invalidNumberStateOp terminal branch)
|
|
182
|
+
const result = stringify(tokenizeString('00,'));
|
|
183
|
+
if (result !== '[{"kind":"error","message":"invalid number"},{"kind":","},{"kind":"eof"}]') {
|
|
184
|
+
throw result;
|
|
185
|
+
}
|
|
186
|
+
},
|
|
180
187
|
() => {
|
|
181
188
|
const result = stringify(tokenizeString('0abc,'));
|
|
182
189
|
if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"abc"},{"kind":","},{"kind":"eof"}]') {
|
package/fs/json/module.f.d.ts
CHANGED
|
@@ -23,12 +23,18 @@ export declare const primitive: import("../types/rtti/module.f.ts").Or<[null, im
|
|
|
23
23
|
* core's `unknown`, the JSON `unknown` excludes `undefined`.
|
|
24
24
|
*/
|
|
25
25
|
export declare const unknown: () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>, import("../types/rtti/module.f.ts").Type1<"array", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>];
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* rtti schema matching a JSON object: `{ readonly [k: string]?: Unknown }`.
|
|
28
|
+
*/
|
|
27
29
|
export declare const object: import("../types/rtti/module.f.ts").Type1<"record", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>;
|
|
28
30
|
/** rtti schema matching a JSON array: `readonly Unknown[]`. */
|
|
29
31
|
export declare const array: import("../types/rtti/module.f.ts").Type1<"array", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>;
|
|
30
32
|
export type Primitive = Ts<typeof primitive>;
|
|
31
|
-
export type Unknown =
|
|
33
|
+
export type Unknown = Object | Array | Primitive;
|
|
34
|
+
export type Object = {
|
|
35
|
+
readonly [k in string]?: Unknown;
|
|
36
|
+
};
|
|
37
|
+
export type Array = readonly Unknown[];
|
|
32
38
|
export declare const setProperty: (value: Unknown) => (path: List<string>) => (src: Unknown) => Unknown;
|
|
33
39
|
export type Entry = ObjectEntry<Unknown>;
|
|
34
40
|
type Entries = List<Entry>;
|
|
@@ -37,6 +43,7 @@ export declare const serialize: (mapEntries: MapEntries) => (value: Unknown) =>
|
|
|
37
43
|
/**
|
|
38
44
|
* The standard `JSON.stringify` rules determined by
|
|
39
45
|
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
|
|
46
|
+
* https://tc39.es/ecma262/#sec-serializejsonproperty
|
|
40
47
|
*/
|
|
41
48
|
export declare const stringify: (mapEntries: MapEntries) => (value: Unknown) => string;
|
|
42
49
|
export declare const parse: (value: string) => Unknown;
|
package/fs/json/module.f.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { next, flat, map } from "../types/list/module.f.js";
|
|
12
12
|
import { concat } from "../types/string/module.f.js";
|
|
13
|
-
import { at } from "../types/object/module.f.js";
|
|
13
|
+
import { at, definedEntries } from "../types/object/module.f.js";
|
|
14
14
|
import { compose, fn } from "../types/function/module.f.js";
|
|
15
15
|
import { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from "./serializer/module.f.js";
|
|
16
16
|
import { boolean as rttiBoolean, number as rttiNumber, string as rttiString, or, record, array as rttiArray } from "../types/rtti/module.f.js";
|
|
@@ -27,14 +27,15 @@ export const primitive = or(null, rttiBoolean, rttiNumber, rttiString);
|
|
|
27
27
|
* core's `unknown`, the JSON `unknown` excludes `undefined`.
|
|
28
28
|
*/
|
|
29
29
|
export const unknown = () => ['or', primitive, object, array];
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* rtti schema matching a JSON object: `{ readonly [k: string]?: Unknown }`.
|
|
32
|
+
*/
|
|
31
33
|
export const object = record(unknown);
|
|
32
34
|
/** rtti schema matching a JSON array: `readonly Unknown[]`. */
|
|
33
35
|
export const array = rttiArray(unknown);
|
|
34
36
|
// ── JSON utilities ────────────────────────────────────────────────────────────
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
const f = path => src => {
|
|
37
|
+
export const setProperty = (value) => {
|
|
38
|
+
const f = (path) => (src) => {
|
|
38
39
|
const result = next(path);
|
|
39
40
|
if (result === null) {
|
|
40
41
|
return value;
|
|
@@ -53,12 +54,12 @@ export const serialize = sort => {
|
|
|
53
54
|
f(v)
|
|
54
55
|
]);
|
|
55
56
|
const mapPropertySerialize = map(propertySerialize);
|
|
56
|
-
const objectSerialize = fn(
|
|
57
|
+
const objectSerialize = fn((definedEntries))
|
|
57
58
|
.map(sort)
|
|
58
59
|
.map(mapPropertySerialize)
|
|
59
60
|
.map(objectWrap)
|
|
60
61
|
.result;
|
|
61
|
-
const f = value => {
|
|
62
|
+
const f = (value) => {
|
|
62
63
|
switch (typeof value) {
|
|
63
64
|
case 'boolean': {
|
|
64
65
|
return boolSerialize(value);
|
|
@@ -86,6 +87,7 @@ export const serialize = sort => {
|
|
|
86
87
|
/**
|
|
87
88
|
* The standard `JSON.stringify` rules determined by
|
|
88
89
|
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
|
|
90
|
+
* https://tc39.es/ecma262/#sec-serializejsonproperty
|
|
89
91
|
*/
|
|
90
92
|
export const stringify = sort => compose(serialize(sort))(concat);
|
|
91
93
|
export const parse = JSON.parse;
|
|
@@ -68,10 +68,9 @@ const isValueToken = token => {
|
|
|
68
68
|
};
|
|
69
69
|
const parseValueOp = token => state => {
|
|
70
70
|
switch (token.kind) {
|
|
71
|
+
// A value is required here (top level, after `[`+`,`, or after `:`),
|
|
72
|
+
// so `]` is never valid — strict JSON has no trailing commas.
|
|
71
73
|
case ']':
|
|
72
|
-
if (state.status === '[,') {
|
|
73
|
-
return endArray(state);
|
|
74
|
-
}
|
|
75
74
|
return { status: 'error', message: 'unexpected token' };
|
|
76
75
|
case '[': return startArray(state);
|
|
77
76
|
case '{': return startObject(state);
|
|
@@ -131,9 +130,8 @@ const parseObjectNextOp = token => state => {
|
|
|
131
130
|
return { status: 'error', message: 'unexpected token' };
|
|
132
131
|
};
|
|
133
132
|
const parseObjectCommaOp = token => state => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
133
|
+
// After a `,` a member (string key) is required — `}` here would be a
|
|
134
|
+
// trailing comma, which strict JSON rejects.
|
|
137
135
|
if (token.kind === 'string') {
|
|
138
136
|
return pushKey(state)(token.value);
|
|
139
137
|
}
|
|
@@ -119,30 +119,31 @@ export const proof = {
|
|
|
119
119
|
if (result !== '["ok",{"a":{"b":{"c":["d"]}}}]') {
|
|
120
120
|
throw result;
|
|
121
121
|
}
|
|
122
|
-
}
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
invalid: [
|
|
123
125
|
() => {
|
|
124
|
-
const tokenList = tokenizeString('
|
|
126
|
+
const tokenList = tokenizeString('');
|
|
125
127
|
const obj = parse(tokenList);
|
|
126
128
|
const result = stringify(obj);
|
|
127
|
-
if (result !== '["
|
|
129
|
+
if (result !== '["error","unexpected end"]') {
|
|
128
130
|
throw result;
|
|
129
131
|
}
|
|
130
132
|
},
|
|
133
|
+
// Trailing commas are not valid JSON — strict parser rejects them.
|
|
131
134
|
() => {
|
|
132
|
-
const tokenList = tokenizeString('
|
|
135
|
+
const tokenList = tokenizeString('[1,]');
|
|
133
136
|
const obj = parse(tokenList);
|
|
134
137
|
const result = stringify(obj);
|
|
135
|
-
if (result !== '["
|
|
138
|
+
if (result !== '["error","unexpected token"]') {
|
|
136
139
|
throw result;
|
|
137
140
|
}
|
|
138
|
-
}
|
|
139
|
-
],
|
|
140
|
-
invalid: [
|
|
141
|
+
},
|
|
141
142
|
() => {
|
|
142
|
-
const tokenList = tokenizeString('');
|
|
143
|
+
const tokenList = tokenizeString('{"a":1,}');
|
|
143
144
|
const obj = parse(tokenList);
|
|
144
145
|
const result = stringify(obj);
|
|
145
|
-
if (result !== '["error","unexpected
|
|
146
|
+
if (result !== '["error","unexpected token"]') {
|
|
146
147
|
throw result;
|
|
147
148
|
}
|
|
148
149
|
},
|
|
@@ -290,6 +291,14 @@ export const proof = {
|
|
|
290
291
|
throw result;
|
|
291
292
|
}
|
|
292
293
|
},
|
|
294
|
+
() => {
|
|
295
|
+
const tokenList = tokenizeString('{"a":1 "b":2}');
|
|
296
|
+
const obj = parse(tokenList);
|
|
297
|
+
const result = stringify(obj);
|
|
298
|
+
if (result !== '["error","unexpected token"]') {
|
|
299
|
+
throw result;
|
|
300
|
+
}
|
|
301
|
+
},
|
|
293
302
|
() => {
|
|
294
303
|
const tokenList = tokenizeString('[{]}');
|
|
295
304
|
const obj = parse(tokenList);
|
package/fs/json/proof.f.d.ts
CHANGED
package/fs/json/proof.f.js
CHANGED
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
import { setProperty, stringify } from "./module.f.js";
|
|
2
2
|
import { sort } from "../types/object/module.f.js";
|
|
3
3
|
import { identity } from "../types/function/module.f.js";
|
|
4
|
+
import { assertEq } from "../asserts/module.f.js";
|
|
4
5
|
export const proof = {
|
|
5
|
-
setProperty:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
setProperty: [
|
|
7
|
+
() => {
|
|
8
|
+
if (setProperty("Hello")([])({}) !== "Hello") {
|
|
9
|
+
throw 'error';
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
() => {
|
|
13
|
+
// src === null: should treat as empty object
|
|
14
|
+
const x = stringify(sort)(setProperty("Hello")(['a'])(null));
|
|
15
|
+
if (x !== '{"a":"Hello"}') {
|
|
16
|
+
throw x;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
() => {
|
|
20
|
+
// typeof src !== 'object': primitive src treated as empty object
|
|
21
|
+
const x = stringify(sort)(setProperty("Hello")(['a'])(42));
|
|
22
|
+
if (x !== '{"a":"Hello"}') {
|
|
23
|
+
throw x;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
() => {
|
|
27
|
+
// src instanceof Array: array src treated as empty object
|
|
28
|
+
const x = stringify(sort)(setProperty("Hello")(['a'])([1, 2]));
|
|
29
|
+
if (x !== '{"a":"Hello"}') {
|
|
30
|
+
throw x;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
],
|
|
10
34
|
stringify: [
|
|
11
35
|
{
|
|
12
36
|
sort: () => {
|
|
@@ -55,5 +79,8 @@ export const proof = {
|
|
|
55
79
|
}
|
|
56
80
|
}
|
|
57
81
|
}
|
|
58
|
-
]
|
|
82
|
+
],
|
|
83
|
+
undefined: () => {
|
|
84
|
+
assertEq(stringify(sort)({ x: undefined }), '{}');
|
|
85
|
+
}
|
|
59
86
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { Ts } from '../../types/rtti/ts/module.f.ts';
|
|
2
2
|
import type { Result } from '../../types/result/module.f.ts';
|
|
3
3
|
import { type Unknown } from '../module.f.ts';
|
|
4
|
+
export declare const jsonrpc: "2.0";
|
|
4
5
|
/** Request/response identifier: a string, a number, or `null`. */
|
|
5
6
|
declare const id: import("../../types/rtti/module.f.ts").Or<[import("../../types/rtti/module.f.ts").String, import("../../types/rtti/module.f.ts").Number, null]>;
|
|
6
7
|
/**
|
|
7
8
|
* A request or notification envelope. `id` present → request (a response is
|
|
8
9
|
* expected); `id` absent → notification (no response). `params` is optional.
|
|
10
|
+
*
|
|
11
|
+
* https://www.jsonrpc.org/specification#request_object
|
|
9
12
|
*/
|
|
10
13
|
export declare const request: {
|
|
11
14
|
readonly jsonrpc: "2.0";
|
|
@@ -42,6 +45,8 @@ export declare const errorResponse: {
|
|
|
42
45
|
* runtime decoder and the static type, with no drift. rtti structs are open
|
|
43
46
|
* (extra keys allowed), so "result XOR error" is not enforced at runtime; in
|
|
44
47
|
* practice the dispatcher only ever constructs one or the other.
|
|
48
|
+
*
|
|
49
|
+
* https://www.jsonrpc.org/specification#response_object
|
|
45
50
|
*/
|
|
46
51
|
export declare const response: import("../../types/rtti/module.f.ts").Or<[{
|
|
47
52
|
readonly jsonrpc: "2.0";
|
package/fs/json/rpc/module.f.js
CHANGED
|
@@ -10,17 +10,21 @@
|
|
|
10
10
|
* `fs/effects/node`, and concrete method sets such as MCP (i665-mcp), which layer
|
|
11
11
|
* on top of `dispatch`.
|
|
12
12
|
*
|
|
13
|
+
* https://www.jsonrpc.org/specification
|
|
14
|
+
*
|
|
13
15
|
* @module
|
|
14
16
|
*/
|
|
15
17
|
import { number, string, or, option } from "../../types/rtti/module.f.js";
|
|
16
18
|
import { validate } from "../../types/rtti/validate/module.f.js";
|
|
17
19
|
import { unknown } from "../module.f.js";
|
|
18
|
-
const jsonrpc = '2.0';
|
|
20
|
+
export const jsonrpc = '2.0';
|
|
19
21
|
/** Request/response identifier: a string, a number, or `null`. */
|
|
20
22
|
const id = or(string, number, null);
|
|
21
23
|
/**
|
|
22
24
|
* A request or notification envelope. `id` present → request (a response is
|
|
23
25
|
* expected); `id` absent → notification (no response). `params` is optional.
|
|
26
|
+
*
|
|
27
|
+
* https://www.jsonrpc.org/specification#request_object
|
|
24
28
|
*/
|
|
25
29
|
export const request = {
|
|
26
30
|
jsonrpc,
|
|
@@ -42,6 +46,8 @@ export const errorResponse = { jsonrpc, error, id };
|
|
|
42
46
|
* runtime decoder and the static type, with no drift. rtti structs are open
|
|
43
47
|
* (extra keys allowed), so "result XOR error" is not enforced at runtime; in
|
|
44
48
|
* practice the dispatcher only ever constructs one or the other.
|
|
49
|
+
*
|
|
50
|
+
* https://www.jsonrpc.org/specification#response_object
|
|
45
51
|
*/
|
|
46
52
|
export const response = or(successResponse, errorResponse);
|
|
47
53
|
/** Decodes an untrusted value as a JSON-RPC request / notification. */
|
|
@@ -54,7 +60,7 @@ export const invalidRequest = rpcError(-32600)('Invalid Request');
|
|
|
54
60
|
export const methodNotFound = rpcError(-32601)('Method not found');
|
|
55
61
|
export const invalidParams = rpcError(-32602)('Invalid params');
|
|
56
62
|
export const internalError = rpcError(-32603)('Internal error');
|
|
57
|
-
const errorResponseOf = (id) => (
|
|
63
|
+
const errorResponseOf = (id) => (error) => ({ jsonrpc, error, id });
|
|
58
64
|
/**
|
|
59
65
|
* Dispatches an already-parsed JSON-RPC value against `handlers`.
|
|
60
66
|
*
|
|
@@ -64,21 +70,20 @@ const errorResponseOf = (id) => (e) => ({ jsonrpc, error: e, id });
|
|
|
64
70
|
* - otherwise the handler's `ok` / `error` result becomes a success / error response
|
|
65
71
|
*/
|
|
66
72
|
export const dispatch = (handlers) => (value) => {
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
73
|
+
const [t, message] = decodeRequest(value);
|
|
74
|
+
if (t === 'error') {
|
|
69
75
|
return errorResponseOf(null)(invalidRequest);
|
|
70
76
|
}
|
|
71
|
-
const
|
|
72
|
-
const id = message.id;
|
|
77
|
+
const { id, method, params } = message;
|
|
73
78
|
if (id === undefined) {
|
|
74
79
|
return null;
|
|
75
80
|
}
|
|
76
|
-
const handler = handlers[
|
|
81
|
+
const handler = handlers[method];
|
|
77
82
|
if (handler === undefined) {
|
|
78
83
|
return errorResponseOf(id)(methodNotFound);
|
|
79
84
|
}
|
|
80
|
-
const result = handler(
|
|
81
|
-
return
|
|
82
|
-
? { jsonrpc, result
|
|
83
|
-
: errorResponseOf(id)(result
|
|
85
|
+
const [t2, result] = handler(params);
|
|
86
|
+
return t2 === 'ok'
|
|
87
|
+
? { jsonrpc, result, id }
|
|
88
|
+
: errorResponseOf(id)(result);
|
|
84
89
|
};
|