functionalscript 0.37.0 → 0.39.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 +1 -1
- package/{fs → fjs}/asn.1/proof.f.js +32 -94
- package/fjs/asserts/module.f.d.ts +36 -0
- package/fjs/asserts/module.f.js +39 -0
- package/fjs/asserts/proof.f.d.ts +11 -0
- package/fjs/asserts/proof.f.js +18 -0
- package/{fs → fjs}/base_n/proof.f.js +12 -36
- package/{fs → fjs}/basen/base64/proof.f.d.ts +1 -0
- package/{fs → fjs}/basen/base64/proof.f.js +15 -1
- package/{fs → fjs}/basen/cbase32/proof.f.js +15 -42
- package/fjs/bnf/data/module.f.d.ts +52 -0
- package/{fs → fjs}/bnf/data/module.f.js +53 -3
- package/{fs → fjs}/bnf/data/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/data/proof.f.js +54 -19
- package/{fs → fjs}/bnf/descent/module.f.d.ts +4 -14
- package/fjs/bnf/descent/module.f.js +124 -0
- package/{fs → fjs}/bnf/descent/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/descent/proof.f.js +55 -24
- package/{fs → fjs}/bnf/ll1/module.f.d.ts +4 -4
- package/{fs → fjs}/bnf/ll1/module.f.js +7 -5
- package/{fs → fjs}/bnf/ll1/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/ll1/proof.f.js +27 -10
- package/{fs → fjs}/bnf/module.f.d.ts +19 -5
- package/{fs → fjs}/bnf/module.f.js +10 -11
- package/fjs/bnf/proof.f.js +69 -0
- package/{fs → fjs}/bnf/testlib.f.js +2 -2
- package/fjs/bnf/token_symbol/module.f.d.ts +38 -0
- package/fjs/bnf/token_symbol/module.f.js +48 -0
- package/fjs/bnf/token_symbol/proof.f.d.ts +10 -0
- package/fjs/bnf/token_symbol/proof.f.js +37 -0
- package/{fs → fjs}/cas/cli/module.f.js +6 -9
- package/{fs → fjs}/cas/cli/proof.f.d.ts +4 -1
- package/{fs → fjs}/cas/cli/proof.f.js +29 -66
- package/fjs/cas/evo/mcp/module.f.d.ts +27 -0
- package/fjs/cas/evo/mcp/module.f.js +94 -0
- package/fjs/cas/evo/mcp/proof.f.d.ts +11 -0
- package/fjs/cas/evo/mcp/proof.f.js +126 -0
- package/fjs/cas/evo/module.f.d.ts +202 -0
- package/fjs/cas/evo/module.f.js +421 -0
- package/fjs/cas/evo/proof.f.d.ts +39 -0
- package/fjs/cas/evo/proof.f.js +572 -0
- package/fjs/cas/mcp/module.f.d.ts +49 -0
- package/{fs → fjs}/cas/mcp/module.f.js +61 -81
- package/{fs → fjs}/cas/mcp/proof.f.d.ts +4 -1
- package/{fs → fjs}/cas/mcp/proof.f.js +45 -17
- package/{fs → fjs}/cas/module.f.d.ts +10 -0
- package/{fs → fjs}/cas/module.f.js +89 -36
- package/fjs/cas/proof.f.d.ts +18 -0
- package/fjs/cas/proof.f.js +305 -0
- package/{fs → fjs}/ci/bun/module.f.js +3 -3
- package/{fs → fjs}/ci/common/module.f.d.ts +1 -2
- package/{fs → fjs}/ci/common/module.f.js +1 -5
- package/{fs → fjs}/ci/config/module.f.d.ts +8 -8
- package/{fs → fjs}/ci/config/module.f.js +8 -8
- package/{fs → fjs}/ci/deno/module.f.js +3 -3
- package/{fs → fjs}/ci/module.f.js +3 -4
- package/{fs → fjs}/ci/node/module.f.js +11 -9
- package/{fs → fjs}/ci/proof.f.js +16 -9
- package/{fs → fjs}/ci/rust/module.f.js +9 -1
- package/{fs → fjs}/cli/module.f.js +2 -2
- package/{fs → fjs}/cli/proof.f.js +22 -63
- package/{fs → fjs}/common/monoid/module.f.d.ts +46 -2
- package/fjs/common/monoid/module.f.js +88 -0
- package/fjs/common/monoid/proof.f.d.ts +9 -0
- package/fjs/common/monoid/proof.f.js +48 -0
- package/{fs → fjs}/crypto/hmac/proof.f.js +4 -12
- package/fjs/crypto/pow/proof.f.js +111 -0
- package/{fs → fjs}/crypto/secp/proof.f.js +12 -33
- package/{fs → fjs}/crypto/sha2/proof.f.js +18 -49
- package/{fs → fjs}/crypto/sign/module.f.d.ts +0 -5
- package/{fs → fjs}/crypto/sign/module.f.js +7 -4
- package/{fs → fjs}/crypto/sign/proof.f.js +36 -105
- package/{fs → fjs}/crypto/vdf/proof.f.js +22 -63
- package/{fs → fjs}/dev/module.f.js +25 -25
- package/{fs → fjs}/dev/package_json/proof.f.js +7 -7
- package/{fs → fjs}/dev/proof.f.js +2 -4
- package/{fs → fjs}/djs/ast/proof.f.js +4 -12
- package/{fs → fjs}/djs/module.f.js +5 -8
- package/{fs → fjs}/djs/parser/module.f.d.ts +8 -0
- package/{fs → fjs}/djs/parser/module.f.js +37 -0
- package/{fs → fjs}/djs/parser/proof.f.js +138 -400
- package/{fs → fjs}/djs/proof.f.js +13 -36
- package/{fs → fjs}/djs/serializer/proof.f.js +14 -39
- package/fjs/djs/tokenizer/module.f.d.ts +24 -0
- package/fjs/djs/tokenizer/module.f.js +472 -0
- package/{fs/djs/tokenizer-new → fjs/djs/tokenizer}/proof.f.d.ts +4 -3
- package/{fs/djs/tokenizer-new → fjs/djs/tokenizer}/proof.f.js +446 -445
- package/{fs → fjs}/djs/transpiler/module.f.js +6 -6
- package/{fs → fjs}/djs/transpiler/proof.f.d.ts +3 -0
- package/{fs → fjs}/djs/transpiler/proof.f.js +29 -30
- package/fjs/effects/eff/module.f.d.ts +72 -0
- package/fjs/effects/eff/module.f.js +46 -0
- package/fjs/effects/eff/proof.f.d.ts +11 -0
- package/fjs/effects/eff/proof.f.js +58 -0
- package/{fs → fjs}/effects/list/module.f.d.ts +11 -5
- package/{fs → fjs}/effects/list/module.f.js +2 -1
- package/{fs → fjs}/effects/memory/proof.f.js +15 -29
- package/fjs/effects/module.f.d.ts +388 -0
- package/fjs/effects/module.f.js +288 -0
- package/{fs → fjs}/effects/node/memory/proof.js +7 -13
- package/{fs → fjs}/effects/node/module.d.ts +1 -1
- package/{fs → fjs}/effects/node/module.f.d.ts +2 -2
- package/{fs → fjs}/effects/node/module.f.js +9 -11
- package/{fs → fjs}/effects/node/module.js +3 -3
- package/{fs → fjs}/effects/node/proof.f.d.ts +1 -0
- package/{fs → fjs}/effects/node/proof.f.js +121 -299
- package/{fs → fjs}/effects/node/virtual/proof.f.d.ts +1 -0
- package/{fs → fjs}/effects/node/virtual/proof.f.js +36 -29
- package/fjs/effects/proof.f.d.ts +51 -0
- package/fjs/effects/proof.f.js +178 -0
- package/{fs → fjs}/emergent_testing/module.f.js +55 -39
- package/{fs → fjs}/emergent_testing/proof.f.d.ts +4 -0
- package/{fs → fjs}/emergent_testing/proof.f.js +60 -27
- package/{fs → fjs}/fsc/proof.f.js +12 -34
- package/{fs → fjs}/fsm/proof.f.js +5 -12
- package/{fs → fjs}/mcp/module.f.d.ts +7 -0
- package/{fs → fjs}/mcp/module.f.js +17 -10
- package/{fs → fjs}/mcp/proof.f.js +17 -16
- package/{fs → fjs}/mcp/stdio/module.f.d.ts +4 -4
- package/{fs → fjs}/mcp/stdio/module.f.js +14 -14
- package/{fs → fjs}/media/html/proof.f.js +12 -33
- package/{fs → fjs}/media/json/parser/module.f.d.ts +5 -0
- package/{fs → fjs}/media/json/parser/module.f.js +14 -0
- package/{fs → fjs}/media/json/parser/proof.f.js +39 -114
- package/{fs → fjs}/media/json/rpc/module.f.js +1 -1
- package/{fs → fjs}/media/json/schema/module.f.d.ts +2 -2
- package/{fs → fjs}/media/json/schema/module.f.js +23 -39
- package/{fs → fjs}/media/json/schema/proof.f.js +3 -6
- package/{fs → fjs}/media/json/serializer/proof.f.js +10 -27
- package/{fs → fjs}/media/module.f.d.ts +6 -6
- package/{fs → fjs}/media/module.f.js +3 -4
- package/{fs → fjs}/media/proof.f.js +5 -4
- package/{fs → fjs}/media/revision/module.f.d.ts +31 -4
- package/{fs → fjs}/media/revision/module.f.js +35 -23
- package/{fs → fjs}/media/revision/proof.f.d.ts +10 -8
- package/fjs/media/revision/proof.f.js +140 -0
- package/{fs → fjs}/media/type/module.f.js +2 -2
- package/{fs → fjs}/media/type/proof.f.js +8 -15
- package/{fs → fjs}/module.f.js +5 -9
- package/{fs → fjs}/path/proof.f.js +27 -78
- package/{fs → fjs}/proof.f.js +2 -0
- package/{fs → fjs}/sul/id/proof.f.js +7 -21
- package/{fs → fjs}/sul/level/hash/proof.f.js +5 -5
- package/{fs → fjs}/sul/level/literal/proof.f.js +12 -26
- package/fjs/text/ascii/proof.f.d.ts +6 -0
- package/{fs → fjs}/text/ascii/proof.f.js +4 -14
- package/{fs → fjs}/text/code_point/module.f.js +10 -10
- package/{fs → fjs}/text/proof.f.js +4 -9
- package/{fs → fjs}/text/sgr/proof.f.js +6 -15
- package/{fs → fjs}/text/utf16/module.f.js +1 -1
- package/{fs → fjs}/text/utf16/proof.f.js +23 -66
- package/{fs → fjs}/text/utf8/proof.f.js +56 -125
- package/{fs → fjs}/types/array/proof.f.js +18 -52
- package/fjs/types/bigfloat/proof.f.js +217 -0
- package/{fs → fjs}/types/bigint/module.f.js +4 -3
- package/{fs → fjs}/types/bigint/proof.f.js +49 -145
- package/{fs → fjs}/types/bit_vec/module.f.js +5 -15
- package/{fs → fjs}/types/bit_vec/proof.f.js +72 -214
- package/{fs → fjs}/types/btree/find/proof.f.js +23 -66
- package/{fs → fjs}/types/btree/proof.f.js +5 -12
- package/{fs → fjs}/types/btree/remove/module.f.d.ts +5 -0
- package/{fs → fjs}/types/btree/remove/module.f.js +12 -0
- package/{fs → fjs}/types/btree/remove/proof.f.d.ts +2 -0
- package/{fs → fjs}/types/btree/remove/proof.f.js +83 -230
- package/{fs → fjs}/types/btree/set/module.f.js +5 -2
- package/{fs → fjs}/types/btree/set/proof.f.js +35 -24
- package/{fs → fjs}/types/byte_set/proof.f.js +22 -63
- package/{fs → fjs}/types/function/compare/proof.f.js +13 -36
- package/{fs → fjs}/types/function/operator/proof.f.js +17 -48
- package/{fs → fjs}/types/function/proof.f.js +2 -3
- package/{fs → fjs}/types/list/module.f.d.ts +21 -0
- package/{fs → fjs}/types/list/module.f.js +17 -0
- package/{fs → fjs}/types/list/proof.f.d.ts +1 -0
- package/{fs → fjs}/types/list/proof.f.js +79 -164
- package/{fs → fjs}/types/map/proof.f.js +4 -12
- package/{fs → fjs}/types/nibble_set/proof.f.js +16 -45
- package/{fs → fjs}/types/nominal/proof.f.js +5 -10
- package/fjs/types/nullable/proof.f.js +29 -0
- package/{fs → fjs}/types/number/module.f.js +2 -1
- package/{fs → fjs}/types/number/proof.f.js +9 -24
- package/{fs → fjs}/types/object/proof.f.js +3 -6
- package/{fs → fjs}/types/patricia_trie/proof.f.js +21 -21
- package/{fs → fjs}/types/prime_field/module.f.js +2 -7
- package/{fs → fjs}/types/range/module.f.d.ts +1 -1
- package/fjs/types/range/module.f.js +2 -0
- package/fjs/types/range/proof.f.js +9 -0
- package/{fs → fjs}/types/range_map/proof.f.js +28 -81
- package/{fs → fjs}/types/result/proof.f.d.ts +3 -2
- package/fjs/types/result/proof.f.js +31 -0
- package/{fs → fjs}/types/rtti/common/module.f.d.ts +36 -1
- package/{fs → fjs}/types/rtti/common/module.f.js +44 -0
- package/fjs/types/rtti/common/proof.f.d.ts +8 -0
- package/fjs/types/rtti/common/proof.f.js +51 -0
- package/{fs → fjs}/types/rtti/parse/module.f.js +13 -22
- package/{fs → fjs}/types/rtti/parse/proof.f.js +7 -18
- package/{fs → fjs}/types/rtti/ts/module.f.d.ts +10 -4
- package/{fs → fjs}/types/rtti/validate/module.f.js +8 -29
- package/{fs → fjs}/types/rtti/validate/proof.f.js +4 -9
- package/{fs → fjs}/types/sorted_list/proof.f.js +8 -21
- package/{fs → fjs}/types/sorted_set/proof.f.js +14 -39
- package/{fs → fjs}/types/string/module.f.js +10 -2
- package/fjs/types/string/proof.f.js +77 -0
- package/fjs/types/string_set/proof.f.js +43 -0
- package/{fs → fjs}/types/ts/proof.f.js +15 -42
- package/{fs → fjs}/types/uint8array/module.f.js +7 -7
- package/{fs → fjs}/types/uint8array/proof.f.d.ts +4 -1
- package/{fs → fjs}/types/uint8array/proof.f.js +7 -7
- package/{fs → fjs}/website/module.f.js +2 -3
- package/{fs → fjs}/website/proof.f.js +3 -6
- package/package.json +8 -8
- package/fs/asserts/module.f.d.ts +0 -4
- package/fs/asserts/module.f.js +0 -9
- package/fs/asserts/proof.f.d.ts +0 -8
- package/fs/asserts/proof.f.js +0 -51
- package/fs/bnf/data/module.f.d.ts +0 -30
- package/fs/bnf/descent/module.f.js +0 -119
- package/fs/bnf/proof.f.js +0 -104
- package/fs/cas/mcp/module.f.d.ts +0 -36
- package/fs/cas/proof.f.d.ts +0 -20
- package/fs/cas/proof.f.js +0 -294
- package/fs/common/monoid/module.f.js +0 -44
- package/fs/common/monoid/proof.f.d.ts +0 -4
- package/fs/common/monoid/proof.f.js +0 -27
- package/fs/crypto/pow/proof.f.js +0 -161
- package/fs/djs/tokenizer/module.f.d.ts +0 -12
- package/fs/djs/tokenizer/module.f.js +0 -62
- package/fs/djs/tokenizer/proof.f.d.ts +0 -7
- package/fs/djs/tokenizer/proof.f.js +0 -543
- package/fs/djs/tokenizer-new/module.f.d.ts +0 -3
- package/fs/djs/tokenizer-new/module.f.js +0 -155
- package/fs/effects/module.f.d.ts +0 -106
- package/fs/effects/module.f.js +0 -80
- package/fs/effects/proof.f.d.ts +0 -25
- package/fs/effects/proof.f.js +0 -115
- package/fs/media/revision/proof.f.js +0 -119
- package/fs/text/ascii/proof.f.d.ts +0 -4
- package/fs/types/bigfloat/proof.f.js +0 -348
- package/fs/types/nullable/proof.f.js +0 -50
- package/fs/types/range/module.f.js +0 -2
- package/fs/types/range/proof.f.js +0 -18
- package/fs/types/result/proof.f.js +0 -52
- package/fs/types/string/proof.f.js +0 -118
- package/fs/types/string_set/proof.f.js +0 -82
- /package/{fs → fjs}/asn.1/module.f.d.ts +0 -0
- /package/{fs → fjs}/asn.1/module.f.js +0 -0
- /package/{fs → fjs}/asn.1/proof.f.d.ts +0 -0
- /package/{fs → fjs}/base_n/module.f.d.ts +0 -0
- /package/{fs → fjs}/base_n/module.f.js +0 -0
- /package/{fs → fjs}/base_n/proof.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/module.f.js +0 -0
- /package/{fs → fjs}/basen/base128/proof.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/proof.f.js +0 -0
- /package/{fs → fjs}/basen/base64/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base64/module.f.js +0 -0
- /package/{fs → fjs}/basen/cbase32/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/cbase32/module.f.js +0 -0
- /package/{fs → fjs}/basen/cbase32/proof.f.d.ts +0 -0
- /package/{fs → fjs}/bnf/proof.f.d.ts +0 -0
- /package/{fs → fjs}/bnf/testlib.f.d.ts +0 -0
- /package/{fs → fjs}/cas/cli/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/bun/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/deno/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/node/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/playwright/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/playwright/module.f.js +0 -0
- /package/{fs → fjs}/ci/proof.f.d.ts +0 -0
- /package/{fs → fjs}/ci/rust/module.f.d.ts +0 -0
- /package/{fs → fjs}/cli/module.f.d.ts +0 -0
- /package/{fs → fjs}/cli/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/hmac/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/hmac/module.f.js +0 -0
- /package/{fs → fjs}/crypto/hmac/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/pow/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/pow/module.f.js +0 -0
- /package/{fs → fjs}/crypto/pow/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/secp/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/secp/module.f.js +0 -0
- /package/{fs → fjs}/crypto/secp/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sha2/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sha2/module.f.js +0 -0
- /package/{fs → fjs}/crypto/sha2/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sign/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/vdf/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/vdf/module.f.js +0 -0
- /package/{fs → fjs}/crypto/vdf/proof.f.d.ts +0 -0
- /package/{fs → fjs}/dev/module.f.d.ts +0 -0
- /package/{fs → fjs}/dev/package_json/module.f.d.ts +0 -0
- /package/{fs → fjs}/dev/package_json/module.f.js +0 -0
- /package/{fs → fjs}/dev/package_json/proof.f.d.ts +0 -0
- /package/{fs → fjs}/dev/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/ast/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/ast/module.f.js +0 -0
- /package/{fs → fjs}/djs/ast/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/input.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/input.f.js +0 -0
- /package/{fs → fjs}/djs/examples/m.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/m.f.js +0 -0
- /package/{fs → fjs}/djs/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/parser/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/serializer/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/serializer/module.f.js +0 -0
- /package/{fs → fjs}/djs/serializer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/transpiler/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/memory/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/memory/module.f.js +0 -0
- /package/{fs → fjs}/effects/memory/proof.f.d.ts +0 -0
- /package/{fs → fjs}/effects/mock/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/mock/module.f.js +0 -0
- /package/{fs → fjs}/effects/module.d.ts +0 -0
- /package/{fs → fjs}/effects/module.js +0 -0
- /package/{fs → fjs}/effects/node/memory/module.d.ts +0 -0
- /package/{fs → fjs}/effects/node/memory/module.js +0 -0
- /package/{fs → fjs}/effects/node/memory/proof.d.ts +0 -0
- /package/{fs → fjs}/effects/node/virtual/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/node/virtual/module.f.js +0 -0
- /package/{fs → fjs}/emergent_testing/all.test.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/all.test.js +0 -0
- /package/{fs → fjs}/emergent_testing/example.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/example.f.js +0 -0
- /package/{fs → fjs}/emergent_testing/module.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/all.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/all.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/fail.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/fail.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/return-value.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/return-value.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable2.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable2.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/throw.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/throw.pass.js +0 -0
- /package/{fs → fjs}/fsc/bnf.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/bnf.f.js +0 -0
- /package/{fs → fjs}/fsc/json.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/json.f.js +0 -0
- /package/{fs → fjs}/fsc/module.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/module.f.js +0 -0
- /package/{fs → fjs}/fsc/proof.f.d.ts +0 -0
- /package/{fs → fjs}/fsm/module.f.d.ts +0 -0
- /package/{fs → fjs}/fsm/module.f.js +0 -0
- /package/{fs → fjs}/fsm/proof.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/module.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/module.f.js +0 -0
- /package/{fs → fjs}/js/tokenizer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/proof.f.js +0 -0
- /package/{fs → fjs}/mcp/proof.f.d.ts +0 -0
- /package/{fs → fjs}/mcp/stdio/proof.f.d.ts +0 -0
- /package/{fs → fjs}/mcp/stdio/proof.f.js +0 -0
- /package/{fs → fjs}/media/html/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/html/module.f.js +0 -0
- /package/{fs → fjs}/media/html/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/module.f.js +0 -0
- /package/{fs → fjs}/media/json/parser/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/proof.f.js +0 -0
- /package/{fs → fjs}/media/json/rpc/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/rpc/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/rpc/proof.f.js +0 -0
- /package/{fs → fjs}/media/json/schema/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/serializer/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/serializer/module.f.js +0 -0
- /package/{fs → fjs}/media/json/serializer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/module.f.js +0 -0
- /package/{fs → fjs}/media/json/tokenizer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/proof.f.js +0 -0
- /package/{fs → fjs}/media/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/type/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/type/proof.f.d.ts +0 -0
- /package/{fs → fjs}/module.d.ts +0 -0
- /package/{fs → fjs}/module.f.d.ts +0 -0
- /package/{fs → fjs}/module.js +0 -0
- /package/{fs → fjs}/path/module.f.d.ts +0 -0
- /package/{fs → fjs}/path/module.f.js +0 -0
- /package/{fs → fjs}/path/proof.f.d.ts +0 -0
- /package/{fs → fjs}/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/id/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/id/module.f.js +0 -0
- /package/{fs → fjs}/sul/id/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/hash/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/hash/module.f.js +0 -0
- /package/{fs → fjs}/sul/level/hash/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/literal/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/literal/module.f.js +0 -0
- /package/{fs → fjs}/sul/level/literal/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/module.f.js +0 -0
- /package/{fs → fjs}/sul/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/proof.f.js +0 -0
- /package/{fs → fjs}/text/ascii/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/ascii/module.f.js +0 -0
- /package/{fs → fjs}/text/code_point/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/code_point/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/code_point/proof.f.js +0 -0
- /package/{fs → fjs}/text/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/module.f.js +0 -0
- /package/{fs → fjs}/text/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/sgr/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/sgr/module.f.js +0 -0
- /package/{fs → fjs}/text/sgr/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf16/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf16/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf8/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf8/module.f.js +0 -0
- /package/{fs → fjs}/text/utf8/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/array/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/array/module.f.js +0 -0
- /package/{fs → fjs}/types/array/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigfloat/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigfloat/module.f.js +0 -0
- /package/{fs → fjs}/types/bigfloat/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigint/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigint/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bit_vec/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bit_vec/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/find/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/find/module.f.js +0 -0
- /package/{fs → fjs}/types/btree/find/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/module.f.js +0 -0
- /package/{fs → fjs}/types/btree/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/types/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/types/module.f.js +0 -0
- /package/{fs → fjs}/types/byte_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/byte_set/module.f.js +0 -0
- /package/{fs → fjs}/types/byte_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/compare/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/compare/module.f.js +0 -0
- /package/{fs → fjs}/types/function/compare/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/module.f.js +0 -0
- /package/{fs → fjs}/types/function/operator/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/operator/module.f.js +0 -0
- /package/{fs → fjs}/types/function/operator/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/map/module.f.js +0 -0
- /package/{fs → fjs}/types/map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nibble_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nibble_set/module.f.js +0 -0
- /package/{fs → fjs}/types/nibble_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nominal/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nominal/module.f.js +0 -0
- /package/{fs → fjs}/types/nominal/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nullable/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nullable/module.f.js +0 -0
- /package/{fs → fjs}/types/nullable/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/number/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/number/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/object/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/object/module.f.js +0 -0
- /package/{fs → fjs}/types/object/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/option/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/option/module.f.js +0 -0
- /package/{fs → fjs}/types/ordered_map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/ordered_map/module.f.js +0 -0
- /package/{fs → fjs}/types/ordered_map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/ordered_map/proof.f.js +0 -0
- /package/{fs → fjs}/types/patricia_trie/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/patricia_trie/module.f.js +0 -0
- /package/{fs → fjs}/types/patricia_trie/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/phantom/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/phantom/module.f.js +0 -0
- /package/{fs → fjs}/types/prime_field/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/prime_field/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/prime_field/proof.f.js +0 -0
- /package/{fs → fjs}/types/range/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/range_map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/range_map/module.f.js +0 -0
- /package/{fs → fjs}/types/range_map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.f.js +0 -0
- /package/{fs → fjs}/types/result/module.js +0 -0
- /package/{fs → fjs}/types/rtti/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/module.f.js +0 -0
- /package/{fs → fjs}/types/rtti/parse/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/parse/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/proof.f.js +0 -0
- /package/{fs → fjs}/types/rtti/ts/module.f.js +0 -0
- /package/{fs → fjs}/types/rtti/ts/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/ts/proof.f.js +0 -0
- /package/{fs → fjs}/types/rtti/validate/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/validate/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_list/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_list/module.f.js +0 -0
- /package/{fs → fjs}/types/sorted_list/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_set/module.f.js +0 -0
- /package/{fs → fjs}/types/sorted_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/string/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/string/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/string_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/string_set/module.f.js +0 -0
- /package/{fs → fjs}/types/string_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/ts/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/ts/module.f.js +0 -0
- /package/{fs → fjs}/types/ts/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/uint8array/module.f.d.ts +0 -0
- /package/{fs → fjs}/website/module.f.d.ts +0 -0
- /package/{fs → fjs}/website/proof.f.d.ts +0 -0
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { sha256 } from '../crypto/sha2/module.f.js';
|
|
7
7
|
import { join, normalize, parse } from '../path/module.f.js';
|
|
8
|
-
import { empty, length, maxLengthBytes, msb, vec } from '../types/bit_vec/module.f.js';
|
|
8
|
+
import { empty, length, maxLength, maxLengthBytes, msb, vec } from '../types/bit_vec/module.f.js';
|
|
9
9
|
import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.js';
|
|
10
|
-
import { foldStep, forEachStep, okStep, pure } from '../effects/module.f.js';
|
|
10
|
+
import { foldStep, forEachStep, history, historyStep, okStep, pure, step } from '../effects/module.f.js';
|
|
11
|
+
import { eff } from '../effects/eff/module.f.js';
|
|
11
12
|
import { access, createExclusive, isNotFound, mkdir, now, randomInt, readBytes, readdir, rename, rm, stat, writeBytes, } from '../effects/node/module.f.js';
|
|
12
13
|
import { toOption } from '../types/nullable/module.f.js';
|
|
13
14
|
import { error, ok, unwrap } from '../types/result/module.f.js';
|
|
@@ -22,6 +23,34 @@ export const toPath = (key) => {
|
|
|
22
23
|
const [b, c] = split2(bc);
|
|
23
24
|
return join(prefix, a, b, c);
|
|
24
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Drains a `Cas<O>.read` chunk stream into a single `Vec`. Used by any caller
|
|
28
|
+
* that needs the whole blob at once (an MCP `content: true` fetch, an Evo
|
|
29
|
+
* revision decode): the chunk stream is concatenated and an error item is
|
|
30
|
+
* surfaced as the result. A single `Vec` cannot exceed `maxLength` bits;
|
|
31
|
+
* concatenating past it would overflow the runtime's `bigint` constraint, so
|
|
32
|
+
* that case is surfaced as an error item too, rather than crashing the
|
|
33
|
+
* process.
|
|
34
|
+
*/
|
|
35
|
+
export const collectRead = (stream) => {
|
|
36
|
+
const loop = (acc) => (s) => eff(s)
|
|
37
|
+
.step((node) => {
|
|
38
|
+
if (node === undefined) {
|
|
39
|
+
return pure(ok(acc));
|
|
40
|
+
}
|
|
41
|
+
const { first, tail } = node;
|
|
42
|
+
const [t, v] = first;
|
|
43
|
+
if (t === 'error') {
|
|
44
|
+
return pure(first);
|
|
45
|
+
}
|
|
46
|
+
if (length(acc) + length(v) > maxLength) {
|
|
47
|
+
return pure(error(`cas blob exceeds maximum vector length of ${maxLength} bits`));
|
|
48
|
+
}
|
|
49
|
+
return loop(msb.concat(acc)(v))(tail);
|
|
50
|
+
})
|
|
51
|
+
.value;
|
|
52
|
+
return loop(empty)(stream);
|
|
53
|
+
};
|
|
25
54
|
/** Maximum chunk size for streaming reads: the largest `Vec` the runtime allows. */
|
|
26
55
|
const chunkBytes = Number(maxLengthBytes);
|
|
27
56
|
/** Staging directory under the store root; GC and every uploader share it. */
|
|
@@ -49,13 +78,18 @@ const deadlineOf = (name) => Number(name.slice(0, name.indexOf('-')));
|
|
|
49
78
|
* still-live lease is left alone; the fencing rename keeps even a misjudged
|
|
50
79
|
* reclaim fail-safe (worst case: that upload restarts).
|
|
51
80
|
*/
|
|
52
|
-
const gcStage = (stageDir) => now()
|
|
81
|
+
const gcStage = (stageDir) => eff(now())
|
|
82
|
+
.step(() => readdir(stageDir, {}))
|
|
83
|
+
.step(([k, v], t) => {
|
|
53
84
|
if (k === 'error') {
|
|
54
85
|
return pure(undefined);
|
|
55
86
|
}
|
|
56
87
|
const expired = v.flatMap(d => d.isFile && deadlineOf(d.name) < t ? [d.name] : []);
|
|
57
|
-
return forEachStep((
|
|
58
|
-
|
|
88
|
+
return forEachStep(pure(expired), name => eff(rm(join(stageDir, name)))
|
|
89
|
+
.step(() => pure(undefined))
|
|
90
|
+
.value);
|
|
91
|
+
})
|
|
92
|
+
.value;
|
|
59
93
|
/**
|
|
60
94
|
* Builds a content-addressable storage facade from a SHA-2 implementation.
|
|
61
95
|
*/
|
|
@@ -66,7 +100,7 @@ export const fileCas = (sha2) => (path) => {
|
|
|
66
100
|
return {
|
|
67
101
|
read: (hash) => {
|
|
68
102
|
const p = join(path, toPath(hash));
|
|
69
|
-
const loop = (offset) => readBytes(p, offset, chunkBytes)
|
|
103
|
+
const loop = (offset) => eff(readBytes(p, offset, chunkBytes))
|
|
70
104
|
.step((result) => {
|
|
71
105
|
const [t, v] = result;
|
|
72
106
|
// A missing shard or read error is an explicit error item, never EOF.
|
|
@@ -78,7 +112,8 @@ export const fileCas = (sha2) => (path) => {
|
|
|
78
112
|
return length(v) === 0n
|
|
79
113
|
? elEmpty()
|
|
80
114
|
: nonEmpty(ok(v), loop(offset + chunkBytes));
|
|
81
|
-
})
|
|
115
|
+
})
|
|
116
|
+
.value;
|
|
82
117
|
return loop(0);
|
|
83
118
|
},
|
|
84
119
|
// Lock-free staging upload (issues/cas/staging-lease.md): stream each chunk straight
|
|
@@ -99,17 +134,20 @@ export const fileCas = (sha2) => (path) => {
|
|
|
99
134
|
const rel = toPath(hash);
|
|
100
135
|
const dst = join(path, rel);
|
|
101
136
|
const dstDir = join(path, ...parse(rel).slice(0, -1));
|
|
102
|
-
return mkdir(dstDir, { recursive: true })
|
|
137
|
+
return eff(mkdir(dstDir, { recursive: true }))
|
|
103
138
|
.step(() => rename(curPath, dst))
|
|
104
139
|
.step(() => rm(curPath))
|
|
105
140
|
.step(() => stat(dst))
|
|
106
|
-
.step(st => pure(st[0] === 'ok' && st[1].size === offset ? ok(hash) : error('publish size mismatch')))
|
|
141
|
+
.step(st => pure(st[0] === 'ok' && st[1].size === offset ? ok(hash) : error('publish size mismatch')))
|
|
142
|
+
.value;
|
|
107
143
|
};
|
|
108
144
|
// Any streaming error fails closed: delete the partial file, return the error.
|
|
109
|
-
const fail = (curPath, e) => rm(curPath)
|
|
110
|
-
|
|
145
|
+
const fail = (curPath, e) => eff(rm(curPath))
|
|
146
|
+
.step(() => pure(error(e)))
|
|
147
|
+
.value;
|
|
148
|
+
return eff(gcStage(stageDir)).step(() => eff(random256).step(rnd => {
|
|
111
149
|
const rndStr = vecToCBase32(rnd);
|
|
112
|
-
const loop = (state, offset, curPath) => (stream) => stream
|
|
150
|
+
const loop = (state, offset, curPath) => (stream) => eff(stream)
|
|
113
151
|
.step((node) => {
|
|
114
152
|
if (node === undefined) {
|
|
115
153
|
return publish(state, offset, curPath);
|
|
@@ -119,7 +157,7 @@ export const fileCas = (sha2) => (path) => {
|
|
|
119
157
|
return fail(curPath, first[1]);
|
|
120
158
|
}
|
|
121
159
|
const chunk = first[1];
|
|
122
|
-
return writeBytes(curPath, offset, chunk)
|
|
160
|
+
return eff(writeBytes(curPath, offset, chunk))
|
|
123
161
|
.step(wb => {
|
|
124
162
|
if (wb[0] === 'error') {
|
|
125
163
|
return fail(curPath, wb[1]);
|
|
@@ -127,49 +165,59 @@ export const fileCas = (sha2) => (path) => {
|
|
|
127
165
|
const newState = sha2.append(chunk)(state);
|
|
128
166
|
const newOffset = offset + Number(length(chunk) / 8n);
|
|
129
167
|
// Renew the lease: rename to a fresh deadline (keeps `delta` constant).
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
.
|
|
168
|
+
// The new path is still needed after the rename, to recurse with,
|
|
169
|
+
// so the rename captures it rather than closing over it.
|
|
170
|
+
const nextPath = step(now(), t => pure(join(stageDir, stageName(t + leaseDelta, rndStr))));
|
|
171
|
+
const renamed = historyStep(history(nextPath), next => rename(curPath, next));
|
|
172
|
+
return step(renamed, ([[rt, v], next]) => rt === 'error'
|
|
173
|
+
? fail(curPath, v)
|
|
174
|
+
: loop(newState, newOffset, next)(tail));
|
|
175
|
+
})
|
|
176
|
+
.value;
|
|
177
|
+
})
|
|
178
|
+
.value;
|
|
179
|
+
return eff(mkdir(stageDir, { recursive: true }))
|
|
180
|
+
.step(() => now())
|
|
141
181
|
.step(t0 => {
|
|
142
182
|
const path0 = join(stageDir, stageName(t0 + leaseDelta, rndStr));
|
|
143
|
-
return createExclusive(path0)
|
|
144
|
-
.step(okStep(() => loop(sha2.init, 0, path0)(payload)))
|
|
145
|
-
|
|
146
|
-
|
|
183
|
+
return eff(createExclusive(path0))
|
|
184
|
+
.step(okStep(() => loop(sha2.init, 0, path0)(payload)))
|
|
185
|
+
.value;
|
|
186
|
+
})
|
|
187
|
+
.value;
|
|
188
|
+
}).value).value;
|
|
147
189
|
},
|
|
148
190
|
list: () =>
|
|
149
191
|
// A fresh store has no `.cas` directory yet. Treat *only* that case as an
|
|
150
192
|
// empty store, mirroring how `read` maps a missing shard to an error item.
|
|
151
193
|
// A `.cas` that exists but cannot be read (permissions, corruption) is a
|
|
152
194
|
// genuine storage error and is surfaced, not masked as "no hashes".
|
|
153
|
-
access(storePrefix)
|
|
195
|
+
eff(access(storePrefix))
|
|
196
|
+
.step(a => {
|
|
154
197
|
if (a[0] === 'error') {
|
|
155
198
|
if (isNotFound(a[1])) {
|
|
156
199
|
return pure([]);
|
|
157
200
|
}
|
|
158
201
|
throw a[1];
|
|
159
202
|
}
|
|
160
|
-
return readdir(storePrefix, { recursive: true })
|
|
203
|
+
return eff(readdir(storePrefix, { recursive: true }))
|
|
161
204
|
.step(r => pure(unwrap(r).flatMap(({ name, parentPath, isFile }) => toOption(isFile
|
|
162
205
|
? cBase32ToVec(normalize(parentPath).substring(normalizedStorePrefix.length).replaceAll('/', '') + name)
|
|
163
|
-
: null))))
|
|
164
|
-
|
|
206
|
+
: null))))
|
|
207
|
+
.value;
|
|
208
|
+
})
|
|
209
|
+
.value,
|
|
165
210
|
url: (hash) => join(path, toPath(hash))
|
|
166
211
|
};
|
|
167
212
|
};
|
|
168
213
|
/** 256-bit random `Vec` built from 8 sequential `randomInt` (32-bit) calls. */
|
|
169
|
-
const random256 = foldStep(
|
|
214
|
+
const random256 = foldStep(pure([0, 1, 2, 3, 4, 5, 6, 7]), empty, () => (acc) => eff(randomInt())
|
|
215
|
+
.step(r => pure(msb.concat(acc)(vec(32n)(BigInt(r)))))
|
|
216
|
+
.value);
|
|
170
217
|
/** Streams any file at `filePath` in `<=128 KiB` chunks as a `ListEffect` of `ok` items. */
|
|
171
218
|
const streamFile = (filePath) => {
|
|
172
|
-
const loop = (offset) => readBytes(filePath, offset, chunkBytes)
|
|
219
|
+
const loop = (offset) => eff(readBytes(filePath, offset, chunkBytes))
|
|
220
|
+
.step((result) => {
|
|
173
221
|
if (result[0] === 'error') {
|
|
174
222
|
return nonEmpty(result, elEmpty());
|
|
175
223
|
}
|
|
@@ -177,7 +225,8 @@ const streamFile = (filePath) => {
|
|
|
177
225
|
return length(chunk) === 0n
|
|
178
226
|
? elEmpty()
|
|
179
227
|
: nonEmpty(ok(chunk), loop(offset + chunkBytes));
|
|
180
|
-
})
|
|
228
|
+
})
|
|
229
|
+
.value;
|
|
181
230
|
return loop(0);
|
|
182
231
|
};
|
|
183
232
|
/**
|
|
@@ -198,5 +247,9 @@ cas.write(streamFile(path));
|
|
|
198
247
|
export const casUpload = (home) => (fileName) => {
|
|
199
248
|
const src = join(home, 'cas_upload', fileName);
|
|
200
249
|
const c = fileCas(sha256)(home);
|
|
201
|
-
return casAddFile(c)(src)
|
|
250
|
+
return eff(casAddFile(c)(src))
|
|
251
|
+
.step(okStep(v => eff(rm(src))
|
|
252
|
+
.step(() => pure(ok(v)))
|
|
253
|
+
.value))
|
|
254
|
+
.value;
|
|
202
255
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const proof: {
|
|
2
|
+
addBigFile: () => void;
|
|
3
|
+
addAndGetBigFile: () => void;
|
|
4
|
+
casWriteRead: () => void;
|
|
5
|
+
casReadMissingShard: () => void;
|
|
6
|
+
casWriteMultiChunk: () => void;
|
|
7
|
+
casWriteDedup: () => void;
|
|
8
|
+
casWriteErrorItemAborts: () => void;
|
|
9
|
+
casWriteReadExceedsMaxLength: () => void;
|
|
10
|
+
casWriteGcReclaimsExpired: () => void;
|
|
11
|
+
casWriteGcSkipsLiveLease: () => void;
|
|
12
|
+
casUploadSuccess: () => void;
|
|
13
|
+
casUploadFailureKeepsSource: () => void;
|
|
14
|
+
collectReadDrainsChunks: () => void;
|
|
15
|
+
collectReadPropagatesErrorItem: () => void;
|
|
16
|
+
collectReadOverflow: () => void;
|
|
17
|
+
casListPropagatesNonNotFoundAccessError: () => void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { length, maxLength, msb, vec, vec8 } from '../types/bit_vec/module.f.js';
|
|
2
|
+
import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.js';
|
|
3
|
+
import { computeSync, sha256 } from '../crypto/sha2/module.f.js';
|
|
4
|
+
import { fileCas, casAddFile, collectRead, casUpload } from './module.f.js';
|
|
5
|
+
import { match, pure, runPure, step } from '../effects/module.f.js';
|
|
6
|
+
import { mkdir, writeFile, rm, readFile, access } from '../effects/node/module.f.js';
|
|
7
|
+
import { error, ok } from '../types/result/module.f.js';
|
|
8
|
+
import { emptyState, virtual } from '../effects/node/virtual/module.f.js';
|
|
9
|
+
import { join } from '../path/module.f.js';
|
|
10
|
+
import { nonEmpty, empty } from '../effects/list/module.f.js';
|
|
11
|
+
import { assert, assertEq, assertNotNullish } from '../asserts/module.f.js';
|
|
12
|
+
const testDir = './test-cas-cli';
|
|
13
|
+
// Names the command a `FileCasOperation` effect stops at, so a proof can assert
|
|
14
|
+
// on it and resume the continuation without reading the `Do` layout. The map
|
|
15
|
+
// has to list every operation the CAS can perform — that is what makes it total,
|
|
16
|
+
// and what makes a new operation a compile error here rather than a silent gap.
|
|
17
|
+
const casCommand = match({
|
|
18
|
+
access: () => 'access',
|
|
19
|
+
createExclusive: () => 'createExclusive',
|
|
20
|
+
mkdir: () => 'mkdir',
|
|
21
|
+
now: () => 'now',
|
|
22
|
+
randomInt: () => 'randomInt',
|
|
23
|
+
readBytes: () => 'readBytes',
|
|
24
|
+
readdir: () => 'readdir',
|
|
25
|
+
rename: () => 'rename',
|
|
26
|
+
rm: () => 'rm',
|
|
27
|
+
stat: () => 'stat',
|
|
28
|
+
writeBytes: () => 'writeBytes',
|
|
29
|
+
});
|
|
30
|
+
// Create a 128 KiB big file content (at the max Vec size limit)
|
|
31
|
+
// This tests the boundary where files are at the chunk size limit
|
|
32
|
+
const createBigFileContent = () => {
|
|
33
|
+
const byteCount = 128n * 1024n; // 128 KiB
|
|
34
|
+
// Create a repeating pattern: 0x42 repeated across the file
|
|
35
|
+
return vec(byteCount * 8n)(0x42424242n);
|
|
36
|
+
};
|
|
37
|
+
// Test adding a big file and verifying the hash
|
|
38
|
+
const testAddBigFile = () => {
|
|
39
|
+
const bigFilePath = `${testDir}/big-file.bin`;
|
|
40
|
+
const cas = fileCas(sha256)(testDir);
|
|
41
|
+
const x0 = step(mkdir(testDir, { recursive: true }), () => writeFile(bigFilePath, createBigFileContent()));
|
|
42
|
+
const x1 = step(x0, writeRes => {
|
|
43
|
+
assert(writeRes[0] === 'ok', ['failed to write test file', writeRes]);
|
|
44
|
+
return casAddFile(cas)(bigFilePath);
|
|
45
|
+
});
|
|
46
|
+
const x2 = step(x1, addRes => {
|
|
47
|
+
assert(addRes[0] === 'ok', ['failed to add file to CAS', addRes]);
|
|
48
|
+
const hash = addRes[1];
|
|
49
|
+
// Verify hash is 256 bits (SHA-256)
|
|
50
|
+
assertEq(length(hash), 256n, ['expected 256-bit hash', length(hash)]);
|
|
51
|
+
// Verify hash can be encoded/decoded
|
|
52
|
+
assertNotNullish(cBase32ToVec(vecToCBase32(hash)), 'failed to decode hash from cBase32');
|
|
53
|
+
return rm(testDir);
|
|
54
|
+
});
|
|
55
|
+
return step(x2, () => pure(undefined));
|
|
56
|
+
};
|
|
57
|
+
// Test adding and retrieving a big file
|
|
58
|
+
const testAddAndGetBigFile = () => {
|
|
59
|
+
const bigContent = createBigFileContent();
|
|
60
|
+
const bigFilePath = `${testDir}/big-file.bin`;
|
|
61
|
+
const cas = fileCas(sha256)(testDir);
|
|
62
|
+
const x0 = step(mkdir(testDir, { recursive: true }), () => writeFile(bigFilePath, bigContent));
|
|
63
|
+
const x1 = step(x0, writeRes => {
|
|
64
|
+
assert(writeRes[0] === 'ok', ['failed to write test file', writeRes]);
|
|
65
|
+
return casAddFile(cas)(bigFilePath);
|
|
66
|
+
});
|
|
67
|
+
// Verify the file is stored at the expected location
|
|
68
|
+
const x2 = step(x1, addRes => {
|
|
69
|
+
assert(addRes[0] === 'ok', ['failed to add file to CAS', addRes]);
|
|
70
|
+
return readFile(cas.url(addRes[1]));
|
|
71
|
+
});
|
|
72
|
+
const x3 = step(x2, readRes => {
|
|
73
|
+
assert(readRes[0] === 'ok', ['failed to read stored file', readRes]);
|
|
74
|
+
// Verify content is the same size as original
|
|
75
|
+
assertEq(length(readRes[1]), length(bigContent), 'stored content size mismatch');
|
|
76
|
+
return rm(testDir);
|
|
77
|
+
});
|
|
78
|
+
return step(x3, () => pure(undefined));
|
|
79
|
+
};
|
|
80
|
+
export const proof = {
|
|
81
|
+
// Both effects must be interpreted, not merely built: an `Effect` is inert
|
|
82
|
+
// data, so returning one from a proof runs none of its continuations and
|
|
83
|
+
// asserts nothing.
|
|
84
|
+
addBigFile: () => { virtual(emptyState)(testAddBigFile()); },
|
|
85
|
+
addAndGetBigFile: () => { virtual(emptyState)(testAddAndGetBigFile()); },
|
|
86
|
+
//
|
|
87
|
+
casWriteRead: () => {
|
|
88
|
+
// Round-trip a single-chunk payload through the real streaming CAS: `write` returns
|
|
89
|
+
// the content hash, and `read` streams the same bytes back as `ok` chunk items.
|
|
90
|
+
const content = vec8(0x2an);
|
|
91
|
+
const c = fileCas(sha256)('.');
|
|
92
|
+
const payload = nonEmpty(ok(content), empty());
|
|
93
|
+
const [state1, writeResult] = virtual(emptyState)(c.write(payload));
|
|
94
|
+
assert(writeResult[0] === 'ok', ['expected write ok', writeResult]);
|
|
95
|
+
const hash = writeResult[1];
|
|
96
|
+
assertEq(length(hash), 256n, ['expected 256-bit hash', length(hash)]);
|
|
97
|
+
assertEq(msb.cmp(hash)(computeSync(sha256)([content])), 0, 'write hash mismatch');
|
|
98
|
+
const drain = (acc) => (stream) => step(stream, (node) => {
|
|
99
|
+
if (node === undefined) {
|
|
100
|
+
return pure(ok(acc));
|
|
101
|
+
}
|
|
102
|
+
const { first, tail } = node;
|
|
103
|
+
if (first[0] === 'error') {
|
|
104
|
+
return pure(first);
|
|
105
|
+
}
|
|
106
|
+
return drain([...acc, first[1]])(tail);
|
|
107
|
+
});
|
|
108
|
+
const [, readResult] = virtual(state1)(drain([])(c.read(hash)));
|
|
109
|
+
assert(readResult[0] === 'ok', ['expected read ok', readResult]);
|
|
110
|
+
assertEq(msb.cmp(msb.listToVec(readResult[1]))(content), 0, 'read content mismatch');
|
|
111
|
+
},
|
|
112
|
+
casReadMissingShard: () => {
|
|
113
|
+
// A missing shard surfaces as an explicit error *item*, never as end-of-stream.
|
|
114
|
+
const c = fileCas(sha256)('.');
|
|
115
|
+
const hash = computeSync(sha256)([vec8(0x2an)]);
|
|
116
|
+
const node = virtual(emptyState)(c.read(hash))[1];
|
|
117
|
+
assert(node !== undefined, 'missing shard must not be EOF');
|
|
118
|
+
assert(node.first[0] === 'error', ['expected error item', node.tail]);
|
|
119
|
+
},
|
|
120
|
+
casWriteMultiChunk: () => {
|
|
121
|
+
// A multi-chunk payload streams through `writeBytes` chunk-by-chunk (the lease is
|
|
122
|
+
// renewed between chunks); the hash equals the SHA-256 of the concatenated bytes,
|
|
123
|
+
// and read streams the same content back.
|
|
124
|
+
const chunks = [vec8(0x11n), vec8(0x22n), vec8(0x33n)];
|
|
125
|
+
const c = fileCas(sha256)('.');
|
|
126
|
+
const payload = chunks.reduceRight((tail, chunk) => nonEmpty(ok(chunk), tail), empty());
|
|
127
|
+
const [state1, writeResult] = virtual(emptyState)(c.write(payload));
|
|
128
|
+
assert(writeResult[0] === 'ok', ['expected write ok', writeResult]);
|
|
129
|
+
const hash = writeResult[1];
|
|
130
|
+
assertEq(msb.cmp(hash)(computeSync(sha256)(chunks)), 0, 'multi-chunk write hash mismatch');
|
|
131
|
+
const drain = (acc) => (stream) => step(stream, (node) => {
|
|
132
|
+
if (node === undefined) {
|
|
133
|
+
return pure(ok(acc));
|
|
134
|
+
}
|
|
135
|
+
const { first, tail } = node;
|
|
136
|
+
if (first[0] === 'error') {
|
|
137
|
+
return pure(first);
|
|
138
|
+
}
|
|
139
|
+
return drain([...acc, first[1]])(tail);
|
|
140
|
+
});
|
|
141
|
+
const [, readResult] = virtual(state1)(drain([])(c.read(hash)));
|
|
142
|
+
assert(readResult[0] === 'ok', ['expected read ok', readResult]);
|
|
143
|
+
const expected = msb.concat(msb.concat(chunks[0])(chunks[1]))(chunks[2]);
|
|
144
|
+
assertEq(msb.cmp(msb.listToVec(readResult[1]))(expected), 0, 'multi-chunk read content mismatch');
|
|
145
|
+
},
|
|
146
|
+
casWriteDedup: () => {
|
|
147
|
+
// Same content ⇒ same hash; the second upload's replace-`rename` publishes over the
|
|
148
|
+
// first, leaving exactly one shard in the store.
|
|
149
|
+
const content = vec8(0x2an);
|
|
150
|
+
const c = fileCas(sha256)('.');
|
|
151
|
+
const payload = () => nonEmpty(ok(content), empty());
|
|
152
|
+
const [state1, w1] = virtual(emptyState)(c.write(payload()));
|
|
153
|
+
const [state2, w2] = virtual(state1)(c.write(payload()));
|
|
154
|
+
assert(!(w1[0] !== 'ok' || w2[0] !== 'ok'), ['expected both writes ok', w1, w2]);
|
|
155
|
+
assertEq(msb.cmp(w1[1])(w2[1]), 0, 'dedup hash mismatch');
|
|
156
|
+
const [, hashes] = virtual(state2)(c.list());
|
|
157
|
+
assertEq(hashes.length, 1, ['expected one shard after dedup', hashes.length]);
|
|
158
|
+
},
|
|
159
|
+
casWriteErrorItemAborts: () => {
|
|
160
|
+
// An error item mid-stream deletes the partial staging file and fails; nothing is
|
|
161
|
+
// published, so the store stays empty.
|
|
162
|
+
const c = fileCas(sha256)('.');
|
|
163
|
+
const okItem = ok(vec8(0x11n));
|
|
164
|
+
const errItem = error({ code: 'BOOM' });
|
|
165
|
+
const payload = nonEmpty(okItem, nonEmpty(errItem, empty()));
|
|
166
|
+
const [state1, result] = virtual(emptyState)(c.write(payload));
|
|
167
|
+
assert(result[0] === 'error', ['expected write error', result]);
|
|
168
|
+
const [, hashes] = virtual(state1)(c.list());
|
|
169
|
+
assertEq(hashes.length, 0, ['expected nothing published on abort', hashes]);
|
|
170
|
+
},
|
|
171
|
+
casWriteReadExceedsMaxLength: () => {
|
|
172
|
+
// The point of streaming: a payload larger than a single `Vec`'s `maxLength`
|
|
173
|
+
// (128 KiB) must round-trip. `write` lands the chunks on disk without ever
|
|
174
|
+
// holding them as one `Vec`, and `read` streams them back the same way — so the
|
|
175
|
+
// round-trip is verified by hashing the read stream incrementally rather than
|
|
176
|
+
// concatenating it (which would itself overflow `maxLength`).
|
|
177
|
+
const big = vec(maxLength)(0xabn); // one full-size chunk: exactly maxLength bits
|
|
178
|
+
const tail = vec8(0x2an); // one more byte ⇒ total > maxLength
|
|
179
|
+
const chunks = [big, tail];
|
|
180
|
+
const c = fileCas(sha256)('.');
|
|
181
|
+
const payload = chunks.reduceRight((tl, chunk) => nonEmpty(ok(chunk), tl), empty());
|
|
182
|
+
const [state1, w] = virtual(emptyState)(c.write(payload));
|
|
183
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
184
|
+
const hash = w[1];
|
|
185
|
+
assertEq(msb.cmp(hash)(computeSync(sha256)(chunks)), 0, 'oversized write hash mismatch');
|
|
186
|
+
// Fold the read stream straight into a fresh SHA-2 state — never one `Vec`.
|
|
187
|
+
const rehash = (state) => (stream) => step(stream, (node) => {
|
|
188
|
+
if (node === undefined) {
|
|
189
|
+
return pure(ok(sha256.end(state)));
|
|
190
|
+
}
|
|
191
|
+
const { first, tail } = node;
|
|
192
|
+
if (first[0] === 'error') {
|
|
193
|
+
return pure(first);
|
|
194
|
+
}
|
|
195
|
+
return rehash(sha256.append(first[1])(state))(tail);
|
|
196
|
+
});
|
|
197
|
+
const [, readBack] = virtual(state1)(rehash(sha256.init)(c.read(hash)));
|
|
198
|
+
assert(readBack[0] === 'ok', ['expected read ok', readBack]);
|
|
199
|
+
assertEq(msb.cmp(readBack[1])(hash), 0, 'oversized read-back hash mismatch');
|
|
200
|
+
},
|
|
201
|
+
casWriteGcReclaimsExpired: () => {
|
|
202
|
+
// A staging file whose deadline is in the past is reclaimed by the GC that `write`
|
|
203
|
+
// runs before staging its own file.
|
|
204
|
+
const stalePath = join('.', '.cas', '_stage', '0000000000000000000-stale');
|
|
205
|
+
const state0 = {
|
|
206
|
+
...emptyState,
|
|
207
|
+
epochNs: 1_000_000,
|
|
208
|
+
root: { '.cas': { '_stage': { '0000000000000000000-stale': [vec8(0x99n)] } } },
|
|
209
|
+
};
|
|
210
|
+
const content = vec8(0x2an);
|
|
211
|
+
const c = fileCas(sha256)('.');
|
|
212
|
+
const x = c.write(nonEmpty(ok(content), empty()));
|
|
213
|
+
const [state1, w] = virtual(state0)(x);
|
|
214
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
215
|
+
const [, present] = virtual(state1)(access(stalePath));
|
|
216
|
+
assert(present[0] === 'error', 'expected GC to reclaim the expired staging file');
|
|
217
|
+
},
|
|
218
|
+
casWriteGcSkipsLiveLease: () => {
|
|
219
|
+
// A staging file whose deadline is still in the future is left alone by the GC
|
|
220
|
+
// that `write` runs before staging its own file.
|
|
221
|
+
const livePath = join('.', '.cas', '_stage', '0000000000002000000-live');
|
|
222
|
+
const state0 = {
|
|
223
|
+
...emptyState,
|
|
224
|
+
epochNs: 1_000_000,
|
|
225
|
+
root: { '.cas': { '_stage': { '0000000000002000000-live': [vec8(0x99n)] } } },
|
|
226
|
+
};
|
|
227
|
+
const content = vec8(0x2an);
|
|
228
|
+
const c = fileCas(sha256)('.');
|
|
229
|
+
const x = c.write(nonEmpty(ok(content), empty()));
|
|
230
|
+
const [state1, w] = virtual(state0)(x);
|
|
231
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
232
|
+
const [, present] = virtual(state1)(access(livePath));
|
|
233
|
+
assert(present[0] === 'ok', 'expected GC to leave the live staging file alone');
|
|
234
|
+
},
|
|
235
|
+
casUploadSuccess: () => {
|
|
236
|
+
// A successful upload returns the hash and deletes the source file from cas_upload/.
|
|
237
|
+
const content = vec8(0x2an);
|
|
238
|
+
const state0 = { ...emptyState, root: { 'cas_upload': { 'myfile': [content] } } };
|
|
239
|
+
const [state1, result] = virtual(state0)(casUpload('.')('myfile'));
|
|
240
|
+
assert(result[0] === 'ok', ['expected casUpload ok', result]);
|
|
241
|
+
assertEq(length(result[1]), 256n, ['expected 256-bit hash', length(result[1])]);
|
|
242
|
+
// Source must be deleted after successful publish.
|
|
243
|
+
const srcPath = join('.', 'cas_upload', 'myfile');
|
|
244
|
+
const [, srcAccess] = virtual(state1)(access(srcPath));
|
|
245
|
+
assert(srcAccess[0] === 'error', 'expected source to be deleted after successful upload');
|
|
246
|
+
},
|
|
247
|
+
casUploadFailureKeepsSource: () => {
|
|
248
|
+
// A missing source file causes write to fail; casUpload returns error and the
|
|
249
|
+
// source is left in place (trivially: it was never there, but the upload is not published).
|
|
250
|
+
const state0 = { ...emptyState, root: {} };
|
|
251
|
+
const [state1, result] = virtual(state0)(casUpload('.')('nonexistent'));
|
|
252
|
+
assert(result[0] === 'error', ['expected casUpload to fail on missing source', result]);
|
|
253
|
+
// Nothing published to the store.
|
|
254
|
+
const c = fileCas(sha256)('.');
|
|
255
|
+
const [, hashes] = virtual(state1)(c.list());
|
|
256
|
+
assertEq(hashes.length, 0, ['expected nothing published on failed upload', hashes]);
|
|
257
|
+
},
|
|
258
|
+
collectReadDrainsChunks: () => {
|
|
259
|
+
// The common path: every chunk is `ok`, so collectRead concatenates them all
|
|
260
|
+
// and returns the whole blob as one `Vec`.
|
|
261
|
+
const stream = nonEmpty(ok(vec8(0x11n)), nonEmpty(ok(vec8(0x22n)), empty()));
|
|
262
|
+
const o = runPure(collectRead(stream));
|
|
263
|
+
assert(o.length === 1, 'expected collectRead to finish without issuing a command');
|
|
264
|
+
assertEq(o[0][0], 'ok');
|
|
265
|
+
},
|
|
266
|
+
collectReadPropagatesErrorItem: () => {
|
|
267
|
+
// An error item mid-stream short-circuits collectRead with that same error.
|
|
268
|
+
const boom = error('boom');
|
|
269
|
+
const stream = nonEmpty(ok(vec8(0x11n)), nonEmpty(boom, empty()));
|
|
270
|
+
const o = runPure(collectRead(stream));
|
|
271
|
+
assert(o.length === 1, 'expected collectRead to finish without issuing a command');
|
|
272
|
+
const [r] = o;
|
|
273
|
+
assertEq(r[0], 'error');
|
|
274
|
+
assertEq(r[1], 'boom');
|
|
275
|
+
},
|
|
276
|
+
// A single `Vec` cannot exceed `maxLength` bits — feed a pure stream whose second
|
|
277
|
+
// chunk pushes the running total just over the limit so the overflow guard fires
|
|
278
|
+
// without any real I/O.
|
|
279
|
+
collectReadOverflow: () => {
|
|
280
|
+
const half = maxLength / 2n;
|
|
281
|
+
const v1 = vec(half)(0n);
|
|
282
|
+
const v2 = vec(half + 1n)(0n);
|
|
283
|
+
const stream = nonEmpty(ok(v1), nonEmpty(ok(v2), empty()));
|
|
284
|
+
const o = runPure(collectRead(stream));
|
|
285
|
+
assert(o.length === 1, 'expected collectRead to finish without issuing a command');
|
|
286
|
+
assertEq(o[0][0], 'error');
|
|
287
|
+
},
|
|
288
|
+
casListPropagatesNonNotFoundAccessError: () => {
|
|
289
|
+
// A non-ENOENT `access` failure (permissions, corruption) is a genuine storage
|
|
290
|
+
// error and must propagate out of `list`, not be swallowed as an empty store.
|
|
291
|
+
const c = fileCas(sha256)('.');
|
|
292
|
+
const boom = { code: 'EACCES' };
|
|
293
|
+
const r = casCommand(c.list());
|
|
294
|
+
assert(r[0] === 'cont', 'expected list() to issue an access command first');
|
|
295
|
+
assertEq(r[1], 'access');
|
|
296
|
+
let threw;
|
|
297
|
+
try {
|
|
298
|
+
r[2](error(boom));
|
|
299
|
+
}
|
|
300
|
+
catch (e) {
|
|
301
|
+
threw = e;
|
|
302
|
+
}
|
|
303
|
+
assertEq(threw, boom);
|
|
304
|
+
},
|
|
305
|
+
};
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
7
|
import { bun } from '../config/module.f.js';
|
|
8
|
-
import {
|
|
9
|
-
export const bunSteps = (version) =>
|
|
8
|
+
import { install, test, uses } from '../common/module.f.js';
|
|
9
|
+
export const bunSteps = (version) => [
|
|
10
10
|
install(uses('oven-sh/setup-bun', { 'bun-version': bun })),
|
|
11
11
|
install({ run: `bun install -g functionalscript@${version}` }),
|
|
12
12
|
test({ run: 'bun install --frozen-lockfile' }),
|
|
13
13
|
test({ run: `bunx functionalscript@${version} t` }),
|
|
14
14
|
test({ run: 'bun test --coverage' }),
|
|
15
|
-
]
|
|
15
|
+
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared CI types and helpers: GitHub Actions step/job RTTI schemas, the
|
|
3
3
|
* `MetaStep` representation used by tool-specific modules, and assemblers like
|
|
4
|
-
* `install`, `test`, `
|
|
4
|
+
* `install`, `test`, `ubuntu`, and `toSteps`.
|
|
5
5
|
*
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
@@ -83,7 +83,6 @@ export type MetaStep = {
|
|
|
83
83
|
export declare const uses: (name: keyof typeof actions, w?: Record<string, string>) => Step;
|
|
84
84
|
export declare const install: (step: Step) => MetaStep;
|
|
85
85
|
export declare const test: (step: Step) => MetaStep;
|
|
86
|
-
export declare const clean: (steps: readonly MetaStep[]) => readonly MetaStep[];
|
|
87
86
|
export declare const toSteps: (m: readonly MetaStep[]) => readonly Step[];
|
|
88
87
|
export declare const ubuntu: (ms: readonly MetaStep[]) => Job;
|
|
89
88
|
export declare const ubuntuArm: (ms: readonly MetaStep[]) => Job;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared CI types and helpers: GitHub Actions step/job RTTI schemas, the
|
|
3
3
|
* `MetaStep` representation used by tool-specific modules, and assemblers like
|
|
4
|
-
* `install`, `test`, `
|
|
4
|
+
* `install`, `test`, `ubuntu`, and `toSteps`.
|
|
5
5
|
*
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
@@ -37,10 +37,6 @@ export const uses = (name, w) => ({
|
|
|
37
37
|
});
|
|
38
38
|
export const install = (step) => ({ type: 'install', step });
|
|
39
39
|
export const test = (step) => ({ type: 'test', step });
|
|
40
|
-
export const clean = (steps) => [
|
|
41
|
-
...steps,
|
|
42
|
-
test({ run: 'git reset --hard HEAD && git clean -fdx' })
|
|
43
|
-
];
|
|
44
40
|
export const toSteps = (m) => {
|
|
45
41
|
const filter = (st) => m.flatMap((mt) => mt.type === st ? [mt.step] : []);
|
|
46
42
|
const aptGet = m.flatMap(v => v.type === 'apt-get' ? [v.package] : []).join(' ');
|
|
@@ -19,24 +19,24 @@ export declare const images: {
|
|
|
19
19
|
readonly arm: 'windows-11-arm';
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
|
-
export declare const functionalscript: '0.
|
|
22
|
+
export declare const functionalscript: '0.38.0';
|
|
23
23
|
export declare const bun = "1.3.14";
|
|
24
|
-
export declare const deno = "2.9.
|
|
25
|
-
export declare const playwright = "1.
|
|
24
|
+
export declare const deno = "2.9.4";
|
|
25
|
+
export declare const playwright = "1.62.0";
|
|
26
26
|
export declare const node: {
|
|
27
27
|
readonly default: '26.5.0';
|
|
28
28
|
readonly node22: '22.23.1';
|
|
29
29
|
readonly node24: '24.18.0';
|
|
30
30
|
};
|
|
31
|
-
export declare const wasmtime = "
|
|
32
|
-
export declare const wasmer = "7.2.
|
|
31
|
+
export declare const wasmtime = "47.0.2";
|
|
32
|
+
export declare const wasmer = "7.2.1";
|
|
33
33
|
export declare const actions: {
|
|
34
|
-
readonly 'actions/checkout': 'v7';
|
|
35
|
-
readonly 'actions/setup-node': '
|
|
34
|
+
readonly 'actions/checkout': 'v7.0.1';
|
|
35
|
+
readonly 'actions/setup-node': 'v7.0.0';
|
|
36
36
|
readonly 'actions/cache': 'v6.1.0';
|
|
37
37
|
readonly 'denoland/setup-deno': 'v2.0.5';
|
|
38
38
|
readonly 'oven-sh/setup-bun': 'v2.2.0';
|
|
39
39
|
readonly 'bytecodealliance/actions/wasmtime/setup': 'v1.1.3';
|
|
40
40
|
readonly 'wasmerio/setup-wasmer': 'v3.1';
|
|
41
|
-
readonly 'dtolnay/rust-toolchain': '1.
|
|
41
|
+
readonly 'dtolnay/rust-toolchain': '1.97.1';
|
|
42
42
|
};
|