functionalscript 0.45.0 → 0.46.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/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +10 -0
- package/fjs/asn.1/proof.f.mjs +16 -0
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -3
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +28 -14
- package/fjs/bnf/descent/module.f.mjs +122 -77
- package/fjs/bnf/descent/proof.f.d.mts +2 -0
- package/fjs/bnf/descent/proof.f.mjs +117 -31
- package/fjs/bnf/descent/types.d.ts +12 -14
- package/fjs/bnf/ll1/module.f.d.mts +64 -22
- package/fjs/bnf/ll1/module.f.mjs +214 -154
- package/fjs/bnf/ll1/proof.f.d.mts +15 -2
- package/fjs/bnf/ll1/proof.f.mjs +323 -149
- package/fjs/bnf/ll1/types.d.ts +16 -24
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +1 -3
- package/fjs/cas/cli/proof.f.mjs +44 -33
- package/fjs/cas/evo/module.f.d.mts +64 -18
- package/fjs/cas/evo/module.f.mjs +148 -70
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +305 -223
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +129 -128
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/config/module.f.d.mts +2 -2
- package/fjs/ci/config/module.f.mjs +2 -2
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.mjs +2 -2
- package/fjs/ci/proof.f.mjs +9 -5
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.mjs +17 -16
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/types.d.ts +1 -1
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +1 -0
- package/fjs/crypto/sha2/proof.f.mjs +24 -0
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/dev/module.f.d.mts +13 -4
- package/fjs/dev/module.f.mjs +56 -27
- package/fjs/dev/update/module.f.d.mts +9 -4
- package/fjs/dev/update/module.f.mjs +14 -10
- package/fjs/dev/update/proof.f.d.mts +1 -3
- package/fjs/dev/update/proof.f.mjs +10 -5
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +13 -3
- package/fjs/djs/parser/module.f.mjs +117 -16
- package/fjs/djs/parser/proof.f.d.mts +5 -1
- package/fjs/djs/parser/proof.f.mjs +274 -12
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +18 -2
- package/fjs/djs/proof.f.mjs +187 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +61 -15
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +99 -60
- package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
- package/fjs/djs/tokenizer/proof.f.mjs +74 -67
- package/fjs/djs/transpiler/module.f.d.mts +12 -7
- package/fjs/djs/transpiler/module.f.mjs +82 -56
- package/fjs/djs/transpiler/types.d.ts +7 -3
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +14 -11
- package/fjs/effects/list/module.f.mjs +13 -11
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +2 -1
- package/fjs/effects/memory/module.f.mjs +3 -4
- package/fjs/effects/memory/proof.f.mjs +13 -7
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +20 -4
- package/fjs/effects/mock/module.f.mjs +37 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +4 -2
- package/fjs/effects/module.f.d.mts +466 -280
- package/fjs/effects/module.f.mjs +537 -299
- package/fjs/effects/module.mjs +2 -1
- package/fjs/effects/node/memory/module.d.mts +4 -2
- package/fjs/effects/node/memory/module.mjs +6 -3
- package/fjs/effects/node/memory/proof.mjs +10 -4
- package/fjs/effects/node/module.d.mts +4 -3
- package/fjs/effects/node/module.f.d.mts +168 -33
- package/fjs/effects/node/module.f.mjs +256 -52
- package/fjs/effects/node/module.mjs +57 -34
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +18 -4
- package/fjs/effects/node/virtual/module.f.mjs +110 -68
- package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
- package/fjs/effects/node/virtual/proof.f.mjs +190 -9
- package/fjs/effects/proof.f.d.mts +69 -37
- package/fjs/effects/proof.f.mjs +410 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/module.f.d.mts +19 -12
- package/fjs/emergent_testing/module.f.mjs +93 -33
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +166 -32
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +2 -0
- package/fjs/fsm/proof.f.mjs +83 -114
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/js/keywords/proof.f.d.mts +3 -0
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +26 -6
- package/fjs/js/tokenizer/module.f.mjs +145 -159
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +4 -4
- package/fjs/mcp/module.f.mjs +6 -6
- package/fjs/mcp/proof.f.d.mts +5 -3
- package/fjs/mcp/proof.f.mjs +112 -46
- package/fjs/media/html/module.f.mjs +1 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +114 -70
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +33 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.mjs +9 -9
- package/fjs/media/json/schema/module.f.mjs +3 -13
- package/fjs/media/json/schema/proof.f.d.mts +0 -1
- package/fjs/media/json/schema/proof.f.mjs +1 -2
- package/fjs/media/json/serializer/module.f.d.mts +32 -1
- package/fjs/media/json/serializer/module.f.mjs +64 -2
- package/fjs/media/json/tokenizer/module.f.mjs +7 -3
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +78 -7
- package/fjs/media/revision/module.f.mjs +119 -12
- package/fjs/media/revision/proof.f.d.mts +10 -0
- package/fjs/media/revision/proof.f.mjs +88 -0
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +33 -15
- package/fjs/media/type/module.f.mjs +35 -29
- package/fjs/media/type/proof.f.d.mts +2 -1
- package/fjs/media/type/proof.f.mjs +30 -10
- package/fjs/module.f.mjs +29 -8
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/proof.f.d.mts +3 -3
- package/fjs/proof.f.mjs +36 -10
- package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
- package/fjs/protocol/json_rpc/module.f.mjs +3 -3
- package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +13 -4
- package/fjs/protocol/mcp/proof.f.mjs +193 -61
- package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
- package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
- package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +0 -1
- package/fjs/sul/id/module.f.mjs +2 -3
- package/fjs/sul/level/hash/module.f.mjs +2 -1
- package/fjs/sul/level/hash/proof.f.mjs +2 -2
- package/fjs/sul/module.f.mjs +18 -13
- package/fjs/text/code_point/module.f.d.mts +8 -0
- package/fjs/text/code_point/module.f.mjs +8 -1
- package/fjs/text/code_point/proof.f.d.mts +1 -0
- package/fjs/text/code_point/proof.f.mjs +11 -0
- package/fjs/text/sgr/module.f.d.mts +4 -6
- package/fjs/text/sgr/module.f.mjs +6 -7
- package/fjs/text/utf16/module.f.mjs +7 -2
- package/fjs/text/utf16/proof.f.mjs +3 -3
- package/fjs/text/utf8/module.f.mjs +4 -2
- package/fjs/types/array/module.f.mjs +14 -2
- package/fjs/types/bit_vec/module.f.d.mts +0 -2
- package/fjs/types/bit_vec/module.f.mjs +46 -32
- package/fjs/types/bit_vec/proof.f.mjs +2 -2
- package/fjs/types/btree/remove/module.f.mjs +1 -1
- package/fjs/types/btree/set/module.f.mjs +9 -11
- package/fjs/types/btree/set/proof.f.mjs +12 -0
- package/fjs/types/byte_set/module.f.d.mts +11 -4
- package/fjs/types/byte_set/module.f.mjs +14 -6
- package/fjs/types/byte_set/proof.f.mjs +7 -7
- package/fjs/types/function/compare/module.f.mjs +10 -3
- package/fjs/types/list/module.f.d.mts +1 -1
- package/fjs/types/list/module.f.mjs +1 -1
- package/fjs/types/nullable/module.f.d.mts +18 -4
- package/fjs/types/nullable/module.f.mjs +21 -4
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/object/module.f.d.mts +12 -2
- package/fjs/types/object/module.f.mjs +11 -1
- package/fjs/types/patricia_trie/module.f.mjs +26 -11
- package/fjs/types/result/module.f.d.mts +3 -3
- package/fjs/types/result/module.f.mjs +3 -3
- package/fjs/types/rtti/common/module.f.d.mts +25 -28
- package/fjs/types/rtti/common/module.f.mjs +36 -32
- package/fjs/types/rtti/common/proof.f.mjs +5 -5
- package/fjs/types/rtti/data/module.f.d.mts +14 -0
- package/fjs/types/rtti/data/module.f.mjs +25 -2
- package/fjs/types/rtti/data/proof.f.d.mts +1 -0
- package/fjs/types/rtti/data/proof.f.mjs +25 -2
- package/fjs/types/rtti/parse/module.f.d.mts +24 -14
- package/fjs/types/rtti/parse/module.f.mjs +37 -28
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +33 -14
- package/fjs/types/rtti/proof.f.mjs +3 -1
- package/fjs/types/rtti/ts/module.f.mjs +13 -17
- package/fjs/types/rtti/ts/types.d.ts +14 -1
- package/fjs/types/sorted_set/module.f.d.mts +18 -0
- package/fjs/types/sorted_set/module.f.mjs +22 -0
- package/fjs/types/sorted_set/proof.f.d.mts +1 -0
- package/fjs/types/sorted_set/proof.f.mjs +16 -1
- package/fjs/types/uint8array/module.f.d.mts +1 -1
- package/fjs/types/uint8array/module.f.mjs +1 -1
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +4 -7
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +2 -2
- package/fjs/dev/package_json/module.f.d.mts +0 -39
- package/fjs/dev/package_json/module.f.mjs +0 -40
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/effects/eff/module.f.d.mts +0 -20
- package/fjs/effects/eff/module.f.mjs +0 -70
- package/fjs/effects/eff/proof.f.d.mts +0 -15
- package/fjs/effects/eff/proof.f.mjs +0 -69
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/types/rtti/validate/module.f.d.mts +0 -41
- package/fjs/types/rtti/validate/module.f.mjs +0 -171
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
|
@@ -109,32 +109,32 @@ export const proof = {
|
|
|
109
109
|
error: () => assertError(parse(/** @type {const} */ (42))(43)),
|
|
110
110
|
},
|
|
111
111
|
nan: {
|
|
112
|
-
ok: () => assertOk(parse(
|
|
112
|
+
ok: () => assertOk(parse(NaN)(NaN)),
|
|
113
113
|
error: () => {
|
|
114
|
-
assertError(parse(
|
|
114
|
+
assertError(parse(NaN)(0))
|
|
115
115
|
assertError(parse(/** @type {const} */ (0))(NaN))
|
|
116
116
|
assertError(parse(/** @type {const} */ (42))(NaN))
|
|
117
117
|
},
|
|
118
118
|
},
|
|
119
119
|
infinity: {
|
|
120
120
|
ok: () => {
|
|
121
|
-
assertOk(parse(
|
|
122
|
-
assertOk(parse(
|
|
121
|
+
assertOk(parse(Infinity)(Infinity))
|
|
122
|
+
assertOk(parse(-Infinity)(-Infinity))
|
|
123
123
|
},
|
|
124
124
|
error: () => {
|
|
125
|
-
assertError(parse(
|
|
126
|
-
assertError(parse(
|
|
125
|
+
assertError(parse(Infinity)(-Infinity))
|
|
126
|
+
assertError(parse(Infinity)(0))
|
|
127
127
|
},
|
|
128
128
|
},
|
|
129
129
|
signedZero: {
|
|
130
130
|
// `Object.is` distinguishes +0 and -0; `===` treats them equal.
|
|
131
131
|
distinct: () => {
|
|
132
132
|
assertError(parse(/** @type {const} */ (0))(-0))
|
|
133
|
-
assertError(parse(
|
|
133
|
+
assertError(parse(-0)(0))
|
|
134
134
|
},
|
|
135
135
|
self: () => {
|
|
136
136
|
assertOk(parse(/** @type {const} */ (0))(0))
|
|
137
|
-
assertOk(parse(
|
|
137
|
+
assertOk(parse(-0)(-0))
|
|
138
138
|
},
|
|
139
139
|
},
|
|
140
140
|
string: {
|
|
@@ -155,14 +155,31 @@ export const proof = {
|
|
|
155
155
|
const r = parse(t)([42, 'hello'])
|
|
156
156
|
assertStructurallySame(unwrap(r), [42, 'hello'])
|
|
157
157
|
},
|
|
158
|
-
//
|
|
159
|
-
|
|
158
|
+
// A tuple is OPEN: a longer array is accepted, and the extras are
|
|
159
|
+
// absent from what `parse` builds. This is deliberate — see
|
|
160
|
+
// "Structs and tuples are open" in ../README.md. Do not add a
|
|
161
|
+
// length check here on the strength of `Ts<readonly [42]>` being
|
|
162
|
+
// an exact tuple; that mapping is exact only because TypeScript
|
|
163
|
+
// could not express the open one (see ../ts/types.ts `TupleTs`),
|
|
164
|
+
// and reading it as a design decision is what produced #1622.
|
|
165
|
+
extraItemsAcceptedAndDropped: () => {
|
|
160
166
|
const r = parse(/** @type {const} */ ([42]))([42, 'extra'])
|
|
161
167
|
assertStructurallySame(unwrap(r), [42])
|
|
168
|
+
const long = parse(/** @type {const} */ ([42]))([42, 1, 2, 3])
|
|
169
|
+
assertStructurallySame(unwrap(long), [42])
|
|
170
|
+
},
|
|
171
|
+
// An absent member reads as `undefined`, so a position is required
|
|
172
|
+
// exactly when its set excludes `undefined` — the same rule the
|
|
173
|
+
// data form states for object keys, applied to arrays.
|
|
174
|
+
shortArrayFillsAnOptionalPosition: () => {
|
|
175
|
+
const r = parse([number, option(string)])([42])
|
|
176
|
+
assertStructurallySame(unwrap(r), [42, undefined])
|
|
162
177
|
},
|
|
163
178
|
error: () => {
|
|
164
179
|
assertError(parse(/** @type {const} */ ([42]))([99]))
|
|
165
180
|
assertError(parse(/** @type {const} */ ([42]))({}))
|
|
181
|
+
// `42` excludes `undefined`, so position 0 is required.
|
|
182
|
+
assertError(parse(/** @type {const} */ ([42]))([]))
|
|
166
183
|
},
|
|
167
184
|
},
|
|
168
185
|
struct: {
|
|
@@ -171,8 +188,10 @@ export const proof = {
|
|
|
171
188
|
const r = parse(t)({ a: 42, b: 'hello' })
|
|
172
189
|
assertStructurallySame(unwrap(r), { a: 42, b: 'hello' })
|
|
173
190
|
},
|
|
174
|
-
//
|
|
175
|
-
|
|
191
|
+
// A struct is OPEN, on the same terms as a tuple: undeclared
|
|
192
|
+
// properties are accepted and absent from what `parse` builds.
|
|
193
|
+
// See "Structs and tuples are open" in ../README.md.
|
|
194
|
+
extraKeysAcceptedAndDropped: () => {
|
|
176
195
|
const r = parse(/** @type {const} */ ({ a: /** @type {const} */ (42) }))({ a: 42, b: 'extra' })
|
|
177
196
|
assertStructurallySame(unwrap(r), { a: 42 })
|
|
178
197
|
},
|
|
@@ -196,7 +215,7 @@ export const proof = {
|
|
|
196
215
|
const input = [1, 2, 3]
|
|
197
216
|
/** @type {readonly number[]} */
|
|
198
217
|
const out = unwrap(parse(array(number))(input))
|
|
199
|
-
assert(out !==
|
|
218
|
+
assert(out !== input, 'expected a fresh array')
|
|
200
219
|
assertStructurallySame(out, [1, 2, 3])
|
|
201
220
|
},
|
|
202
221
|
error: () => {
|
|
@@ -224,7 +243,7 @@ export const proof = {
|
|
|
224
243
|
const input = { a: 1, b: 2 }
|
|
225
244
|
/** @type {Record<string, number>} */
|
|
226
245
|
const out = unwrap(parse(record(number))(input))
|
|
227
|
-
assert(out !==
|
|
246
|
+
assert(out !== input, 'expected a fresh record')
|
|
228
247
|
assertStructurallySame(out, { a: 1, b: 2 })
|
|
229
248
|
},
|
|
230
249
|
error: () => {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* @import { StringMap } from '../object/types.ts'
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { assertNotNullish } from '../../asserts/module.f.mjs'
|
|
6
|
+
|
|
5
7
|
/** @typedef {StringMap<readonly unknown[]>} _Tests */
|
|
6
8
|
|
|
7
9
|
/** @type {_Tests} */
|
|
@@ -16,7 +18,7 @@ const tests = {
|
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export const proof = {
|
|
19
|
-
typeof: Object.fromEntries(Object.entries(tests).map(([k, a]) => [k,
|
|
21
|
+
typeof: Object.fromEntries(Object.entries(tests).map(([k, a]) => [k, assertNotNullish(a).map(v => () => {
|
|
20
22
|
if (typeof v !== k) { throw `typeof ${v} !== ${k}` }
|
|
21
23
|
})])),
|
|
22
24
|
}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { assertNotNullish } from '../../../asserts/module.f.mjs'
|
|
22
|
+
import { reservedWords, strictModeReservedWords } from '../../../js/keywords/module.f.mjs'
|
|
22
23
|
import { at, definedEntries } from '../../object/module.f.mjs'
|
|
23
24
|
import { primitive, union, printer as tsPrinter } from '../../ts/module.f.mjs'
|
|
24
25
|
import { cmp, toData, unitBit, unknown as top } from '../data/module.f.mjs'
|
|
@@ -30,27 +31,22 @@ const trueBit = unitBit(true)
|
|
|
30
31
|
const booleanBits = falseBit | trueBit
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
* Names that cannot name a TypeScript type alias: the
|
|
34
|
-
*
|
|
35
|
-
* strict-mode
|
|
36
|
-
* (`TS1214`) —
|
|
34
|
+
* Names that cannot name a TypeScript type alias: the ECMAScript reserved
|
|
35
|
+
* words — from the one source of truth for JavaScript keywords,
|
|
36
|
+
* `fjs/js/keywords`, the strict-mode ones included since every module is
|
|
37
|
+
* strict-mode code (`TS1214`) — plus TypeScript's predefined type names
|
|
38
|
+
* (`TS2457`) and the type keywords that fail in the alias-name position.
|
|
37
39
|
*/
|
|
38
|
-
|
|
40
|
+
/** @type {readonly string[]} */
|
|
41
|
+
const reserved = [
|
|
42
|
+
...reservedWords,
|
|
43
|
+
...strictModeReservedWords,
|
|
39
44
|
// predefined type names
|
|
40
|
-
'any', 'bigint', 'boolean', '
|
|
41
|
-
'
|
|
42
|
-
// ECMAScript reserved words
|
|
43
|
-
'await', 'break', 'case', 'catch', 'class', 'const', 'continue',
|
|
44
|
-
'debugger', 'default', 'delete', 'do', 'else', 'enum', 'export',
|
|
45
|
-
'extends', 'finally', 'for', 'function', 'if', 'import', 'in',
|
|
46
|
-
'instanceof', 'new', 'return', 'super', 'switch', 'this', 'throw', 'try',
|
|
47
|
-
'typeof', 'var', 'while', 'with',
|
|
48
|
-
// reserved in strict-mode code — and every module is strict-mode code
|
|
49
|
-
'implements', 'interface', 'let', 'package', 'private', 'protected',
|
|
50
|
-
'public', 'static', 'yield',
|
|
45
|
+
'any', 'bigint', 'boolean', 'never', 'number', 'object', 'string',
|
|
46
|
+
'symbol', 'undefined', 'unknown',
|
|
51
47
|
// type-operator keywords, and `intrinsic` (TS2795 outside lib.d.ts)
|
|
52
48
|
'infer', 'intrinsic', 'keyof', 'readonly', 'unique',
|
|
53
|
-
]
|
|
49
|
+
]
|
|
54
50
|
|
|
55
51
|
/** @type {(c: string) => boolean} */
|
|
56
52
|
const isIdStart = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c === '_' || c === '$'
|
|
@@ -51,7 +51,20 @@ export type ArrayTs<T extends Type> = ReadonlyArray<Ts<T>>;
|
|
|
51
51
|
export type RecordTs<T extends Type> = {
|
|
52
52
|
readonly [K in string]?: Ts<T>;
|
|
53
53
|
};
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Maps a tuple schema to a readonly tuple of resolved types.
|
|
56
|
+
*
|
|
57
|
+
* **The commented-out line is the accurate mapping.** A tuple schema is *open*
|
|
58
|
+
* — a longer array is a member of the set it describes (see "Structs and
|
|
59
|
+
* tuples are open" in `../README.md`) — and the open form below says so. It is
|
|
60
|
+
* commented out because TypeScript could not handle it, so this renders the
|
|
61
|
+
* closed approximation instead.
|
|
62
|
+
*
|
|
63
|
+
* That is a limitation of this renderer, **not** a statement about the value
|
|
64
|
+
* model. Do not cite the exact mapping as evidence that tuples are closed and
|
|
65
|
+
* add a length check to `../parse/module.f.mjs`; that inference is what
|
|
66
|
+
* produced #1622.
|
|
67
|
+
*/
|
|
55
68
|
export type TupleTs<T extends Tuple> = {
|
|
56
69
|
readonly [K in keyof T]: Ts<T[K]>;
|
|
57
70
|
};
|
|
@@ -52,3 +52,21 @@ export declare const has: <T>(
|
|
|
52
52
|
* @returns {(value: T) => (set: SortedSet<T>) => boolean}
|
|
53
53
|
*/
|
|
54
54
|
cmp: Cmp<T>) => (value: T) => (set: SortedSet<T>) => boolean;
|
|
55
|
+
/**
|
|
56
|
+
* A canonical key for a set of strings: equal sets always produce the same
|
|
57
|
+
* key, and unequal sets never produce the same one. Useful wherever a set has
|
|
58
|
+
* to index a `StringMap` — the subset construction in `fjs/fsm`, say.
|
|
59
|
+
*
|
|
60
|
+
* Each element is written length-prefixed (`3:abc`) and the parts are
|
|
61
|
+
* concatenated. Joining on a separator would **not** be canonical: elements
|
|
62
|
+
* are arbitrary strings, so `['a,b']` and `['a', 'b']` would both produce
|
|
63
|
+
* `a,b` and two different sets would share one key. A length prefix is
|
|
64
|
+
* readable back — take the digits, the `:`, then exactly that many code
|
|
65
|
+
* units — so the encoding is injective without an escaping table.
|
|
66
|
+
*
|
|
67
|
+
* The key is canonical for the *set* only because `SortedSet` is sorted:
|
|
68
|
+
* element order is fixed by the set's own invariant, not by this function.
|
|
69
|
+
*
|
|
70
|
+
* @type {(set: SortedSet<string>) => string}
|
|
71
|
+
*/
|
|
72
|
+
export declare const toKey: (set: SortedSet<string>) => string;
|
|
@@ -56,3 +56,25 @@ export const has =
|
|
|
56
56
|
* @returns {(value: T) => (set: SortedSet<T>) => boolean}
|
|
57
57
|
*/
|
|
58
58
|
cmp => value => set => find(cmp)(value)(set) === value
|
|
59
|
+
|
|
60
|
+
/** @type {(s: string) => string} */
|
|
61
|
+
const lengthPrefixed = s => `${s.length}:${s}`
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A canonical key for a set of strings: equal sets always produce the same
|
|
65
|
+
* key, and unequal sets never produce the same one. Useful wherever a set has
|
|
66
|
+
* to index a `StringMap` — the subset construction in `fjs/fsm`, say.
|
|
67
|
+
*
|
|
68
|
+
* Each element is written length-prefixed (`3:abc`) and the parts are
|
|
69
|
+
* concatenated. Joining on a separator would **not** be canonical: elements
|
|
70
|
+
* are arbitrary strings, so `['a,b']` and `['a', 'b']` would both produce
|
|
71
|
+
* `a,b` and two different sets would share one key. A length prefix is
|
|
72
|
+
* readable back — take the digits, the `:`, then exactly that many code
|
|
73
|
+
* units — so the encoding is injective without an escaping table.
|
|
74
|
+
*
|
|
75
|
+
* The key is canonical for the *set* only because `SortedSet` is sorted:
|
|
76
|
+
* element order is fixed by the set's own invariant, not by this function.
|
|
77
|
+
*
|
|
78
|
+
* @type {(set: SortedSet<string>) => string}
|
|
79
|
+
*/
|
|
80
|
+
export const toKey = set => set.map(lengthPrefixed).join('')
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @import { Unknown } from '../../media/json/types.ts'
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { has, intersect, union } from './module.f.mjs'
|
|
5
|
+
import { has, intersect, toKey, union } from './module.f.mjs'
|
|
6
6
|
import { stringify } from '../../media/json/module.f.mjs'
|
|
7
7
|
import { sort } from '../object/module.f.mjs'
|
|
8
8
|
import { toArray, countdown, length } from '../list/module.f.mjs'
|
|
@@ -16,6 +16,21 @@ const str = a => stringify(sort)(a)
|
|
|
16
16
|
const reverseCmp = flip(cmp)
|
|
17
17
|
|
|
18
18
|
export const proof = {
|
|
19
|
+
toKey: [
|
|
20
|
+
() => assertEq(toKey([]), ''),
|
|
21
|
+
() => assertEq(toKey(['']), '0:'),
|
|
22
|
+
() => assertEq(toKey(['a']), '1:a'),
|
|
23
|
+
() => assertEq(toKey(['a', 'b']), '1:a1:b'),
|
|
24
|
+
// The reason the key is length-prefixed rather than separator-joined:
|
|
25
|
+
// these two sets are different and must not share a key, but any
|
|
26
|
+
// fixed separator that can occur in an element collapses them.
|
|
27
|
+
() => assert(toKey(['a,b']) !== toKey(['a', 'b']), 'comma'),
|
|
28
|
+
() => assert(toKey(['a:b']) !== toKey(['a', 'b']), 'colon'),
|
|
29
|
+
() => assert(toKey(['a\nb']) !== toKey(['a', 'b']), 'newline'),
|
|
30
|
+
// A prefix of one element must not be confused with a shorter one.
|
|
31
|
+
() => assert(toKey(['ab']) !== toKey(['a']), 'prefix'),
|
|
32
|
+
() => assert(toKey(['']) !== toKey([]), 'empty element vs empty set'),
|
|
33
|
+
],
|
|
19
34
|
example: () => {
|
|
20
35
|
const cmp = (/** @type {number} */ a) => (/** @type {number} */ b) => a < b ? -1 : a > b ? 1 : 0
|
|
21
36
|
|
|
@@ -19,7 +19,7 @@ import type { List } from '../list/types.ts';
|
|
|
19
19
|
*
|
|
20
20
|
* Throws if the result would exceed `maxLength`. The bound is not precomputed:
|
|
21
21
|
* `tryU8ListToVec` attempts the real conversion and reports `null` when it does
|
|
22
|
-
* not fit (
|
|
22
|
+
* not fit (`DESIGN.md` §6).
|
|
23
23
|
*
|
|
24
24
|
* @type {(input: List<Uint8Array>) => Vec}
|
|
25
25
|
*/
|
|
@@ -29,7 +29,7 @@ const m = map(fromArrayLike)
|
|
|
29
29
|
*
|
|
30
30
|
* Throws if the result would exceed `maxLength`. The bound is not precomputed:
|
|
31
31
|
* `tryU8ListToVec` attempts the real conversion and reports `null` when it does
|
|
32
|
-
* not fit (
|
|
32
|
+
* not fit (`DESIGN.md` §6).
|
|
33
33
|
*
|
|
34
34
|
* @type {(input: List<Uint8Array>) => Vec}
|
|
35
35
|
*/
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*
|
|
6
|
-
* @import { WriteFile } from '../effects/node/types.ts'
|
|
6
|
+
* @import { Write, WriteFile } from '../effects/node/types.ts'
|
|
7
7
|
* @import { Effect } from '../effects/types.ts'
|
|
8
8
|
*/
|
|
9
|
-
import type { WriteFile } from '../effects/node/types.ts';
|
|
9
|
+
import type { Write, WriteFile } from '../effects/node/types.ts';
|
|
10
10
|
import type { Effect } from '../effects/types.ts';
|
|
11
|
-
export declare const main: () => Effect<WriteFile, number>;
|
|
11
|
+
export declare const main: () => Effect<Write | WriteFile, 0, number>;
|
package/fjs/website/module.f.mjs
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*
|
|
6
|
-
* @import { WriteFile } from '../effects/node/types.ts'
|
|
6
|
+
* @import { Write, WriteFile } from '../effects/node/types.ts'
|
|
7
7
|
* @import { Effect } from '../effects/types.ts'
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { htmlUtf8 } from '../media/html/module.f.mjs'
|
|
11
|
-
import { writeFile } from '../effects/node/module.f.mjs'
|
|
12
|
-
import { pure, step } from '../effects/module.f.mjs'
|
|
11
|
+
import { exitStep, writeFile } from '../effects/node/module.f.mjs'
|
|
13
12
|
|
|
14
13
|
const html = htmlUtf8()(
|
|
15
14
|
['a',
|
|
@@ -17,9 +16,7 @@ const html = htmlUtf8()(
|
|
|
17
16
|
'GitHub Repository'
|
|
18
17
|
])
|
|
19
18
|
|
|
20
|
-
/** @type {Effect<WriteFile, number>} */
|
|
21
|
-
const program =
|
|
22
|
-
writeFile('index.html', html),
|
|
23
|
-
() => pure(0))
|
|
19
|
+
/** @type {Effect<WriteFile | Write, 0, number>} */
|
|
20
|
+
const program = exitStep(writeFile('index.html', html))
|
|
24
21
|
|
|
25
22
|
export const main = () => program
|
package/fjs/website/proof.f.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { exitCode } from '../effects/node/module.f.mjs'
|
|
1
2
|
import { main } from './module.f.mjs'
|
|
2
3
|
import { emptyState, virtual } from '../effects/node/virtual/module.f.mjs'
|
|
3
4
|
import { assertEq, assertNotNullish } from '../asserts/module.f.mjs'
|
|
@@ -9,6 +10,6 @@ export const proof = {
|
|
|
9
10
|
run: () => {
|
|
10
11
|
const state = { ...emptyState, root: { '.github': { workflows: {} } } }
|
|
11
12
|
const [_, result] = virtual(state)(main())
|
|
12
|
-
assertEq(result, 0)
|
|
13
|
+
assertEq(exitCode(result), 0)
|
|
13
14
|
},
|
|
14
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"prepack": "tsc --noEmit false --emitDeclarationOnly && tsc",
|
|
14
14
|
"test": "tsc && node ./fjs/module.mjs t",
|
|
15
|
-
"cov": "node --test --experimental-test-coverage --test-coverage-include=**/module.f.mjs
|
|
15
|
+
"cov": "node --test --experimental-test-coverage --test-coverage-include=**/module.f.mjs --test-coverage-lines=100 --test-coverage-branches=100 --test-coverage-functions=100",
|
|
16
16
|
"start": "node ./fjs/module.mjs",
|
|
17
17
|
"ci-update": "node ./fjs/module.mjs ci && node ./fjs/module.mjs r ./fjs/nanvm/update/module.f.mjs",
|
|
18
18
|
"dev-update": "node ./fjs/module.mjs r ./fjs/dev/update/module.f.mjs",
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for reading package.json-style metadata without losing unrelated
|
|
3
|
-
* fields before write-back.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*
|
|
7
|
-
* @import { ValidationError } from '../../types/rtti/common/types.ts'
|
|
8
|
-
* @import { Ts } from '../../types/rtti/ts/types.ts'
|
|
9
|
-
* @import { Result } from '../../types/result/types.ts'
|
|
10
|
-
*/
|
|
11
|
-
import type { ValidationError } from '../../types/rtti/common/types.ts';
|
|
12
|
-
import type { Ts } from '../../types/rtti/ts/types.ts';
|
|
13
|
-
import type { Result } from '../../types/result/types.ts';
|
|
14
|
-
export declare const packageJsonSchema: {
|
|
15
|
-
readonly name: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts")._Type0<"string">, undefined]>;
|
|
16
|
-
readonly version: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts")._Type0<"string">, undefined]>;
|
|
17
|
-
readonly scripts: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Type1<"record", import("../../types/rtti/types.ts")._Type0<"string">>, undefined]>;
|
|
18
|
-
};
|
|
19
|
-
export type PackageJson = Ts<typeof packageJsonSchema>;
|
|
20
|
-
export type JsonTextError = string | ValidationError;
|
|
21
|
-
/** @typedef {Ts<typeof packageJsonSchema>} PackageJson */
|
|
22
|
-
/** @typedef {string | ValidationError} JsonTextError */
|
|
23
|
-
export declare const validatePackageJson: import("../../types/rtti/common/types.ts").Validate<{
|
|
24
|
-
readonly name: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts")._Type0<"string">, undefined]>;
|
|
25
|
-
readonly version: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts")._Type0<"string">, undefined]>;
|
|
26
|
-
readonly scripts: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Type1<"record", import("../../types/rtti/types.ts")._Type0<"string">>, undefined]>;
|
|
27
|
-
}>;
|
|
28
|
-
/**
|
|
29
|
-
* Parses `text` as JSON and validates it against {@link packageJsonSchema}.
|
|
30
|
-
*
|
|
31
|
-
* Both failures reach the caller as they were raised: a parse failure is a
|
|
32
|
-
* `string`, a schema failure a `ValidationError`, and `JsonTextError` is
|
|
33
|
-
* exactly that union — which is what `okThen` produces from the two steps'
|
|
34
|
-
* own error types, with no rewrapping to widen either one.
|
|
35
|
-
*
|
|
36
|
-
* @param {string} text
|
|
37
|
-
* @returns {Result<PackageJson, JsonTextError>}
|
|
38
|
-
*/
|
|
39
|
-
export declare const validatePackageJsonText: (text: string) => Result<PackageJson, JsonTextError>;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for reading package.json-style metadata without losing unrelated
|
|
3
|
-
* fields before write-back.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*
|
|
7
|
-
* @import { ValidationError } from '../../types/rtti/common/types.ts'
|
|
8
|
-
* @import { Ts } from '../../types/rtti/ts/types.ts'
|
|
9
|
-
* @import { Result } from '../../types/result/types.ts'
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { parse as parseJsonText } from '../../media/json/module.f.mjs'
|
|
13
|
-
import { option, record, string } from '../../types/rtti/module.f.mjs'
|
|
14
|
-
import { validate as rttiValidate } from '../../types/rtti/validate/module.f.mjs'
|
|
15
|
-
import { okThen } from '../../types/result/module.f.mjs'
|
|
16
|
-
|
|
17
|
-
export const packageJsonSchema = /** @type {const} */ ({
|
|
18
|
-
name: option(string),
|
|
19
|
-
version: option(string),
|
|
20
|
-
scripts: option(record(string)),
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
/** @typedef {Ts<typeof packageJsonSchema>} PackageJson */
|
|
24
|
-
/** @typedef {string | ValidationError} JsonTextError */
|
|
25
|
-
|
|
26
|
-
export const validatePackageJson = rttiValidate(packageJsonSchema)
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Parses `text` as JSON and validates it against {@link packageJsonSchema}.
|
|
30
|
-
*
|
|
31
|
-
* Both failures reach the caller as they were raised: a parse failure is a
|
|
32
|
-
* `string`, a schema failure a `ValidationError`, and `JsonTextError` is
|
|
33
|
-
* exactly that union — which is what `okThen` produces from the two steps'
|
|
34
|
-
* own error types, with no rewrapping to widen either one.
|
|
35
|
-
*
|
|
36
|
-
* @param {string} text
|
|
37
|
-
* @returns {Result<PackageJson, JsonTextError>}
|
|
38
|
-
*/
|
|
39
|
-
export const validatePackageJsonText = text =>
|
|
40
|
-
okThen(validatePackageJson)(parseJsonText(text))
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { assert, assertEq } from '../../asserts/module.f.mjs'
|
|
2
|
-
import { unwrap } from '../../types/result/module.f.mjs'
|
|
3
|
-
import {
|
|
4
|
-
validatePackageJson,
|
|
5
|
-
validatePackageJsonText,
|
|
6
|
-
} from './module.f.mjs'
|
|
7
|
-
|
|
8
|
-
export const proof = {
|
|
9
|
-
parseMetadata: () => {
|
|
10
|
-
const result = unwrap(validatePackageJsonText('{"name":"x","version":"1.0.0","scripts":{"test":"node test.js"}}'))
|
|
11
|
-
assertEq(result.name, 'x', result)
|
|
12
|
-
assertEq(result.version, '1.0.0', result)
|
|
13
|
-
assertEq(result.scripts?.test, 'node test.js', result)
|
|
14
|
-
},
|
|
15
|
-
malformedJson: () => {
|
|
16
|
-
const result = validatePackageJsonText('{')
|
|
17
|
-
assert(result[0] === 'error', result)
|
|
18
|
-
},
|
|
19
|
-
validationError: () => {
|
|
20
|
-
// valid JSON but `name` is a number, not a string — validation should fail
|
|
21
|
-
const result = validatePackageJsonText('{"name": 42}')
|
|
22
|
-
assert(result[0] === 'error', result)
|
|
23
|
-
},
|
|
24
|
-
validatePreservesOriginalObject: () => {
|
|
25
|
-
const object = /** @type {const} */ ({ name: 'x', version: '1.0.0', private: true })
|
|
26
|
-
const metadata = unwrap(validatePackageJson(object))
|
|
27
|
-
assertEq(metadata.name, 'x', metadata)
|
|
28
|
-
assertEq(metadata.version, '1.0.0', metadata)
|
|
29
|
-
assert(Object.is(metadata, object), metadata)
|
|
30
|
-
assertEq(object.private, true, object)
|
|
31
|
-
},
|
|
32
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A fluent, method-chaining wrapper over the raw `Effect`.
|
|
3
|
-
*
|
|
4
|
-
* See `./types.ts` for the `Eff` type-level API.
|
|
5
|
-
*
|
|
6
|
-
* @module
|
|
7
|
-
*
|
|
8
|
-
* @import { Effect, Operation } from '../types.ts'
|
|
9
|
-
* @import { Eff } from './types.ts'
|
|
10
|
-
*/
|
|
11
|
-
import type { Effect, Operation } from '../types.ts';
|
|
12
|
-
import type { Eff } from './types.ts';
|
|
13
|
-
/**
|
|
14
|
-
* Wraps a raw {@link Effect}; the bridge into the `Eff` world, with an empty
|
|
15
|
-
* history. The empty tuple is spelled out because {@link Eff} deliberately has
|
|
16
|
-
* no default for `P` — see its docs.
|
|
17
|
-
*
|
|
18
|
-
* @type {<O extends Operation, T>(value: Effect<O, T>) => Eff<O, T, readonly[]>}
|
|
19
|
-
*/
|
|
20
|
-
export declare const eff: <O extends Operation, T>(value: Effect<O, T>) => Eff<O, T, readonly []>;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A fluent, method-chaining wrapper over the raw `Effect`.
|
|
3
|
-
*
|
|
4
|
-
* See `./types.ts` for the `Eff` type-level API.
|
|
5
|
-
*
|
|
6
|
-
* @module
|
|
7
|
-
*
|
|
8
|
-
* @import { Effect, Operation } from '../types.ts'
|
|
9
|
-
* @import { Eff } from './types.ts'
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { history, historyStep, mapStep, pure } from '../module.f.mjs'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Builds an `Eff` from two views of the same chain: `value`, the effect for the
|
|
16
|
-
* current value alone, and `h`, a thunk for the `[current, ...history]` tuple.
|
|
17
|
-
*
|
|
18
|
-
* **The two must denote the same computation** — `value` has to be what `h()`
|
|
19
|
-
* produces with the history dropped. Nothing enforces it. The
|
|
20
|
-
* redundancy is deliberate: `value` used to be derived from `h` on demand,
|
|
21
|
-
* which made disagreement impossible but also forced the entry case to rebuild
|
|
22
|
-
* an effect it was already holding. Passing it in is what lets {@link eff} hand
|
|
23
|
-
* the original back.
|
|
24
|
-
*
|
|
25
|
-
* The asymmetry between the two — one built, one deferred — is the point.
|
|
26
|
-
* `value` is either already in hand ({@link eff} was given it) or already built
|
|
27
|
-
* (`.step` has just composed the chain it projects from), so storing it costs
|
|
28
|
-
* no more than the projection itself. `h` is different: nothing needs the
|
|
29
|
-
* history tuple until a later `.step` asks for it, and composing effects is
|
|
30
|
-
* eager, so holding a thunk is the only way to not compose it yet. That keeps
|
|
31
|
-
* `eff(e)` free of work entirely.
|
|
32
|
-
*
|
|
33
|
-
* `.step` calls `h()` once and closes over the effect, so everything built
|
|
34
|
-
* from that link shares it. `eff`'s thunk is not memoized, so calling `.step`
|
|
35
|
-
* twice on the same `eff(e)` rebuilds and re-forces `e` — harmless under
|
|
36
|
-
* `Pure`'s contract, which requires the thunk to be pure and to tolerate
|
|
37
|
-
* repeat calls.
|
|
38
|
-
*
|
|
39
|
-
* @template {Operation} O
|
|
40
|
-
* @template T
|
|
41
|
-
* @template {readonly unknown[]} P
|
|
42
|
-
* @param {Effect<O, T>} value
|
|
43
|
-
* @param {() => Effect<O, readonly[T, ...P]>} h
|
|
44
|
-
* @returns {Eff<O, T, P>}
|
|
45
|
-
*/
|
|
46
|
-
const create = (value, h) => {
|
|
47
|
-
// `self` is named so `.map` can be *defined* as the `.step` call it is
|
|
48
|
-
// documented to equal, rather than as a second copy of `.step`'s body that
|
|
49
|
-
// has to be re-checked against it.
|
|
50
|
-
/** @type {Eff<O, T, P>} */
|
|
51
|
-
const self = {
|
|
52
|
-
value,
|
|
53
|
-
step: f => {
|
|
54
|
-
const x1 = historyStep(h(), f)
|
|
55
|
-
return create(mapStep(x1, ([t]) => t), () => x1)
|
|
56
|
-
},
|
|
57
|
-
map: f => self.step((...tp) => pure(f(...tp)))
|
|
58
|
-
}
|
|
59
|
-
return self
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Wraps a raw {@link Effect}; the bridge into the `Eff` world, with an empty
|
|
64
|
-
* history. The empty tuple is spelled out because {@link Eff} deliberately has
|
|
65
|
-
* no default for `P` — see its docs.
|
|
66
|
-
*
|
|
67
|
-
* @type {<O extends Operation, T>(value: Effect<O, T>) => Eff<O, T, readonly[]>}
|
|
68
|
-
*/
|
|
69
|
-
export const eff = value =>
|
|
70
|
-
create(value, () => history(value))
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import { Effect, OperationMap } from '../types.ts'
|
|
3
|
-
*/
|
|
4
|
-
export type _AddOp = readonly ['add', (a: number, b: number) => number];
|
|
5
|
-
export declare const proof: {
|
|
6
|
-
value: () => void;
|
|
7
|
-
pure: () => void;
|
|
8
|
-
chain: () => void;
|
|
9
|
-
overDo: () => void;
|
|
10
|
-
map: {
|
|
11
|
-
chain: () => void;
|
|
12
|
-
growsHistory: () => void;
|
|
13
|
-
overDo: () => void;
|
|
14
|
-
};
|
|
15
|
-
};
|