functionalscript 0.37.0 → 0.38.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/{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 +19 -0
- package/fjs/cas/evo/mcp/module.f.js +56 -0
- package/fjs/cas/evo/mcp/proof.f.d.ts +9 -0
- package/fjs/cas/evo/mcp/proof.f.js +95 -0
- package/fjs/cas/evo/module.f.d.ts +138 -0
- package/fjs/cas/evo/module.f.js +309 -0
- package/fjs/cas/evo/proof.f.d.ts +32 -0
- package/fjs/cas/evo/proof.f.js +453 -0
- package/fjs/cas/mcp/module.f.d.ts +49 -0
- package/{fs → fjs}/cas/mcp/module.f.js +54 -76
- package/{fs → fjs}/cas/mcp/proof.f.d.ts +4 -1
- package/{fs → fjs}/cas/mcp/proof.f.js +41 -13
- package/{fs → fjs}/cas/module.f.d.ts +10 -0
- package/{fs → fjs}/cas/module.f.js +27 -1
- package/{fs → fjs}/cas/proof.f.d.ts +4 -0
- package/{fs → fjs}/cas/proof.f.js +77 -86
- package/{fs → fjs}/ci/config/module.f.d.ts +5 -5
- package/{fs → fjs}/ci/config/module.f.js +5 -5
- package/{fs → fjs}/ci/proof.f.js +14 -9
- package/{fs → fjs}/ci/rust/module.f.js +9 -1
- package/{fs → fjs}/cli/proof.f.js +22 -63
- package/{fs → fjs}/common/monoid/proof.f.js +4 -9
- 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/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/parser/module.f.d.ts +5 -0
- package/{fs → fjs}/djs/parser/module.f.js +20 -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/proof.f.d.ts +3 -0
- package/{fs → fjs}/djs/transpiler/proof.f.js +29 -30
- package/{fs → fjs}/effects/memory/proof.f.js +8 -21
- package/{fs → fjs}/effects/node/memory/proof.js +5 -12
- package/{fs → fjs}/effects/node/module.d.ts +1 -1
- package/{fs → fjs}/effects/node/module.f.d.ts +1 -1
- 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 +106 -292
- package/{fs → fjs}/effects/node/virtual/proof.f.d.ts +1 -0
- package/{fs → fjs}/effects/node/virtual/proof.f.js +36 -29
- package/{fs → fjs}/effects/proof.f.js +16 -45
- package/{fs → fjs}/emergent_testing/proof.f.js +7 -7
- 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 +9 -2
- package/{fs → fjs}/mcp/proof.f.js +12 -12
- package/{fs → fjs}/mcp/stdio/module.f.d.ts +2 -2
- package/{fs → fjs}/mcp/stdio/module.f.js +2 -2
- 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/proof.f.js +2 -6
- package/{fs → fjs}/module.f.js +1 -1
- 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/proof.f.js +49 -145
- 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/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/proof.f.js +55 -163
- 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/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/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/proof.f.js +3 -6
- package/package.json +6 -6
- 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/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/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}/cas/cli/module.f.js +0 -0
- /package/{fs → fjs}/ci/bun/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/bun/module.f.js +0 -0
- /package/{fs → fjs}/ci/common/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/common/module.f.js +0 -0
- /package/{fs → fjs}/ci/deno/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/deno/module.f.js +0 -0
- /package/{fs → fjs}/ci/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/module.f.js +0 -0
- /package/{fs → fjs}/ci/node/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/node/module.f.js +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/module.f.js +0 -0
- /package/{fs → fjs}/cli/proof.f.d.ts +0 -0
- /package/{fs → fjs}/common/monoid/module.f.d.ts +0 -0
- /package/{fs → fjs}/common/monoid/module.f.js +0 -0
- /package/{fs → fjs}/common/monoid/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/module.f.js +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/module.f.js +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}/djs/transpiler/module.f.js +0 -0
- /package/{fs → fjs}/effects/list/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/list/module.f.js +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.f.d.ts +0 -0
- /package/{fs → fjs}/effects/module.f.js +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/module.f.js +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}/effects/proof.f.d.ts +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/module.f.js +0 -0
- /package/{fs → fjs}/emergent_testing/proof.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/module.f.js +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/module.f.js +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/module.f.js +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/remove/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/remove/module.f.js +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/list/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/list/module.f.js +0 -0
- /package/{fs → fjs}/types/list/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/module.f.js +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/module.f.js +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/module.f.js +0 -0
- /package/{fs → fjs}/website/proof.f.d.ts +0 -0
|
@@ -10,6 +10,8 @@ import { codePointListToString, stringToCodePointList } from '../text/utf16/modu
|
|
|
10
10
|
import { definedValues } from '../types/object/module.f.js';
|
|
11
11
|
import { isArray2 } from '../types/array/module.f.js';
|
|
12
12
|
import { map, toArray, repeat as listRepeat } from '../types/list/module.f.js';
|
|
13
|
+
import { contains } from '../types/range/module.f.js';
|
|
14
|
+
import { assert } from '../asserts/module.f.js';
|
|
13
15
|
/**
|
|
14
16
|
* Full 24-bit symbol range packed into a single {@link TerminalRange}.
|
|
15
17
|
*/
|
|
@@ -18,10 +20,6 @@ export const fullRange = 0x000000_FFFFFF;
|
|
|
18
20
|
* Unicode scalar value range packed into a single {@link TerminalRange}.
|
|
19
21
|
*/
|
|
20
22
|
export const unicodeRange = 0x000000_10FFFF;
|
|
21
|
-
/**
|
|
22
|
-
* Maximal non-Unicode symbol encoded as a string value.
|
|
23
|
-
*/
|
|
24
|
-
export const max = codePointListToString([0xFFFFFF]);
|
|
25
23
|
/**
|
|
26
24
|
* Maximal Unicode code point encoded as a string value.
|
|
27
25
|
*/
|
|
@@ -34,11 +32,9 @@ const { fromCodePoint } = String;
|
|
|
34
32
|
*/
|
|
35
33
|
const offset = 24;
|
|
36
34
|
const mask = (1 << offset) - 1;
|
|
37
|
-
const isValid = (
|
|
35
|
+
const isValid = contains(0, mask);
|
|
38
36
|
export const rangeEncode = (a, b) => {
|
|
39
|
-
|
|
40
|
-
throw `Invalid range ${a} ${b}.`;
|
|
41
|
-
}
|
|
37
|
+
assert(isValid(a) && isValid(b) && a <= b);
|
|
42
38
|
return Number((BigInt(a) << BigInt(offset)) | BigInt(b));
|
|
43
39
|
};
|
|
44
40
|
/**
|
|
@@ -46,13 +42,16 @@ export const rangeEncode = (a, b) => {
|
|
|
46
42
|
*/
|
|
47
43
|
export const oneEncode = (a) => rangeEncode(a, a);
|
|
48
44
|
/**
|
|
49
|
-
* End-of-file marker
|
|
45
|
+
* End-of-file marker: `mask`, the single largest value the 24-bit symbol
|
|
46
|
+
* space can hold (the top of `fullRange`). Deliberately outside Unicode
|
|
47
|
+
* (`unicodeRange` tops out at `0x10FFFF`) so it can never collide with a
|
|
48
|
+
* real code point.
|
|
50
49
|
*/
|
|
51
|
-
export const eof = oneEncode(
|
|
50
|
+
export const eof = oneEncode(mask);
|
|
52
51
|
/**
|
|
53
52
|
* Decodes a packed range into `[start, end]` symbols.
|
|
54
53
|
*/
|
|
55
|
-
export const rangeDecode = (r) => [Number(BigInt(r) >> BigInt(offset)),
|
|
54
|
+
export const rangeDecode = (r) => [Number(BigInt(r) >> BigInt(offset)), r & mask];
|
|
56
55
|
const mapOneEncode = map(oneEncode);
|
|
57
56
|
export const toSequence = (s) => toArray(mapOneEncode(stringToCodePointList(s)));
|
|
58
57
|
/**
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { assert, assertEq } from '../asserts/module.f.js';
|
|
2
|
+
import { classic, deterministic } from './testlib.f.js';
|
|
3
|
+
import { rangeEncode, str, set, range, commaJoin0Plus, isEmpty, oneEncode, repeat1Plus, } from './module.f.js';
|
|
4
|
+
export const proof = {
|
|
5
|
+
test: () => {
|
|
6
|
+
classic();
|
|
7
|
+
deterministic();
|
|
8
|
+
},
|
|
9
|
+
throw: {
|
|
10
|
+
rangeEncodeInvalid: [
|
|
11
|
+
() => { rangeEncode(-1, 0); },
|
|
12
|
+
() => { rangeEncode(0, -1); },
|
|
13
|
+
() => { rangeEncode(5, 3); },
|
|
14
|
+
],
|
|
15
|
+
rangeInvalid: [
|
|
16
|
+
() => { range('a'); },
|
|
17
|
+
() => { range('abc'); },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
str: [
|
|
21
|
+
() => {
|
|
22
|
+
const result = str('a');
|
|
23
|
+
assertEq(typeof result, 'number', result);
|
|
24
|
+
assertEq(result, oneEncode(0x61));
|
|
25
|
+
},
|
|
26
|
+
() => {
|
|
27
|
+
const result = str('ab');
|
|
28
|
+
assert(Array.isArray(result), result);
|
|
29
|
+
assertEq(result.length, 2, result);
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
set: () => {
|
|
33
|
+
const result = set('abc');
|
|
34
|
+
assert(!(typeof result !== 'object' || result === null), result);
|
|
35
|
+
assert('a' in result, result);
|
|
36
|
+
assert('b' in result, result);
|
|
37
|
+
assert('c' in result, result);
|
|
38
|
+
},
|
|
39
|
+
commaJoin0Plus: () => {
|
|
40
|
+
const ws = '';
|
|
41
|
+
const item = 'x';
|
|
42
|
+
const result = commaJoin0Plus(ws)('[]', item);
|
|
43
|
+
assert(Array.isArray(result), result);
|
|
44
|
+
assert(result[0] === '[', result);
|
|
45
|
+
},
|
|
46
|
+
isEmpty: [
|
|
47
|
+
() => { assert(isEmpty(''), 'empty string should be empty'); },
|
|
48
|
+
() => { assert(isEmpty([]), 'empty array should be empty'); },
|
|
49
|
+
() => { assert(!(isEmpty('a')), 'non-empty string should not be empty'); },
|
|
50
|
+
() => {
|
|
51
|
+
const f = () => '';
|
|
52
|
+
assert(isEmpty(f), 'function returning empty string should be empty');
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
repeat1Plus: [
|
|
56
|
+
() => {
|
|
57
|
+
const result = repeat1Plus('x');
|
|
58
|
+
assert(result[0] === 'x');
|
|
59
|
+
assertEq(typeof result[1], 'function', 'expected repeat0Plus function');
|
|
60
|
+
},
|
|
61
|
+
() => {
|
|
62
|
+
const rule = 'ab';
|
|
63
|
+
const result = repeat1Plus(rule);
|
|
64
|
+
assertEq(result[0], rule);
|
|
65
|
+
const inner = result[1]();
|
|
66
|
+
assert(!(!('some' in inner) || !('none' in inner)), 'expected Option shape');
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { commaJoin0Plus,
|
|
1
|
+
import { commaJoin0Plus, none, option, range, remove, repeat, repeat0Plus, set, unicodeMax } from './module.f.js';
|
|
2
2
|
export const classic = () => {
|
|
3
3
|
// https://www.json.org/json-en.html
|
|
4
4
|
const json = () => [element];
|
|
@@ -93,7 +93,7 @@ export const deterministic = () => {
|
|
|
93
93
|
const string = [
|
|
94
94
|
'"',
|
|
95
95
|
repeat0Plus({
|
|
96
|
-
...remove(range(` ${
|
|
96
|
+
...remove(range(` ${unicodeMax}`), set('"\\')),
|
|
97
97
|
escape: [
|
|
98
98
|
'\\',
|
|
99
99
|
{
|
|
@@ -2,13 +2,16 @@ export declare const proof: {
|
|
|
2
2
|
mainAdd: () => void;
|
|
3
3
|
mainAddGetBig: () => void;
|
|
4
4
|
mainAddWrongArgs: () => void;
|
|
5
|
+
mainAddMissingFile: () => void;
|
|
5
6
|
mainGetFound: () => void;
|
|
6
7
|
mainGetNotFound: () => void;
|
|
7
8
|
mainGetWrongArgs: () => void;
|
|
8
9
|
mainGetInvalidHash: () => void;
|
|
9
10
|
mainList: () => void;
|
|
10
11
|
mainListEmptyStore: () => void;
|
|
11
|
-
mainListCorruptStore: () => void;
|
|
12
12
|
mainNoCmd: () => void;
|
|
13
13
|
mainUnknownCmd: () => void;
|
|
14
|
+
throw: {
|
|
15
|
+
mainListCorruptStore: () => readonly [import("../../effects/node/virtual/module.f.ts").State, number];
|
|
16
|
+
};
|
|
14
17
|
};
|
|
@@ -13,12 +13,8 @@ export const proof = {
|
|
|
13
13
|
const content = vec8(0x2an);
|
|
14
14
|
const state = { ...emptyState, root: { myfile: [content] } };
|
|
15
15
|
const [finalState, exitCode] = virtual(state)(main(makeOptions(['add', 'myfile'])));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
if (finalState.stdout.length === 0) {
|
|
20
|
-
throw 'expected hash in stdout';
|
|
21
|
-
}
|
|
16
|
+
assertEq(exitCode, 0, ['expected exit 0', exitCode]);
|
|
17
|
+
assert(finalState.stdout.length !== 0, 'expected hash in stdout');
|
|
22
18
|
},
|
|
23
19
|
mainAddGetBig: () => {
|
|
24
20
|
const chunk = vec(maxLength)(1n);
|
|
@@ -47,18 +43,21 @@ export const proof = {
|
|
|
47
43
|
assertEq(exitCode, 1);
|
|
48
44
|
assert(finalState.stderr.length !== 0);
|
|
49
45
|
},
|
|
46
|
+
mainAddMissingFile: () => {
|
|
47
|
+
// The source path doesn't exist, so `streamFile`'s first read comes back as an
|
|
48
|
+
// error item; `write` fails closed with that error and the handler exits 1
|
|
49
|
+
// without ever calling `log` — covers the `hashResult[0] === 'error'` branch.
|
|
50
|
+
const [, exitCode] = virtual(emptyState)(main(makeOptions(['add', 'missing'])));
|
|
51
|
+
assertEq(exitCode, 1);
|
|
52
|
+
},
|
|
50
53
|
mainGetFound: () => {
|
|
51
54
|
const content = vec8(0x2an);
|
|
52
55
|
const state = { ...emptyState, root: { myfile: [content] } };
|
|
53
56
|
const [state1, exitCode1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
|
|
54
|
-
|
|
55
|
-
throw ['expected add exit 0', exitCode1];
|
|
56
|
-
}
|
|
57
|
+
assertEq(exitCode1, 0, ['expected add exit 0', exitCode1]);
|
|
57
58
|
const hashStr = state1.stdout.trim();
|
|
58
59
|
const [, exitCode2] = virtual(state1)(main(makeOptions(['get', hashStr, 'output'])));
|
|
59
|
-
|
|
60
|
-
throw ['expected get exit 0', exitCode2];
|
|
61
|
-
}
|
|
60
|
+
assertEq(exitCode2, 0, ['expected get exit 0', exitCode2]);
|
|
62
61
|
},
|
|
63
62
|
mainGetNotFound: () => {
|
|
64
63
|
// valid cBase32 hash that has not been stored
|
|
@@ -68,82 +67,46 @@ export const proof = {
|
|
|
68
67
|
const hashStr = state1.stdout.trim();
|
|
69
68
|
// use an empty store so the hash is not found
|
|
70
69
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', hashStr, 'output'])));
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
if (finalState.stderr.length === 0) {
|
|
75
|
-
throw 'expected error in stderr';
|
|
76
|
-
}
|
|
70
|
+
assertEq(exitCode, 1, ['expected exit 1', exitCode]);
|
|
71
|
+
assert(finalState.stderr.length !== 0, 'expected error in stderr');
|
|
77
72
|
},
|
|
78
73
|
mainGetWrongArgs: () => {
|
|
79
74
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get'])));
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
if (finalState.stderr.length === 0) {
|
|
84
|
-
throw 'expected error in stderr';
|
|
85
|
-
}
|
|
75
|
+
assertEq(exitCode, 1, ['expected exit 1', exitCode]);
|
|
76
|
+
assert(finalState.stderr.length !== 0, 'expected error in stderr');
|
|
86
77
|
},
|
|
87
78
|
mainGetInvalidHash: () => {
|
|
88
79
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', 'not-a-valid-hash', 'output'])));
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (finalState.stderr.length === 0) {
|
|
93
|
-
throw 'expected error in stderr';
|
|
94
|
-
}
|
|
80
|
+
assertEq(exitCode, 1, ['expected exit 1', exitCode]);
|
|
81
|
+
assert(finalState.stderr.length !== 0, 'expected error in stderr');
|
|
95
82
|
},
|
|
96
83
|
mainList: () => {
|
|
97
84
|
const content = vec8(0x2an);
|
|
98
85
|
const state = { ...emptyState, root: { myfile: [content] } };
|
|
99
86
|
const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
|
|
100
87
|
const [, exitCode] = virtual(state1)(main(makeOptions(['list'])));
|
|
101
|
-
|
|
102
|
-
throw ['expected exit 0', exitCode];
|
|
103
|
-
}
|
|
88
|
+
assertEq(exitCode, 0, ['expected exit 0', exitCode]);
|
|
104
89
|
},
|
|
105
90
|
mainListEmptyStore: () => {
|
|
106
91
|
// A fresh directory has no `.cas` yet; listing must succeed (empty),
|
|
107
92
|
// not crash unwrapping a readdir ENOENT.
|
|
108
93
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['list'])));
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
if (finalState.stdout !== '') {
|
|
113
|
-
throw ['expected empty stdout', finalState.stdout];
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
mainListCorruptStore: () => {
|
|
117
|
-
// `.cas` exists but is a file, not a directory: a real storage error
|
|
118
|
-
// that must surface, not be masked as an empty list.
|
|
119
|
-
const state = { ...emptyState, root: { '.cas': [vec8(0x2an)] } };
|
|
120
|
-
let threw = false;
|
|
121
|
-
try {
|
|
122
|
-
virtual(state)(main(makeOptions(['list'])));
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
threw = true;
|
|
126
|
-
}
|
|
127
|
-
if (!threw) {
|
|
128
|
-
throw 'expected list to surface the storage error';
|
|
129
|
-
}
|
|
94
|
+
assertEq(exitCode, 0, ['expected exit 0', exitCode]);
|
|
95
|
+
assertEq(finalState.stdout, '', ['expected empty stdout', finalState.stdout]);
|
|
130
96
|
},
|
|
131
97
|
mainNoCmd: () => {
|
|
132
98
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions([])));
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
if (finalState.stderr.length === 0) {
|
|
137
|
-
throw 'expected error in stderr';
|
|
138
|
-
}
|
|
99
|
+
assertEq(exitCode, 1, ['expected exit 1', exitCode]);
|
|
100
|
+
assert(finalState.stderr.length !== 0, 'expected error in stderr');
|
|
139
101
|
},
|
|
140
102
|
mainUnknownCmd: () => {
|
|
141
103
|
const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['bogus'])));
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
104
|
+
assertEq(exitCode, 1, ['expected exit 1', exitCode]);
|
|
105
|
+
assert(finalState.stderr.length !== 0, 'expected error in stderr');
|
|
106
|
+
},
|
|
107
|
+
throw: {
|
|
108
|
+
// `.cas` exists but is a file, not a directory: a real storage error
|
|
109
|
+
// that must surface, not be masked as an empty list.
|
|
110
|
+
mainListCorruptStore: () => virtual({ ...emptyState, root: { '.cas': [vec8(0x2an)] } })(main(makeOptions(['list']))),
|
|
148
111
|
},
|
|
149
112
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Operation } from '../../../effects/module.f.ts';
|
|
2
|
+
import { type MemOp } from '../../../effects/memory/module.f.ts';
|
|
3
|
+
import { type ToolEntry } from '../../../mcp/module.f.ts';
|
|
4
|
+
import { type Evo } from '../module.f.ts';
|
|
5
|
+
/** Arguments for `evo_list`: none. */
|
|
6
|
+
export declare const evoListArgs: {};
|
|
7
|
+
/** Arguments for `evo_head`: the subject whose current heads are requested. */
|
|
8
|
+
export declare const evoHeadArgs: {
|
|
9
|
+
readonly subject: import("../../../types/rtti/module.f.ts").String;
|
|
10
|
+
};
|
|
11
|
+
/** Arguments for `evo_add`: a new revision, per `fjs/cas/evo`'s `AddRevision`. */
|
|
12
|
+
export declare const evoAddArgs: {
|
|
13
|
+
readonly parents: import("../../../types/rtti/module.f.ts").Type1<"array", import("../../../types/rtti/module.f.ts").String>;
|
|
14
|
+
readonly snapshot: import("../../../types/rtti/module.f.ts").Or<readonly [import("../../../types/rtti/module.f.ts").String, undefined]>;
|
|
15
|
+
readonly subject: import("../../../types/rtti/module.f.ts").Or<readonly [import("../../../types/rtti/module.f.ts").String, undefined]>;
|
|
16
|
+
readonly archived: import("../../../types/rtti/module.f.ts").Or<readonly [true, undefined]>;
|
|
17
|
+
};
|
|
18
|
+
/** Registry of all Evo tools, bound to an `Evo<O>`. */
|
|
19
|
+
export declare const evoToolRegistry: <O extends Operation>(e: Evo<O>) => readonly ToolEntry<O | MemOp>[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions for the Evo API (`fjs/cas/evo/module.f.ts`): subjects
|
|
3
|
+
* and revision heads over the content-addressable store, backed by the
|
|
4
|
+
* in-memory cache the core module maintains.
|
|
5
|
+
*
|
|
6
|
+
* ## Tools
|
|
7
|
+
*
|
|
8
|
+
* | Tool | args | action | result |
|
|
9
|
+
* |-------------|-------------------------------------------|---------------|---------------------------|
|
|
10
|
+
* | `evo_list` | `{}` | `e.list()` | subjects, as a JSON array of strings |
|
|
11
|
+
* | `evo_head` | `{ subject }` | `e.head(...)` | head hashes, one per line |
|
|
12
|
+
* | `evo_add` | `{ parents, snapshot?, subject?, archived? }` | `e.add(...)` | hash (cBase32) |
|
|
13
|
+
*
|
|
14
|
+
* These tools are not served by their own process: `fjs/cas/mcp` (the same
|
|
15
|
+
* server as `cas_add`/`cas_get`/`cas_list`) builds one `Evo<O>` from its own
|
|
16
|
+
* `Cas<O>` and cache slot, concatenates `evoToolRegistry` onto its own
|
|
17
|
+
* registry, and serves everything from that single process — one `~/.cas/`
|
|
18
|
+
* store, one Evo cache, one server.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
import { string, option, array } from '../../../types/rtti/module.f.js';
|
|
23
|
+
import { pure } from '../../../effects/module.f.js';
|
|
24
|
+
import {} from '../../../effects/memory/module.f.js';
|
|
25
|
+
import { toolEntry, errorResult, okResult, } from '../../../mcp/module.f.js';
|
|
26
|
+
import { stringify } from '../../../media/json/module.f.js';
|
|
27
|
+
import { identity } from '../../../types/function/module.f.js';
|
|
28
|
+
import {} from '../module.f.js';
|
|
29
|
+
// ── Argument schemas (declared once, used for both inputSchema and validate) ─────
|
|
30
|
+
/** Arguments for `evo_list`: none. */
|
|
31
|
+
export const evoListArgs = {};
|
|
32
|
+
/** Arguments for `evo_head`: the subject whose current heads are requested. */
|
|
33
|
+
export const evoHeadArgs = {
|
|
34
|
+
subject: string,
|
|
35
|
+
};
|
|
36
|
+
/** Arguments for `evo_add`: a new revision, per `fjs/cas/evo`'s `AddRevision`. */
|
|
37
|
+
export const evoAddArgs = {
|
|
38
|
+
parents: array(string),
|
|
39
|
+
snapshot: option(string),
|
|
40
|
+
subject: option(string),
|
|
41
|
+
archived: option(true),
|
|
42
|
+
};
|
|
43
|
+
// ── Tool registry ────────────────────────────────────────────────────────────────
|
|
44
|
+
/** Canonical JSON encoder for `evo_list`'s result. */
|
|
45
|
+
const toJson = stringify(identity);
|
|
46
|
+
/** Registry of all Evo tools, bound to an `Evo<O>`. */
|
|
47
|
+
export const evoToolRegistry = (e) => [
|
|
48
|
+
toolEntry('evo_list', 'List all subjects with at least one stored revision, as a JSON array of strings.', evoListArgs,
|
|
49
|
+
// Subjects are arbitrary caller-supplied strings (unlike hashes, not
|
|
50
|
+
// constrained to a newline-free alphabet), so a `join('\n')` line
|
|
51
|
+
// format could not represent an empty subject or one containing a
|
|
52
|
+
// newline without ambiguity — JSON encoding can.
|
|
53
|
+
() => e.list().step(subjects => pure(okResult(toJson(subjects))))),
|
|
54
|
+
toolEntry('evo_head', 'List the current head hashes (cBase32) of a subject, one per line. Empty when the subject is unknown.', evoHeadArgs, ({ subject }) => e.head(subject).step(heads => pure(okResult(heads.join('\n'))))),
|
|
55
|
+
toolEntry('evo_add', 'Add a new revision (a `vnd.fjs.revision` blob) and return its hash (cBase32). `subject` is required unless there is exactly one parent, from which it is inherited. `snapshot`, when omitted, is resolved from the parents (zero parents → `subject`, one parent → the parent\'s snapshot; a merge requires an explicit `snapshot`) and written explicitly. `generation` is computed by the server.', evoAddArgs, (input) => e.add(input).step(result => pure(result[0] === 'error' ? errorResult(result[1]) : okResult(result[1])))),
|
|
56
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const proof: {
|
|
2
|
+
toolNamesMatchTheDesign: () => void;
|
|
3
|
+
evoListReflectsTheCache: () => void;
|
|
4
|
+
evoListEncodesArbitrarySubjectsAsJson: () => void;
|
|
5
|
+
evoHeadReflectsTheCache: () => void;
|
|
6
|
+
evoHeadMissingSubjectIsInvalidArguments: () => void;
|
|
7
|
+
evoAddSuccessReturnsHash: () => void;
|
|
8
|
+
evoAddDomainErrorIsError: () => void;
|
|
9
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { assert, assertEq } from '../../../asserts/module.f.js';
|
|
2
|
+
import { fileCas } from '../../module.f.js';
|
|
3
|
+
import { sha256 } from '../../../crypto/sha2/module.f.js';
|
|
4
|
+
import { emptyState, virtual } from '../../../effects/node/virtual/module.f.js';
|
|
5
|
+
import { vec8 } from '../../../types/bit_vec/module.f.js';
|
|
6
|
+
import { vecToCBase32 } from '../../../basen/cbase32/module.f.js';
|
|
7
|
+
import { initEvo, evo } from '../module.f.js';
|
|
8
|
+
import { evoToolRegistry } from './module.f.js';
|
|
9
|
+
const home = '/home/user';
|
|
10
|
+
const findEntry = (registry, name) => {
|
|
11
|
+
const entry = registry.find(e => e.name === name);
|
|
12
|
+
assert(entry !== undefined, ['missing tool entry', name]);
|
|
13
|
+
return entry;
|
|
14
|
+
};
|
|
15
|
+
const textOf = (result) => {
|
|
16
|
+
const [item] = result.content;
|
|
17
|
+
assert(item.type === 'text', ['expected a text content item', item]);
|
|
18
|
+
return item.text;
|
|
19
|
+
};
|
|
20
|
+
export const proof = {
|
|
21
|
+
toolNamesMatchTheDesign: () => {
|
|
22
|
+
const e = { list: () => { throw 'unused'; }, head: () => { throw 'unused'; }, add: () => { throw 'unused'; } };
|
|
23
|
+
assertEq(evoToolRegistry(e).map(entry => entry.name).join(','), 'evo_list,evo_head,evo_add');
|
|
24
|
+
},
|
|
25
|
+
evoListReflectsTheCache: () => {
|
|
26
|
+
const c = fileCas(sha256)(home);
|
|
27
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
28
|
+
const e = evo(c)(cacheKey);
|
|
29
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_list');
|
|
30
|
+
const [, result] = virtual(state0)(entry.handle({}));
|
|
31
|
+
assert(!result.isError);
|
|
32
|
+
assertEq(textOf(result), '[]');
|
|
33
|
+
},
|
|
34
|
+
// Regression: subjects are arbitrary strings, not constrained to a
|
|
35
|
+
// newline-free alphabet like hashes, so evo_list must not join them with
|
|
36
|
+
// '\n' — a subject containing a newline, or an empty subject, would be
|
|
37
|
+
// indistinguishable from multiple/no subjects in that format. JSON
|
|
38
|
+
// encoding preserves both exactly.
|
|
39
|
+
evoListEncodesArbitrarySubjectsAsJson: () => {
|
|
40
|
+
const c = fileCas(sha256)(home);
|
|
41
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
42
|
+
const e = evo(c)(cacheKey);
|
|
43
|
+
const [state1, addA] = virtual(state0)(e.add({ parents: [], subject: 'line one\nline two', snapshot: vecToCBase32(vec8(0x2an)) }));
|
|
44
|
+
assert(addA[0] === 'ok', ['expected add ok', addA]);
|
|
45
|
+
const [state2, addB] = virtual(state1)(e.add({ parents: [], subject: '', snapshot: vecToCBase32(vec8(0x2bn)) }));
|
|
46
|
+
assert(addB[0] === 'ok', ['expected add ok', addB]);
|
|
47
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_list');
|
|
48
|
+
const [, result] = virtual(state2)(entry.handle({}));
|
|
49
|
+
assert(!result.isError);
|
|
50
|
+
const subjects = JSON.parse(textOf(result));
|
|
51
|
+
assertEq(subjects.length, 2);
|
|
52
|
+
assert(subjects.includes('line one\nline two'), ['unexpected subjects', subjects]);
|
|
53
|
+
assert(subjects.includes(''), ['unexpected subjects', subjects]);
|
|
54
|
+
},
|
|
55
|
+
evoHeadReflectsTheCache: () => {
|
|
56
|
+
const c = fileCas(sha256)(home);
|
|
57
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
58
|
+
const e = evo(c)(cacheKey);
|
|
59
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_head');
|
|
60
|
+
const [, result] = virtual(state0)(entry.handle({ subject: 'nope' }));
|
|
61
|
+
assert(!result.isError);
|
|
62
|
+
assertEq(textOf(result), '');
|
|
63
|
+
},
|
|
64
|
+
evoHeadMissingSubjectIsInvalidArguments: () => {
|
|
65
|
+
const c = fileCas(sha256)(home);
|
|
66
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
67
|
+
const e = evo(c)(cacheKey);
|
|
68
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_head');
|
|
69
|
+
const [, result] = virtual(state0)(entry.handle({}));
|
|
70
|
+
assertEq(result.isError, true);
|
|
71
|
+
},
|
|
72
|
+
// Covers evo_add's success branch: a valid revision is stored and its
|
|
73
|
+
// hash comes back as plain, non-error text.
|
|
74
|
+
evoAddSuccessReturnsHash: () => {
|
|
75
|
+
const c = fileCas(sha256)(home);
|
|
76
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
77
|
+
const e = evo(c)(cacheKey);
|
|
78
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_add');
|
|
79
|
+
const args = { parents: [], subject: 'doc', snapshot: vecToCBase32(vec8(0x1n)) };
|
|
80
|
+
const [, result] = virtual(state0)(entry.handle(args));
|
|
81
|
+
assert(!result.isError);
|
|
82
|
+
assert(textOf(result).length > 0);
|
|
83
|
+
},
|
|
84
|
+
// Covers evo_add's error branch: a domain-level failure (Evo.add's
|
|
85
|
+
// Result) is surfaced as isError with the failure message as text.
|
|
86
|
+
evoAddDomainErrorIsError: () => {
|
|
87
|
+
const c = fileCas(sha256)(home);
|
|
88
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
89
|
+
const e = evo(c)(cacheKey);
|
|
90
|
+
const entry = findEntry(evoToolRegistry(e), 'evo_add');
|
|
91
|
+
const [, result] = virtual(state0)(entry.handle({ parents: [] }));
|
|
92
|
+
assertEq(result.isError, true);
|
|
93
|
+
assert(textOf(result).includes('subject is required'));
|
|
94
|
+
},
|
|
95
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evo API: subjects and revision heads, cached in memory over an immutable
|
|
3
|
+
* content-addressable store.
|
|
4
|
+
*
|
|
5
|
+
* A `Cas<O>` stores `vnd.fjs.revision` blobs ([`fjs/media/revision`](../../media/revision/module.f.ts))
|
|
6
|
+
* like any other content: as immutable bytes under a hash. Resolving "what
|
|
7
|
+
* are the current heads of subject X" from that store means walking every
|
|
8
|
+
* stored revision and reversing the parent links — too expensive to redo on
|
|
9
|
+
* every query. This module scans the store once into an in-memory `Cache`
|
|
10
|
+
* ([`fjs/effects/memory`](../../effects/memory/module.f.ts)) mapping subject →
|
|
11
|
+
* head hashes, then keeps the cache current as new revisions are `add`ed
|
|
12
|
+
* through it — or, for a revision stored some other way (e.g. the generic
|
|
13
|
+
* `cas_add` MCP tool), via {@link syncRevision}.
|
|
14
|
+
*
|
|
15
|
+
* A **head** of a subject is any stored revision of that subject whose hash
|
|
16
|
+
* is not referenced as a `parents` entry by another revision of the same
|
|
17
|
+
* subject (see [`fjs/media/revision/README.md`](../../media/revision/README.md)).
|
|
18
|
+
* `Cache` therefore tracks, per subject, every revision hash seen and every
|
|
19
|
+
* hash referenced as somebody's parent; heads are the set difference between
|
|
20
|
+
* the two, computed at read time ({@link headsOf}). Storing both sets rather
|
|
21
|
+
* than a running head list is what makes folding revisions truly order
|
|
22
|
+
* independent: `cas.list()` (used by {@link buildCache} to scan an existing
|
|
23
|
+
* store) returns hashes in hash order, not revision ancestry, so a child can
|
|
24
|
+
* be seen before its parent — an incremental "drop this hash from the head
|
|
25
|
+
* set, then re-add whichever hash we just saw" would wrongly resurrect the
|
|
26
|
+
* parent as a head once it is scanned after its child. Tracking the two sets
|
|
27
|
+
* separately and only subtracting at read time has no such ordering
|
|
28
|
+
* dependency: whichever order revisions are folded in, `hashes − parents`
|
|
29
|
+
* converges to the same result. {@link buildCache} and {@link addRevision}
|
|
30
|
+
* both fold through the same {@link addRevisionToCache}, the former over the
|
|
31
|
+
* whole store at once, the latter incrementally for one new revision.
|
|
32
|
+
*
|
|
33
|
+
* @module
|
|
34
|
+
*/
|
|
35
|
+
import { type Effect, type Operation } from '../../effects/module.f.ts';
|
|
36
|
+
import { type Key, type MemOp } from '../../effects/memory/module.f.ts';
|
|
37
|
+
import { type Cas } from '../module.f.ts';
|
|
38
|
+
import { type Revision } from '../../media/revision/module.f.ts';
|
|
39
|
+
import { type Result } from '../../types/result/module.f.ts';
|
|
40
|
+
import { type StringMap } from '../../types/object/module.f.ts';
|
|
41
|
+
import type { Vec } from '../../types/bit_vec/module.f.ts';
|
|
42
|
+
/** A cBase32 content hash, as accepted/returned by `Cas<O>`. */
|
|
43
|
+
export type Hash = string;
|
|
44
|
+
/** The identity of a mutable object whose revisions are being evolved. */
|
|
45
|
+
export type Subject = string;
|
|
46
|
+
/**
|
|
47
|
+
* Input to {@link addRevision}: everything the caller supplies for a new
|
|
48
|
+
* revision. Both `subject` and `snapshot` are input conveniences the write
|
|
49
|
+
* boundary resolves, because the stored `vnd.fjs.revision` blob requires
|
|
50
|
+
* them explicitly (see `fjs/media/revision`): `subject`, when omitted, is
|
|
51
|
+
* inherited from the single parent's own `subject` (see
|
|
52
|
+
* {@link resolveSubject}); `snapshot`, when omitted, is resolved from the
|
|
53
|
+
* parents (see {@link resolveSnapshot}) — the inference the format used to
|
|
54
|
+
* carry, run once here with the parents already in hand. `generation` is
|
|
55
|
+
* never an input: {@link computeGeneration} derives the authoritative value.
|
|
56
|
+
*/
|
|
57
|
+
export type AddRevision = {
|
|
58
|
+
readonly parents: readonly Hash[];
|
|
59
|
+
readonly snapshot?: Hash | undefined;
|
|
60
|
+
readonly subject?: Subject | undefined;
|
|
61
|
+
readonly archived?: true | undefined;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Per-subject bookkeeping: every revision hash seen for the subject, and
|
|
65
|
+
* every hash any of those revisions names as a parent. See the module doc
|
|
66
|
+
* for why both sets are kept (rather than a running head list) and
|
|
67
|
+
* {@link headsOf} for how heads are derived from them.
|
|
68
|
+
*/
|
|
69
|
+
export type SubjectState = {
|
|
70
|
+
readonly hashes: readonly Hash[];
|
|
71
|
+
readonly parents: readonly Hash[];
|
|
72
|
+
};
|
|
73
|
+
/** In-memory index: subject → its {@link SubjectState}. */
|
|
74
|
+
export type Cache = {
|
|
75
|
+
readonly bySubject: StringMap<string, SubjectState>;
|
|
76
|
+
};
|
|
77
|
+
/** A cache with no known subjects yet — the starting point for {@link buildCache}. */
|
|
78
|
+
export declare const emptyCache: Cache;
|
|
79
|
+
/**
|
|
80
|
+
* Decodes already-read bytes as a `vnd.fjs.revision`. Returns `null` for
|
|
81
|
+
* anything that is not a valid revision — bytes that are not valid UTF-8, or
|
|
82
|
+
* text that does not parse/validate as the dialect.
|
|
83
|
+
*/
|
|
84
|
+
export declare const decodeRevisionVec: (value: Vec) => Revision | null;
|
|
85
|
+
/**
|
|
86
|
+
* Reads and decodes the blob at `hash` as a `vnd.fjs.revision`. Returns
|
|
87
|
+
* `null` for anything that is not a valid revision — a missing hash, or (via
|
|
88
|
+
* {@link decodeRevisionVec}) bytes that are not valid UTF-8 or do not
|
|
89
|
+
* parse/validate as the dialect — so a store containing arbitrary other
|
|
90
|
+
* content can be scanned without failing the whole cache build.
|
|
91
|
+
*/
|
|
92
|
+
export declare const decodeRevisionBlob: <O extends Operation>(cas: Cas<O>) => (hash: Vec) => Effect<O, Revision | null>;
|
|
93
|
+
/**
|
|
94
|
+
* Scans every hash in `cas` and builds a fresh {@link Cache} from the
|
|
95
|
+
* `vnd.fjs.revision` blobs found among them. Non-revision blobs are ignored.
|
|
96
|
+
*/
|
|
97
|
+
export declare const buildCache: <O extends Operation>(cas: Cas<O>) => Effect<O, Cache>;
|
|
98
|
+
/** Scans `cas` once and allocates a memory slot holding the resulting {@link Cache}. */
|
|
99
|
+
export declare const initEvo: <O extends Operation>(cas: Cas<O>) => Effect<O | MemOp, Key<Cache>>;
|
|
100
|
+
/**
|
|
101
|
+
* Folds `value` — bytes already written to a `Cas` at `hash` by some other
|
|
102
|
+
* caller — into the cache at `cacheKey` if it decodes as a `vnd.fjs.revision`
|
|
103
|
+
* ({@link decodeRevisionVec}); a no-op otherwise. `cas_add`/`evo_add`
|
|
104
|
+
* (`fjs/cas/mcp`) are two ways to reach the same store — a plain `cas_add`
|
|
105
|
+
* call can store a revision blob without going through {@link addRevision},
|
|
106
|
+
* and this is what keeps the cache honest about it without rescanning the
|
|
107
|
+
* whole store.
|
|
108
|
+
*/
|
|
109
|
+
export declare const syncRevision: (cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void>;
|
|
110
|
+
/**
|
|
111
|
+
* Adds a new revision to `cas` and folds it into the cache at `cacheKey`.
|
|
112
|
+
*
|
|
113
|
+
* Steps: resolve and validate every parent ({@link resolveParents}), resolve
|
|
114
|
+
* `subject` from them ({@link resolveSubject}) and check every parent
|
|
115
|
+
* actually belongs to it ({@link validateParentSubjects}), resolve `snapshot`
|
|
116
|
+
* ({@link resolveSnapshot}) and compute `generation`
|
|
117
|
+
* ({@link computeGeneration}), assemble a `Revision` and check its hash /
|
|
118
|
+
* generation semantics (`fjs/media/revision` `checkReferences` — the same rule
|
|
119
|
+
* a reader applies; the shape itself is already guaranteed by this function's
|
|
120
|
+
* own field types), encode and write it to `cas`, then fold the new revision
|
|
121
|
+
* into the cache. Every failure — an invalid or missing parent, a
|
|
122
|
+
* cross-subject parent, an unresolvable subject or snapshot, an invalid
|
|
123
|
+
* revision, a blob too large to encode, or a store write failure — is
|
|
124
|
+
* reported as `error(message)` rather than thrown, so a caller (e.g. an MCP
|
|
125
|
+
* tool handler) can surface it without a `throw`/`catch`.
|
|
126
|
+
*/
|
|
127
|
+
export declare const addRevision: <O extends Operation>(cas: Cas<O>) => (cacheKey: Key<Cache>) => (input: AddRevision) => Effect<O | MemOp, Result<Hash, string>>;
|
|
128
|
+
/** The Evo API described in `fjs/cas/evo/README.md`, bound to a `Cas<O>` and its cache slot. */
|
|
129
|
+
export type Evo<O extends Operation> = {
|
|
130
|
+
/** Returns every subject with at least one stored revision. */
|
|
131
|
+
readonly list: () => Effect<MemOp, readonly Subject[]>;
|
|
132
|
+
/** Returns the current head hashes of `subject` (empty if unknown). */
|
|
133
|
+
readonly head: (subject: Subject) => Effect<MemOp, readonly Hash[]>;
|
|
134
|
+
/** Adds a new head; see {@link addRevision}. */
|
|
135
|
+
readonly add: (input: AddRevision) => Effect<O | MemOp, Result<Hash, string>>;
|
|
136
|
+
};
|
|
137
|
+
/** Builds the {@link Evo} API over `cas`, backed by the cache at `cacheKey` (see {@link initEvo}). */
|
|
138
|
+
export declare const evo: <O extends Operation>(cas: Cas<O>) => (cacheKey: Key<Cache>) => Evo<O>;
|