functionalscript 0.44.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +15 -0
- package/fjs/asn.1/proof.f.mjs +31 -3
- package/fjs/asserts/module.f.d.mts +14 -0
- package/fjs/asserts/module.f.mjs +20 -0
- package/fjs/asserts/proof.f.d.mts +3 -0
- package/fjs/asserts/proof.f.mjs +15 -1
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/basen/base128/proof.f.d.mts +3 -1
- package/fjs/basen/base128/proof.f.mjs +3 -1
- package/fjs/basen/base64/module.f.mjs +7 -3
- package/fjs/basen/base64/proof.f.d.mts +3 -1
- package/fjs/basen/base64/proof.f.mjs +7 -4
- package/fjs/basen/cbase32/proof.f.d.mts +3 -1
- package/fjs/basen/cbase32/proof.f.mjs +3 -1
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -4
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +34 -5
- package/fjs/bnf/descent/module.f.mjs +176 -54
- package/fjs/bnf/descent/proof.f.d.mts +3 -0
- package/fjs/bnf/descent/proof.f.mjs +189 -27
- package/fjs/bnf/descent/types.d.ts +24 -18
- package/fjs/bnf/ll1/module.f.d.mts +74 -6
- package/fjs/bnf/ll1/module.f.mjs +297 -95
- package/fjs/bnf/ll1/proof.f.d.mts +17 -2
- package/fjs/bnf/ll1/proof.f.mjs +372 -137
- package/fjs/bnf/ll1/types.d.ts +25 -27
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/module.f.d.mts +15 -6
- package/fjs/bnf/module.f.mjs +52 -11
- package/fjs/bnf/proof.f.d.mts +2 -0
- package/fjs/bnf/proof.f.mjs +79 -3
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
- package/fjs/bnf/token_symbol/module.f.mjs +7 -6
- package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
- package/fjs/bnf/token_symbol/types.d.ts +2 -2
- package/fjs/bnf/types.d.ts +10 -3
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +4 -4
- package/fjs/cas/cli/proof.f.mjs +47 -34
- package/fjs/cas/evo/module.f.d.mts +71 -31
- package/fjs/cas/evo/module.f.mjs +223 -138
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +311 -226
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +164 -176
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/common/module.f.d.mts +1 -1
- package/fjs/ci/common/module.f.mjs +1 -0
- package/fjs/ci/config/module.f.d.mts +3 -3
- package/fjs/ci/config/module.f.mjs +3 -3
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.d.mts +2 -0
- package/fjs/ci/nix/proof.f.mjs +4 -4
- package/fjs/ci/proof.f.d.mts +4 -2
- package/fjs/ci/proof.f.mjs +13 -8
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.d.mts +4 -2
- package/fjs/cli/proof.f.mjs +21 -18
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/module.f.d.mts +70 -12
- package/fjs/common/monoid/module.f.mjs +177 -14
- package/fjs/common/monoid/proof.f.d.mts +12 -1
- package/fjs/common/monoid/proof.f.mjs +88 -4
- package/fjs/common/monoid/types.d.ts +23 -0
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/secp/proof.f.d.mts +3 -1
- package/fjs/crypto/secp/proof.f.mjs +3 -1
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +4 -1
- package/fjs/crypto/sha2/proof.f.mjs +27 -1
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/crypto/vdf/module.f.d.mts +23 -4
- package/fjs/crypto/vdf/module.f.mjs +6 -4
- package/fjs/dev/module.f.d.mts +17 -5
- package/fjs/dev/module.f.mjs +60 -30
- package/fjs/dev/update/module.f.d.mts +11 -3
- package/fjs/dev/update/module.f.mjs +16 -11
- package/fjs/dev/update/proof.f.d.mts +4 -3
- package/fjs/dev/update/proof.f.mjs +11 -7
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +16 -3
- package/fjs/djs/parser/module.f.mjs +135 -16
- package/fjs/djs/parser/proof.f.d.mts +8 -1
- package/fjs/djs/parser/proof.f.mjs +287 -13
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +20 -1
- package/fjs/djs/proof.f.mjs +190 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +66 -19
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +120 -73
- package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
- package/fjs/djs/tokenizer/proof.f.mjs +86 -67
- package/fjs/djs/transpiler/module.f.d.mts +13 -19
- package/fjs/djs/transpiler/module.f.mjs +79 -72
- package/fjs/djs/transpiler/types.d.ts +29 -0
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +23 -12
- package/fjs/effects/list/module.f.mjs +16 -12
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +6 -3
- package/fjs/effects/memory/module.f.mjs +7 -7
- package/fjs/effects/memory/proof.f.d.mts +4 -0
- package/fjs/effects/memory/proof.f.mjs +18 -9
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +28 -4
- package/fjs/effects/mock/module.f.mjs +39 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +12 -2
- package/fjs/effects/module.f.d.mts +469 -281
- package/fjs/effects/module.f.mjs +538 -299
- package/fjs/effects/module.mjs +11 -2
- package/fjs/effects/node/memory/module.d.mts +7 -2
- package/fjs/effects/node/memory/module.mjs +9 -5
- package/fjs/effects/node/memory/proof.d.mts +2 -0
- package/fjs/effects/node/memory/proof.mjs +12 -5
- package/fjs/effects/node/module.d.mts +8 -2
- package/fjs/effects/node/module.f.d.mts +183 -43
- package/fjs/effects/node/module.f.mjs +260 -62
- package/fjs/effects/node/module.mjs +61 -50
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +21 -4
- package/fjs/effects/node/virtual/module.f.mjs +113 -70
- package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
- package/fjs/effects/node/virtual/proof.f.mjs +201 -8
- package/fjs/effects/proof.f.d.mts +69 -34
- package/fjs/effects/proof.f.mjs +413 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/all.test.d.mts +8 -0
- package/fjs/emergent_testing/all.test.mjs +14 -0
- package/fjs/emergent_testing/module.f.d.mts +22 -10
- package/fjs/emergent_testing/module.f.mjs +119 -85
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +169 -35
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsc/bnf.f.d.mts +3 -0
- package/fjs/fsc/bnf.f.mjs +4 -1
- package/fjs/fsc/json.f.d.mts +3 -0
- package/fjs/fsc/json.f.mjs +4 -1
- package/fjs/fsc/module.f.d.mts +9 -0
- package/fjs/fsc/module.f.mjs +5 -3
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +5 -0
- package/fjs/fsm/proof.f.mjs +87 -115
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +30 -3
- package/fjs/js/tokenizer/module.f.mjs +161 -211
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +39 -4
- package/fjs/mcp/module.f.mjs +14 -12
- package/fjs/mcp/proof.f.d.mts +13 -1
- package/fjs/mcp/proof.f.mjs +120 -61
- package/fjs/media/html/module.f.d.mts +12 -0
- package/fjs/media/html/module.f.mjs +7 -5
- package/fjs/media/html/proof.f.d.mts +3 -0
- package/fjs/media/html/proof.f.mjs +4 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +133 -72
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +38 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.d.mts +3 -0
- package/fjs/media/json/rtti/proof.f.mjs +12 -12
- package/fjs/media/json/schema/module.f.d.mts +61 -27
- package/fjs/media/json/schema/module.f.mjs +218 -63
- package/fjs/media/json/schema/proof.f.d.mts +41 -1
- package/fjs/media/json/schema/proof.f.mjs +220 -9
- package/fjs/media/json/serializer/module.f.d.mts +44 -0
- package/fjs/media/json/serializer/module.f.mjs +71 -9
- package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
- package/fjs/media/json/tokenizer/module.f.mjs +31 -8
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/nix/module.f.d.mts +13 -0
- package/fjs/media/nix/module.f.mjs +4 -2
- package/fjs/media/nix/proof.f.d.mts +3 -0
- package/fjs/media/nix/proof.f.mjs +4 -1
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +83 -7
- package/fjs/media/revision/module.f.mjs +127 -23
- package/fjs/media/revision/proof.f.d.mts +14 -0
- package/fjs/media/revision/proof.f.mjs +93 -2
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +53 -18
- package/fjs/media/type/module.f.mjs +87 -97
- package/fjs/media/type/proof.f.d.mts +17 -0
- package/fjs/media/type/proof.f.mjs +73 -13
- package/fjs/module.d.mts +5 -0
- package/fjs/module.f.d.mts +8 -0
- package/fjs/module.f.mjs +33 -10
- package/fjs/module.mjs +6 -0
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/path/module.f.d.mts +8 -0
- package/fjs/path/module.f.mjs +4 -2
- package/fjs/proof.f.d.mts +7 -3
- package/fjs/proof.f.mjs +41 -12
- package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
- package/fjs/protocol/json_rpc/module.f.mjs +10 -7
- package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
- package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +16 -3
- package/fjs/protocol/mcp/proof.f.mjs +224 -69
- package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
- package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
- package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
- package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +4 -0
- package/fjs/sul/id/module.f.mjs +6 -6
- package/fjs/sul/level/hash/module.f.d.mts +4 -1
- package/fjs/sul/level/hash/module.f.mjs +6 -4
- package/fjs/sul/level/hash/proof.f.d.mts +4 -0
- package/fjs/sul/level/hash/proof.f.mjs +7 -4
- package/fjs/sul/level/literal/module.f.d.mts +4 -1
- package/fjs/sul/level/literal/module.f.mjs +4 -3
- package/fjs/sul/level/literal/proof.f.d.mts +3 -0
- package/fjs/sul/level/literal/proof.f.mjs +4 -1
- package/fjs/sul/module.f.d.mts +5 -3
- package/fjs/sul/module.f.mjs +23 -17
- package/fjs/sul/proof.f.d.mts +4 -0
- package/fjs/sul/proof.f.mjs +5 -2
- package/fjs/text/ascii/module.f.d.mts +26 -0
- package/fjs/text/ascii/module.f.mjs +49 -1
- package/fjs/text/ascii/proof.f.d.mts +10 -0
- package/fjs/text/ascii/proof.f.mjs +33 -1
- package/fjs/text/code_point/module.f.d.mts +29 -3
- package/fjs/text/code_point/module.f.mjs +32 -9
- package/fjs/text/code_point/proof.f.d.mts +2 -0
- package/fjs/text/code_point/proof.f.mjs +39 -0
- package/fjs/text/module.f.d.mts +4 -2
- package/fjs/text/module.f.mjs +4 -3
- package/fjs/text/proof.f.d.mts +3 -0
- package/fjs/text/proof.f.mjs +4 -1
- package/fjs/text/sgr/module.f.d.mts +6 -5
- package/fjs/text/sgr/module.f.mjs +8 -8
- package/fjs/text/sgr/proof.f.d.mts +3 -0
- package/fjs/text/sgr/proof.f.mjs +4 -1
- package/fjs/text/utf16/module.f.d.mts +5 -1
- package/fjs/text/utf16/module.f.mjs +38 -35
- package/fjs/text/utf16/proof.f.d.mts +3 -1
- package/fjs/text/utf16/proof.f.mjs +19 -2
- package/fjs/text/utf8/module.f.d.mts +9 -5
- package/fjs/text/utf8/module.f.mjs +20 -20
- package/fjs/types/array/module.f.d.mts +2 -1
- package/fjs/types/array/module.f.mjs +16 -4
- package/fjs/types/bigfloat/module.f.d.mts +21 -1
- package/fjs/types/bigfloat/module.f.mjs +33 -7
- package/fjs/types/bigfloat/proof.f.d.mts +1 -0
- package/fjs/types/bigfloat/proof.f.mjs +46 -0
- package/fjs/types/bigint/module.f.d.mts +4 -0
- package/fjs/types/bigint/module.f.mjs +4 -3
- package/fjs/types/bit_vec/module.f.d.mts +10 -16
- package/fjs/types/bit_vec/module.f.mjs +99 -95
- package/fjs/types/bit_vec/proof.f.d.mts +6 -0
- package/fjs/types/bit_vec/proof.f.mjs +31 -5
- package/fjs/types/btree/find/module.f.d.mts +5 -1
- package/fjs/types/btree/find/module.f.mjs +5 -5
- package/fjs/types/btree/find/proof.f.d.mts +5 -1
- package/fjs/types/btree/find/proof.f.mjs +5 -3
- package/fjs/types/btree/module.f.d.mts +3 -0
- package/fjs/types/btree/module.f.mjs +3 -2
- package/fjs/types/btree/proof.f.d.mts +5 -1
- package/fjs/types/btree/proof.f.mjs +5 -3
- package/fjs/types/btree/remove/module.f.d.mts +11 -0
- package/fjs/types/btree/remove/module.f.mjs +10 -10
- package/fjs/types/btree/remove/proof.f.d.mts +3 -0
- package/fjs/types/btree/remove/proof.f.mjs +4 -1
- package/fjs/types/btree/set/module.f.d.mts +9 -0
- package/fjs/types/btree/set/module.f.mjs +14 -17
- package/fjs/types/btree/set/proof.f.d.mts +3 -0
- package/fjs/types/btree/set/proof.f.mjs +16 -1
- package/fjs/types/btree/types/module.f.d.mts +2 -1
- package/fjs/types/btree/types/module.f.mjs +2 -1
- package/fjs/types/byte_set/module.f.d.mts +20 -4
- package/fjs/types/byte_set/module.f.mjs +18 -8
- package/fjs/types/byte_set/proof.f.d.mts +3 -1
- package/fjs/types/byte_set/proof.f.mjs +10 -8
- package/fjs/types/function/compare/module.f.d.mts +3 -2
- package/fjs/types/function/compare/module.f.mjs +13 -5
- package/fjs/types/function/module.f.d.mts +8 -1
- package/fjs/types/function/module.f.mjs +8 -1
- package/fjs/types/function/operator/module.f.d.mts +2 -1
- package/fjs/types/function/operator/module.f.mjs +2 -2
- package/fjs/types/list/module.f.d.mts +10 -3
- package/fjs/types/list/module.f.mjs +6 -4
- package/fjs/types/list/proof.f.d.mts +4 -1
- package/fjs/types/list/proof.f.mjs +4 -2
- package/fjs/types/nibble_set/module.f.d.mts +2 -1
- package/fjs/types/nibble_set/module.f.mjs +2 -2
- package/fjs/types/nominal/module.f.d.mts +2 -1
- package/fjs/types/nominal/module.f.mjs +2 -1
- package/fjs/types/nullable/module.f.d.mts +26 -6
- package/fjs/types/nullable/module.f.mjs +25 -6
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/number/module.f.d.mts +4 -0
- package/fjs/types/number/module.f.mjs +4 -3
- package/fjs/types/object/module.f.d.mts +26 -4
- package/fjs/types/object/module.f.mjs +26 -7
- package/fjs/types/object/proof.f.d.mts +5 -2
- package/fjs/types/object/proof.f.mjs +6 -3
- package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
- package/fjs/types/object/structurally_same/module.f.mjs +59 -0
- package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
- package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
- package/fjs/types/ordered_map/module.f.d.mts +5 -0
- package/fjs/types/ordered_map/module.f.mjs +5 -4
- package/fjs/types/ordered_map/proof.f.d.mts +3 -0
- package/fjs/types/ordered_map/proof.f.mjs +4 -1
- package/fjs/types/patricia_trie/module.f.d.mts +2 -1
- package/fjs/types/patricia_trie/module.f.mjs +27 -12
- package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
- package/fjs/types/patricia_trie/proof.f.mjs +4 -1
- package/fjs/types/prime_field/module.f.d.mts +3 -1
- package/fjs/types/prime_field/module.f.mjs +3 -2
- package/fjs/types/range/module.f.d.mts +2 -1
- package/fjs/types/range/module.f.mjs +2 -2
- package/fjs/types/range_map/module.f.d.mts +6 -0
- package/fjs/types/range_map/module.f.mjs +6 -9
- package/fjs/types/range_map/proof.f.d.mts +5 -1
- package/fjs/types/range_map/proof.f.mjs +5 -3
- package/fjs/types/range_set/module.f.d.mts +5 -0
- package/fjs/types/range_set/module.f.mjs +1 -0
- package/fjs/types/range_set/proof.f.d.mts +3 -0
- package/fjs/types/range_set/proof.f.mjs +4 -1
- package/fjs/types/result/module.d.mts +8 -0
- package/fjs/types/result/module.f.d.mts +37 -7
- package/fjs/types/result/module.f.mjs +38 -8
- package/fjs/types/result/module.mjs +9 -1
- package/fjs/types/result/proof.f.d.mts +5 -0
- package/fjs/types/result/proof.f.mjs +22 -2
- package/fjs/types/rtti/common/module.f.d.mts +44 -14
- package/fjs/types/rtti/common/module.f.mjs +42 -36
- package/fjs/types/rtti/common/proof.f.d.mts +4 -0
- package/fjs/types/rtti/common/proof.f.mjs +10 -7
- package/fjs/types/rtti/data/module.f.d.mts +134 -0
- package/fjs/types/rtti/data/module.f.mjs +1053 -0
- package/fjs/types/rtti/data/proof.f.d.mts +76 -0
- package/fjs/types/rtti/data/proof.f.mjs +589 -0
- package/fjs/types/rtti/data/types.d.ts +83 -0
- package/fjs/types/rtti/module.f.d.mts +12 -5
- package/fjs/types/rtti/module.f.mjs +7 -5
- package/fjs/types/rtti/parse/module.f.d.mts +48 -0
- package/fjs/types/rtti/parse/module.f.mjs +45 -34
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +51 -52
- package/fjs/types/rtti/proof.f.d.mts +3 -1
- package/fjs/types/rtti/proof.f.mjs +6 -2
- package/fjs/types/rtti/ts/module.f.d.mts +68 -9
- package/fjs/types/rtti/ts/module.f.mjs +258 -30
- package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
- package/fjs/types/rtti/ts/proof.f.mjs +152 -4
- package/fjs/types/rtti/ts/types.d.ts +25 -1
- package/fjs/types/rtti/types.d.ts +40 -0
- package/fjs/types/sorted_list/module.f.d.mts +4 -1
- package/fjs/types/sorted_list/module.f.mjs +21 -12
- package/fjs/types/sorted_list/proof.f.d.mts +3 -1
- package/fjs/types/sorted_list/proof.f.mjs +3 -1
- package/fjs/types/sorted_set/module.f.d.mts +49 -1
- package/fjs/types/sorted_set/module.f.mjs +26 -2
- package/fjs/types/sorted_set/proof.f.d.mts +4 -1
- package/fjs/types/sorted_set/proof.f.mjs +19 -2
- package/fjs/types/string/module.f.d.mts +4 -0
- package/fjs/types/string/module.f.mjs +4 -3
- package/fjs/types/string_set/module.f.d.mts +3 -1
- package/fjs/types/string_set/module.f.mjs +3 -2
- package/fjs/types/ts/module.f.d.mts +2 -0
- package/fjs/types/ts/module.f.mjs +3 -3
- package/fjs/types/ts/proof.f.d.mts +1 -0
- package/fjs/types/ts/proof.f.mjs +5 -0
- package/fjs/types/ts/types.d.ts +6 -1
- package/fjs/types/uint8array/module.f.d.mts +13 -2
- package/fjs/types/uint8array/module.f.mjs +20 -15
- package/fjs/website/module.f.d.mts +5 -2
- package/fjs/website/module.f.mjs +6 -8
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +3 -3
- package/fjs/asn.1/types.js +0 -6
- package/fjs/asserts/types.js +0 -6
- package/fjs/basen/types.js +0 -6
- package/fjs/bnf/data/types.js +0 -6
- package/fjs/bnf/descent/types.js +0 -6
- package/fjs/bnf/ll1/types.js +0 -6
- package/fjs/bnf/token_symbol/types.js +0 -6
- package/fjs/bnf/types.js +0 -6
- package/fjs/cas/evo/types.js +0 -7
- package/fjs/cas/types.js +0 -6
- package/fjs/ci/common/types.js +0 -1
- package/fjs/ci/nix/types.js +0 -6
- package/fjs/ci/types.js +0 -6
- package/fjs/cli/types.js +0 -6
- package/fjs/common/monoid/types.js +0 -6
- package/fjs/crypto/pow/types.js +0 -6
- package/fjs/crypto/secp/types.js +0 -6
- package/fjs/crypto/sha2/types.js +0 -6
- package/fjs/crypto/sign/types.js +0 -6
- package/fjs/crypto/vdf/types.js +0 -6
- package/fjs/dev/package_json/module.f.d.mts +0 -32
- package/fjs/dev/package_json/module.f.mjs +0 -37
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/dev/types.js +0 -6
- package/fjs/djs/ast/types.js +0 -8
- package/fjs/djs/parser/types.js +0 -7
- package/fjs/djs/tokenizer/types.js +0 -7
- package/fjs/djs/types.js +0 -7
- package/fjs/effects/eff/module.f.d.mts +0 -10
- package/fjs/effects/eff/module.f.mjs +0 -68
- package/fjs/effects/eff/proof.f.d.mts +0 -12
- package/fjs/effects/eff/proof.f.mjs +0 -66
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/effects/eff/types.js +0 -6
- package/fjs/effects/list/types.js +0 -6
- package/fjs/effects/memory/types.js +0 -6
- package/fjs/effects/mock/types.js +0 -6
- package/fjs/effects/node/types.js +0 -6
- package/fjs/effects/node/virtual/types.js +0 -7
- package/fjs/effects/types.js +0 -6
- package/fjs/emergent_testing/all.test.d.ts +0 -1
- package/fjs/emergent_testing/all.test.js +0 -5
- package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
- package/fjs/emergent_testing/scenarios/all.js +0 -1
- package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
- package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
- package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
- package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
- package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
- package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
- package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
- package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
- package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
- package/fjs/emergent_testing/types.js +0 -6
- package/fjs/js/tokenizer/types.js +0 -6
- package/fjs/media/html/types.js +0 -6
- package/fjs/media/json/parser/types.js +0 -6
- package/fjs/media/json/tokenizer/types.js +0 -6
- package/fjs/media/json/types.js +0 -13
- package/fjs/media/nix/types.js +0 -6
- package/fjs/media/revision/types.js +0 -8
- package/fjs/media/type/types.js +0 -6
- package/fjs/media/types.js +0 -7
- package/fjs/nanvm/types.js +0 -11
- package/fjs/protocol/json_rpc/types.js +0 -8
- package/fjs/protocol/mcp/types.js +0 -8
- package/fjs/sul/id/types.js +0 -6
- package/fjs/sul/level/hash/types.js +0 -6
- package/fjs/sul/level/literal/types.js +0 -6
- package/fjs/sul/types.js +0 -6
- package/fjs/text/sgr/types.js +0 -6
- package/fjs/text/types.js +0 -6
- package/fjs/text/utf16/types.js +0 -6
- package/fjs/text/utf8/types.js +0 -6
- package/fjs/types/array/types.js +0 -6
- package/fjs/types/bigfloat/types.js +0 -6
- package/fjs/types/bigint/types.js +0 -6
- package/fjs/types/bit_vec/types.js +0 -6
- package/fjs/types/btree/find/types.js +0 -6
- package/fjs/types/btree/types/types.js +0 -6
- package/fjs/types/byte_set/types.js +0 -6
- package/fjs/types/function/compare/types.js +0 -6
- package/fjs/types/function/operator/types.js +0 -6
- package/fjs/types/function/types.js +0 -6
- package/fjs/types/list/types.js +0 -6
- package/fjs/types/nibble_set/types.js +0 -6
- package/fjs/types/nominal/types.js +0 -6
- package/fjs/types/nullable/types.js +0 -6
- package/fjs/types/object/types.js +0 -8
- package/fjs/types/option/types.js +0 -6
- package/fjs/types/ordered_map/types.js +0 -6
- package/fjs/types/patricia_trie/types.js +0 -6
- package/fjs/types/phantom/types.js +0 -11
- package/fjs/types/prime_field/types.js +0 -6
- package/fjs/types/range/types.js +0 -6
- package/fjs/types/range_map/types.js +0 -6
- package/fjs/types/result/types.js +0 -6
- package/fjs/types/rtti/common/types.js +0 -1
- package/fjs/types/rtti/parse/types.js +0 -1
- package/fjs/types/rtti/ts/types.js +0 -1
- package/fjs/types/rtti/types.js +0 -1
- package/fjs/types/rtti/validate/module.f.d.mts +0 -6
- package/fjs/types/rtti/validate/module.f.mjs +0 -169
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
- package/fjs/types/rtti/validate/types.js +0 -1
- package/fjs/types/sorted_list/types.js +0 -6
- package/fjs/types/sorted_set/types.js +0 -6
- package/fjs/types/string_set/types.js +0 -6
- package/fjs/types/ts/types.js +0 -8
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { assert, assertEq } from '../../asserts/module.f.mjs'
|
|
2
|
+
import { dialect, mediaType, decodeText, encodeText, noteDialect, priorities, validate } from './module.f.mjs'
|
|
3
|
+
import { dialect as lockDialect } from '../lock/module.f.mjs'
|
|
4
|
+
|
|
5
|
+
export const proof = {
|
|
6
|
+
dialectAndMediaType: () => {
|
|
7
|
+
assertEq(dialect, 'vnd.fjs.note')
|
|
8
|
+
assertEq(mediaType, 'application/vnd.fjs.note+json')
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
// The published scale, most urgent first — `todo/README.md`'s vocabulary.
|
|
12
|
+
priorityScale: () => {
|
|
13
|
+
assertEq(priorities.join(','), 'P1,P2,P3,P4,P5')
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
validate: {
|
|
17
|
+
// The ordinary case: the tag and the text.
|
|
18
|
+
minimalNoteAccepted: () => {
|
|
19
|
+
const r = validate({ dialect, text: 'buy milk' })
|
|
20
|
+
assert(r[0] === 'ok', ['expected ok', r])
|
|
21
|
+
assertEq(r[1].text, 'buy milk')
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// `text` may be empty — required rather than optional, so an absent
|
|
25
|
+
// text and an empty one are not two spellings of one blob.
|
|
26
|
+
emptyTextAccepted: () => {
|
|
27
|
+
const [t] = validate({ dialect, text: '' })
|
|
28
|
+
assertEq(t, 'ok')
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// `text` is required: a blob carrying only the tag is not a note.
|
|
32
|
+
missingTextRejected: () => {
|
|
33
|
+
const [t] = validate({ dialect })
|
|
34
|
+
assertEq(t, 'error')
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// The text is a string, nothing else.
|
|
38
|
+
nonStringTextRejected: () => {
|
|
39
|
+
const [t] = validate({ dialect, text: 42 })
|
|
40
|
+
assertEq(t, 'error')
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// Dependencies are subject identity strings, unconstrained like
|
|
44
|
+
// `vnd.fjs.revision`'s `subject` — no semantic check applies. The
|
|
45
|
+
// text may reference them by index (`[0]`, `[1]`), which is a
|
|
46
|
+
// reading convention, not a validation rule: this blob validates the
|
|
47
|
+
// same with any text.
|
|
48
|
+
dependenciesAccepted: () => {
|
|
49
|
+
const r = validate({ dialect, text: 'ship it once [0] and [1] land', dependencies: ['write the spec', 'review'] })
|
|
50
|
+
assert(r[0] === 'ok', ['expected ok', r])
|
|
51
|
+
assertEq(r[1].dependencies?.length, 2)
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// `[]` and an absent field both say "depends on nothing"; the format
|
|
55
|
+
// does not distinguish them, and both validate.
|
|
56
|
+
emptyDependenciesAccepted: () => {
|
|
57
|
+
const [t] = validate({ dialect, text: 'hi', dependencies: [] })
|
|
58
|
+
assertEq(t, 'ok')
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// The field is a list of strings, nothing else.
|
|
62
|
+
nonArrayDependenciesRejected: () => {
|
|
63
|
+
const [t] = validate({ dialect, text: 'hi', dependencies: 'write the spec' })
|
|
64
|
+
assertEq(t, 'error')
|
|
65
|
+
},
|
|
66
|
+
nonStringDependencyRejected: () => {
|
|
67
|
+
const [t] = validate({ dialect, text: 'hi', dependencies: [42] })
|
|
68
|
+
assertEq(t, 'error')
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// A priority is one of the closed `priorities` literals — the
|
|
72
|
+
// author's urgency decision, enforced entirely structurally.
|
|
73
|
+
priorityAccepted: () => {
|
|
74
|
+
const r = validate({ dialect, text: 'fix the build', priority: 'P1' })
|
|
75
|
+
assert(r[0] === 'ok', ['expected ok', r])
|
|
76
|
+
assertEq(r[1].priority, 'P1')
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// The scale is closed: an unknown rank fails structurally rather than
|
|
80
|
+
// passing as a free-form string — the fail-closed widening path.
|
|
81
|
+
unknownPriorityRejected: () => {
|
|
82
|
+
const [t] = validate({ dialect, text: 'hi', priority: 'P0' })
|
|
83
|
+
assertEq(t, 'error')
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// The rank is a literal, not a number: `1` is not `'P1'`.
|
|
87
|
+
numericPriorityRejected: () => {
|
|
88
|
+
const [t] = validate({ dialect, text: 'hi', priority: 1 })
|
|
89
|
+
assertEq(t, 'error')
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// rtti structs are open, so unknown fields are ignored rather than
|
|
93
|
+
// rejected — the additive forward-compatibility path every future
|
|
94
|
+
// extension (title, tags, dates, …) relies on.
|
|
95
|
+
unknownFieldsIgnored: () => {
|
|
96
|
+
const [t] = validate({ dialect, text: 'call Bob', title: 'todo', done: true })
|
|
97
|
+
assertEq(t, 'ok')
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// Another dialect's blob is not a note: the tag is matched as an
|
|
101
|
+
// exact literal.
|
|
102
|
+
otherDialectRejected: () => {
|
|
103
|
+
const [t] = validate({ dialect: lockDialect, text: 'hi' })
|
|
104
|
+
assertEq(t, 'error')
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
decodeText: {
|
|
109
|
+
validJson: () => {
|
|
110
|
+
const r = decodeText(`{"dialect":"${dialect}","text":"buy milk"}`)
|
|
111
|
+
assert(r[0] === 'ok', ['expected ok', r])
|
|
112
|
+
assertEq(r[1].text, 'buy milk')
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
// Key order carries no meaning: the JSON is parsed and the parsed
|
|
116
|
+
// value validated, so `dialect` need not come first.
|
|
117
|
+
keyOrderIndependent: () => {
|
|
118
|
+
const [t] = decodeText(`{"text":"hi","dialect":"${dialect}"}`)
|
|
119
|
+
assertEq(t, 'ok')
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
malformedJsonRejected: () => {
|
|
123
|
+
const [t] = decodeText('{not json')
|
|
124
|
+
assertEq(t, 'error')
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
ordinaryJsonRejected: () => {
|
|
128
|
+
const [t] = decodeText('{"hello":"world"}')
|
|
129
|
+
assertEq(t, 'error')
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
encodeText: {
|
|
134
|
+
// Two blobs differing only in property order converge on one byte
|
|
135
|
+
// sequence, so they address the same CAS blob. `dependencies` sorts
|
|
136
|
+
// ahead of `dialect`, and its array order is preserved — arrays retain
|
|
137
|
+
// their declared order under canonical serialization.
|
|
138
|
+
sortsPropertiesLexicographically: () => {
|
|
139
|
+
const decoded = decodeText(`{"text":"hi","dependencies":["b","a"],"dialect":"${dialect}"}`)
|
|
140
|
+
assert(decoded[0] === 'ok', ['expected ok', decoded])
|
|
141
|
+
assertEq(encodeText(decoded[1]), `{"dependencies":["b","a"],"dialect":"${dialect}","text":"hi"}`)
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
// The registry entry carries the schema's own tag; matching is exercised
|
|
146
|
+
// end to end through `detect` in `fjs/media/proof.f.mjs`.
|
|
147
|
+
noteDialectTag: () => {
|
|
148
|
+
assertEq(noteDialect.dialect, dialect)
|
|
149
|
+
},
|
|
150
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level API for `fjs/media/note/module.f.mjs`: `Note` and `NoteError`.
|
|
3
|
+
*/
|
|
4
|
+
import type { ValidationError } from '../../types/rtti/common/types.ts';
|
|
5
|
+
import type { Ts } from '../../types/rtti/ts/types.ts';
|
|
6
|
+
import type { noteSchema } from './module.f.mjs';
|
|
7
|
+
/** The TypeScript type derived from `noteSchema` — the single source of truth. */
|
|
8
|
+
export type Note = Ts<typeof noteSchema>;
|
|
9
|
+
/** Either a structural validation error or a JSON parse error message. */
|
|
10
|
+
export type NoteError = ValidationError | string;
|
package/fjs/media/proof.f.d.mts
CHANGED
|
@@ -4,7 +4,10 @@ export declare const proof: {
|
|
|
4
4
|
keyOrderIndependent: () => void;
|
|
5
5
|
invalidRevisionFallsThrough: () => void;
|
|
6
6
|
nonHashSnapshotFallsThrough: () => void;
|
|
7
|
-
|
|
7
|
+
validLock: () => void;
|
|
8
|
+
lockAndRevisionDoNotOverlap: () => void;
|
|
9
|
+
nonHashLockValueFallsThrough: () => void;
|
|
10
|
+
validNote: () => void;
|
|
8
11
|
nonVndDialectName: () => void;
|
|
9
12
|
firstMatchWins: () => void;
|
|
10
13
|
noDialects: () => void;
|
package/fjs/media/proof.f.mjs
CHANGED
|
@@ -6,6 +6,8 @@ import { assertEq } from '../asserts/module.f.mjs'
|
|
|
6
6
|
import { msb, u8ListToVec, repeat, vec8 } from '../types/bit_vec/module.f.mjs'
|
|
7
7
|
import { detect, dialectEntry } from './module.f.mjs'
|
|
8
8
|
import { dialect, revisionDialect } from './revision/module.f.mjs'
|
|
9
|
+
import { dialect as lockDialectName, lockDialect } from './lock/module.f.mjs'
|
|
10
|
+
import { dialect as noteDialectName, noteDialect } from './note/module.f.mjs'
|
|
9
11
|
import { number, string } from '../types/rtti/module.f.mjs'
|
|
10
12
|
|
|
11
13
|
// All test strings here are ASCII, so char code === UTF-8 byte value.
|
|
@@ -14,22 +16,12 @@ const utf8Bytes = s => u8ListToVec(msb)([...s].map(c => c.charCodeAt(0)))
|
|
|
14
16
|
|
|
15
17
|
const revisionJson = `{"dialect":"${dialect}","subject":"8","parents":[],"snapshot":"8","generation":0}`
|
|
16
18
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const detectRevision = detect(dialects)
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* A second dialect following the same `vnd.fjs.<name>` convention, registered
|
|
24
|
-
* with no refinement: structure alone decides the match.
|
|
19
|
+
/** The three dialects `fjs/media` itself ships, in the order `fjs/mcp` registers them.
|
|
20
|
+
* @type {readonly DialectEntry[]}
|
|
25
21
|
*/
|
|
26
|
-
const
|
|
27
|
-
dialect: 'vnd.fjs.note',
|
|
28
|
-
text: string,
|
|
29
|
-
})
|
|
22
|
+
const dialects = [revisionDialect, lockDialect, noteDialect]
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
const noteDialect = dialectEntry(noteSchema)
|
|
24
|
+
const detectRevision = detect(dialects)
|
|
33
25
|
|
|
34
26
|
/** A dialect name outside `vnd.fjs.*` — registerable, and detected as itself. */
|
|
35
27
|
const gadgetSchema = /** @type {const} */ ({
|
|
@@ -83,14 +75,41 @@ export const proof = {
|
|
|
83
75
|
assertEq(m.mime_type, 'text/plain')
|
|
84
76
|
},
|
|
85
77
|
|
|
86
|
-
// A
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
assertEq(
|
|
91
|
-
assertEq(
|
|
78
|
+
// A valid shared-lock blob is recognized as its own dialect, alongside the
|
|
79
|
+
// revision one, and reported under the derived media type.
|
|
80
|
+
validLock: () => {
|
|
81
|
+
const m = detectRevision(utf8Bytes(`{"dialect":"${lockDialectName}","lock":{"dependency":"8"}}`))
|
|
82
|
+
assertEq(m.type, 'text')
|
|
83
|
+
assertEq(m.mime_type, 'application/vnd.fjs.lock+json')
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// The two dialects never claim each other's blobs: each schema matches its
|
|
87
|
+
// own `dialect` literal, so a revision carrying an inline `lock` is still a
|
|
88
|
+
// revision, and a lock blob is never a revision.
|
|
89
|
+
lockAndRevisionDoNotOverlap: () => {
|
|
90
|
+
const withLock = `{"dialect":"${dialect}","subject":"8","parents":[],"snapshot":"8","generation":0,"lock":{"d":"8"}}`
|
|
91
|
+
assertEq(detectRevision(utf8Bytes(withLock)).mime_type, 'application/vnd.fjs.revision+json')
|
|
92
|
+
assertEq(detectRevision(utf8Bytes(revisionJson)).mime_type, 'application/vnd.fjs.revision+json')
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// `lockDialect` carries the semantic check too: a structurally valid lock
|
|
96
|
+
// blob whose binding is not a cbase32 hash is not detected as one, exactly
|
|
97
|
+
// as its `decodeText` would say.
|
|
98
|
+
nonHashLockValueFallsThrough: () => {
|
|
99
|
+
const text = `{"dialect":"${lockDialectName}","lock":{"dependency":"not a hash"}}`
|
|
100
|
+
const m = detectRevision(utf8Bytes(text))
|
|
101
|
+
assertEq(m.type, 'text')
|
|
102
|
+
assertEq(m.mime_type, 'text/plain')
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// The note dialect is registered with no refinement, so structure alone
|
|
106
|
+
// decides the match — a valid note is recognized alongside its siblings.
|
|
107
|
+
validNote: () => {
|
|
108
|
+
const m = detectRevision(utf8Bytes(`{"dialect":"${noteDialectName}","text":"hi"}`))
|
|
109
|
+
assertEq(m.type, 'text')
|
|
110
|
+
assertEq(m.mime_type, 'application/vnd.fjs.note+json')
|
|
92
111
|
// Same tag, wrong shape: no entry matches.
|
|
93
|
-
assertEq(
|
|
112
|
+
assertEq(detectRevision(utf8Bytes(`{"dialect":"${noteDialectName}","text":42}`)).mime_type, 'text/plain')
|
|
94
113
|
},
|
|
95
114
|
|
|
96
115
|
// The name is neither grammar-checked nor allowlisted: a dialect outside
|
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
* @import { Unknown } from '../json/types.ts'
|
|
18
18
|
* @import { Result } from '../../types/result/types.ts'
|
|
19
19
|
* @import { DialectEntry } from '../types.ts'
|
|
20
|
-
* @import {
|
|
20
|
+
* @import { String as RttiString } from '../../types/rtti/types.ts'
|
|
21
|
+
* @import { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts'
|
|
21
22
|
*/
|
|
22
23
|
import type { Unknown } from '../json/types.ts';
|
|
23
24
|
import type { Result } from '../../types/result/types.ts';
|
|
24
25
|
import type { DialectEntry } from '../types.ts';
|
|
25
|
-
import type { Revision, RevisionError } from './types.ts';
|
|
26
|
+
import type { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts';
|
|
26
27
|
/**
|
|
27
28
|
* Format tag: names the dialect of this BLOB. The media type it is served
|
|
28
29
|
* with is derived mechanically: `application/` + `dialect` + `+json`.
|
|
@@ -40,8 +41,52 @@ export declare const mediaType: "application/vnd.fjs.revision+json";
|
|
|
40
41
|
* not by this schema on its own.
|
|
41
42
|
*/
|
|
42
43
|
export declare const hash: import("../../types/rtti/types.ts")._Type0<"string">;
|
|
43
|
-
/**
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* rtti schema for a lock map: an open map whose every value is either a
|
|
46
|
+
* direct hash string or a nested lock map, to any depth.
|
|
47
|
+
*
|
|
48
|
+
* Self-referential through {@link lockValue}, which is a module-level
|
|
49
|
+
* constant rather than a union rebuilt inside the thunk: the rtti data form
|
|
50
|
+
* (`fjs/types/rtti/data`, which `toJsonSchema` routes through) closes
|
|
51
|
+
* reference cycles by *identity*, so a schema handing out a fresh union thunk
|
|
52
|
+
* on every call would present an infinite graph and never terminate.
|
|
53
|
+
*
|
|
54
|
+
* The named `@type` — rather than `@type {const}` — is what a self-referential
|
|
55
|
+
* schema needs twice over: a `const` cannot reference itself in its own
|
|
56
|
+
* initializer at all, and naming the recursive position is also what keeps
|
|
57
|
+
* declaration emit from inlining the structure and giving up at depth (see
|
|
58
|
+
* `fjs/AGENTS.md` §3.2 and `../json/rtti/module.f.mjs`).
|
|
59
|
+
*
|
|
60
|
+
* Like `hash`, this is `string` at the structural level; cbase32 decodability
|
|
61
|
+
* of every direct value, at every depth, is enforced by
|
|
62
|
+
* {@link checkReferences}.
|
|
63
|
+
*
|
|
64
|
+
* @type {LockSchema}
|
|
65
|
+
*/
|
|
66
|
+
export declare const lock: LockSchema;
|
|
67
|
+
/**
|
|
68
|
+
* rtti schema for a revision's `lock` **field**: the bindings inline as a lock
|
|
69
|
+
* map, or a hash naming a `vnd.fjs.lock` blob (`fjs/media/lock`) that holds
|
|
70
|
+
* one to share — see [Shared lock references](./README.md#shared-lock-references).
|
|
71
|
+
*
|
|
72
|
+
* Structurally identical to {@link lockValue}, and deliberately a separate
|
|
73
|
+
* name: the two positions mean different things. A string *inside* a map is a
|
|
74
|
+
* dependency's content hash; a string in this position is a lock blob's hash,
|
|
75
|
+
* i.e. where the whole map lives. Only the top level is widened, so a nested
|
|
76
|
+
* string keeps meaning exactly what it always did and no position is
|
|
77
|
+
* ambiguous.
|
|
78
|
+
*
|
|
79
|
+
* Widening the field rather than adding a `lockRef` sibling is what keeps this
|
|
80
|
+
* dialect: an older reader validates `lock` as a map and rejects a string
|
|
81
|
+
* outright, whereas an unknown sibling field would validate and be read as
|
|
82
|
+
* "no bindings were recorded" — the fail-open misread the versioning rule
|
|
83
|
+
* exists to prevent. It also makes "inline map *and* reference" unstatable, so
|
|
84
|
+
* the format defines no precedence between them, consistent with its refusal
|
|
85
|
+
* to define overlay or inheritance for nested maps.
|
|
86
|
+
*
|
|
87
|
+
* @type {LockFieldSchema}
|
|
88
|
+
*/
|
|
89
|
+
export declare const lockField: LockFieldSchema;
|
|
45
90
|
/**
|
|
46
91
|
* rtti schema for a `revision` BLOB. See the README for the full semantics of
|
|
47
92
|
* each field; `dialect` is the type discriminant, matched here as an exact
|
|
@@ -54,7 +99,7 @@ export declare const revisionSchema: {
|
|
|
54
99
|
readonly snapshot: import("../../types/rtti/types.ts")._Type0<"string">;
|
|
55
100
|
readonly generation: import("../../types/rtti/types.ts")._Type0<"number">;
|
|
56
101
|
readonly archived: import("../../types/rtti/types.ts").Or<readonly [true, undefined]>;
|
|
57
|
-
readonly lock: import("../../types/rtti/types.ts").Or<readonly [
|
|
102
|
+
readonly lock: import("../../types/rtti/types.ts").Or<readonly [LockFieldSchema, undefined]>;
|
|
58
103
|
};
|
|
59
104
|
/** Serializes a revision canonically, recursively sorting every object's property names.
|
|
60
105
|
* @type {(revision: Revision) => string}
|
|
@@ -64,12 +109,38 @@ export declare const encodeText: (revision: Revision) => string;
|
|
|
64
109
|
* @type {(s: string) => boolean}
|
|
65
110
|
*/
|
|
66
111
|
export declare const isHash: (s: string) => boolean;
|
|
112
|
+
/**
|
|
113
|
+
* The first reason a structurally valid lock map is not a valid one, or `null`
|
|
114
|
+
* — {@link lockError} rooted at the empty scope, so a reported path is
|
|
115
|
+
* relative to the map itself.
|
|
116
|
+
*
|
|
117
|
+
* Exported because `fjs/media/lock` validates the very same map as a
|
|
118
|
+
* standalone blob: one recursive schema and one semantic check, so a map means
|
|
119
|
+
* the same thing inline and shared, and the two forms cannot drift.
|
|
120
|
+
*
|
|
121
|
+
* @type {(lock: LockMap) => string | null}
|
|
122
|
+
*/
|
|
123
|
+
export declare const lockMapError: (lock: LockMap) => string | null;
|
|
124
|
+
/**
|
|
125
|
+
* The first reason a structurally valid `lock` field is not a valid one, or
|
|
126
|
+
* `null`. A map is checked entry by entry ({@link lockMapError}); a string is
|
|
127
|
+
* a reference to a `vnd.fjs.lock` blob and is checked as a cbase32 hash and
|
|
128
|
+
* nothing more — this module is pure format with no store access, so whether
|
|
129
|
+
* the blob exists, and what its bindings mean once fetched, stay a resolver's
|
|
130
|
+
* business exactly as they do for `snapshot`.
|
|
131
|
+
*
|
|
132
|
+
* @type {(value: LockField) => string | null}
|
|
133
|
+
*/
|
|
134
|
+
export declare const lockFieldError: (value: LockField) => string | null;
|
|
67
135
|
/**
|
|
68
136
|
* Checks the semantic refinements the structural schema can't express on an
|
|
69
137
|
* already shape-valid revision: every `parents` entry and the `snapshot` must
|
|
70
|
-
* decode as a cbase32 hash ({@link isHash}),
|
|
138
|
+
* decode as a cbase32 hash ({@link isHash}), the `lock` field must too —
|
|
139
|
+
* every direct value at every depth of an inline map, or the shared-lock
|
|
140
|
+
* reference itself ({@link lockFieldError}) — and `generation` must be a
|
|
71
141
|
* non-negative *safe* integer. `subject` is not checked — it is an identity
|
|
72
|
-
* string, never a snapshot reference, so any string is valid
|
|
142
|
+
* string, never a snapshot reference, so any string is valid, and the same
|
|
143
|
+
* goes for a lock map's keys, which are subjects.
|
|
73
144
|
*
|
|
74
145
|
* `generation` uses `Number.isSafeInteger`, not `Number.isInteger`: a value at
|
|
75
146
|
* or above `2 ** 53` passes `isInteger` but is no longer uniquely
|
|
@@ -97,6 +168,11 @@ export declare const checkReferences: (r: Revision) => Result<Revision, string>;
|
|
|
97
168
|
* Validates an already-parsed JSON value as a `revision` BLOB: structural
|
|
98
169
|
* (rtti) validation followed by the hash / generation semantic checks.
|
|
99
170
|
*
|
|
171
|
+
* `RevisionError` is the union of the two stages' own error types, so each
|
|
172
|
+
* failure reaches the caller as it was raised — `ValidationError` from the
|
|
173
|
+
* schema, `string` from {@link checkReferences} — which is exactly what
|
|
174
|
+
* `okThen` produces here.
|
|
175
|
+
*
|
|
100
176
|
* @type {(value: Unknown) => Result<Revision, RevisionError>}
|
|
101
177
|
*/
|
|
102
178
|
export declare const validate: (value: Unknown) => Result<Revision, RevisionError>;
|
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
* @import { Unknown } from '../json/types.ts'
|
|
18
18
|
* @import { Result } from '../../types/result/types.ts'
|
|
19
19
|
* @import { DialectEntry } from '../types.ts'
|
|
20
|
-
* @import {
|
|
20
|
+
* @import { String as RttiString } from '../../types/rtti/types.ts'
|
|
21
|
+
* @import { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts'
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
|
-
import { array, number, option,
|
|
24
|
-
import {
|
|
24
|
+
import { array, number, option, string } from '../../types/rtti/module.f.mjs'
|
|
25
|
+
import { parse as rttiParse } from '../../types/rtti/parse/module.f.mjs'
|
|
25
26
|
import { parse as parseJson } from '../json/module.f.mjs'
|
|
26
27
|
import { cBase32ToVec } from '../../basen/cbase32/module.f.mjs'
|
|
27
|
-
import { error, ok } from '../../types/result/module.f.mjs'
|
|
28
|
+
import { error, ok, okThen } from '../../types/result/module.f.mjs'
|
|
28
29
|
import { dialectEntry } from '../module.f.mjs'
|
|
29
30
|
import { definedEntries, sort } from '../../types/object/module.f.mjs'
|
|
30
31
|
import { stringify } from '../json/module.f.mjs'
|
|
@@ -49,8 +50,64 @@ export const mediaType = /** @type {const} */ (`application/${dialect}+json`)
|
|
|
49
50
|
*/
|
|
50
51
|
export const hash = string
|
|
51
52
|
|
|
52
|
-
/**
|
|
53
|
-
|
|
53
|
+
/**
|
|
54
|
+
* rtti schema for a lock map: an open map whose every value is either a
|
|
55
|
+
* direct hash string or a nested lock map, to any depth.
|
|
56
|
+
*
|
|
57
|
+
* Self-referential through {@link lockValue}, which is a module-level
|
|
58
|
+
* constant rather than a union rebuilt inside the thunk: the rtti data form
|
|
59
|
+
* (`fjs/types/rtti/data`, which `toJsonSchema` routes through) closes
|
|
60
|
+
* reference cycles by *identity*, so a schema handing out a fresh union thunk
|
|
61
|
+
* on every call would present an infinite graph and never terminate.
|
|
62
|
+
*
|
|
63
|
+
* The named `@type` — rather than `@type {const}` — is what a self-referential
|
|
64
|
+
* schema needs twice over: a `const` cannot reference itself in its own
|
|
65
|
+
* initializer at all, and naming the recursive position is also what keeps
|
|
66
|
+
* declaration emit from inlining the structure and giving up at depth (see
|
|
67
|
+
* `fjs/AGENTS.md` §3.2 and `../json/rtti/module.f.mjs`).
|
|
68
|
+
*
|
|
69
|
+
* Like `hash`, this is `string` at the structural level; cbase32 decodability
|
|
70
|
+
* of every direct value, at every depth, is enforced by
|
|
71
|
+
* {@link checkReferences}.
|
|
72
|
+
*
|
|
73
|
+
* @type {LockSchema}
|
|
74
|
+
*/
|
|
75
|
+
export const lock = () => ['record', lockValue]
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* One lock-map value: a direct hash, or a nested lock map. Written as the
|
|
79
|
+
* union tuple rather than as `or(string, lock)` so the thunk carries the name
|
|
80
|
+
* `lockValue`: this is where the reference cycle closes, and the data form
|
|
81
|
+
* names a rule after its defining function — an anonymous thunk would publish
|
|
82
|
+
* the recursion as `$defs: { '': … }` in every derived JSON Schema.
|
|
83
|
+
*
|
|
84
|
+
* @type {() => readonly['or', RttiString, LockSchema]}
|
|
85
|
+
*/
|
|
86
|
+
const lockValue = () => ['or', string, lock]
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* rtti schema for a revision's `lock` **field**: the bindings inline as a lock
|
|
90
|
+
* map, or a hash naming a `vnd.fjs.lock` blob (`fjs/media/lock`) that holds
|
|
91
|
+
* one to share — see [Shared lock references](./README.md#shared-lock-references).
|
|
92
|
+
*
|
|
93
|
+
* Structurally identical to {@link lockValue}, and deliberately a separate
|
|
94
|
+
* name: the two positions mean different things. A string *inside* a map is a
|
|
95
|
+
* dependency's content hash; a string in this position is a lock blob's hash,
|
|
96
|
+
* i.e. where the whole map lives. Only the top level is widened, so a nested
|
|
97
|
+
* string keeps meaning exactly what it always did and no position is
|
|
98
|
+
* ambiguous.
|
|
99
|
+
*
|
|
100
|
+
* Widening the field rather than adding a `lockRef` sibling is what keeps this
|
|
101
|
+
* dialect: an older reader validates `lock` as a map and rejects a string
|
|
102
|
+
* outright, whereas an unknown sibling field would validate and be read as
|
|
103
|
+
* "no bindings were recorded" — the fail-open misread the versioning rule
|
|
104
|
+
* exists to prevent. It also makes "inline map *and* reference" unstatable, so
|
|
105
|
+
* the format defines no precedence between them, consistent with its refusal
|
|
106
|
+
* to define overlay or inheritance for nested maps.
|
|
107
|
+
*
|
|
108
|
+
* @type {LockFieldSchema}
|
|
109
|
+
*/
|
|
110
|
+
export const lockField = () => ['or', hash, lock]
|
|
54
111
|
|
|
55
112
|
/**
|
|
56
113
|
* rtti schema for a `revision` BLOB. See the README for the full semantics of
|
|
@@ -64,7 +121,7 @@ export const revisionSchema = /** @type {const} */ ({
|
|
|
64
121
|
snapshot: hash,
|
|
65
122
|
generation: number,
|
|
66
123
|
archived: option(true),
|
|
67
|
-
lock: option(
|
|
124
|
+
lock: option(lockField),
|
|
68
125
|
})
|
|
69
126
|
|
|
70
127
|
/** Serializes a revision canonically, recursively sorting every object's property names.
|
|
@@ -73,19 +130,70 @@ export const revisionSchema = /** @type {const} */ ({
|
|
|
73
130
|
export const encodeText = stringify(sort)
|
|
74
131
|
|
|
75
132
|
/** Structural-only validator: checks the shape, not the hash / generation semantics. */
|
|
76
|
-
const validateShape =
|
|
133
|
+
const validateShape = rttiParse(revisionSchema)
|
|
77
134
|
|
|
78
135
|
/** True when `s` decodes as a cbase32 CAS hash (rejects `https://` and any other non-cbase32 string).
|
|
79
136
|
* @type {(s: string) => boolean}
|
|
80
137
|
*/
|
|
81
138
|
export const isHash = s => cBase32ToVec(s) !== null
|
|
82
139
|
|
|
140
|
+
/**
|
|
141
|
+
* The first reason a structurally valid lock map is not a valid one, or
|
|
142
|
+
* `null` when every direct value at every depth is a cbase32 hash
|
|
143
|
+
* ({@link isHash}). Nested maps are scopes, not references, so only the
|
|
144
|
+
* strings are checked; `scope` names the path walked to reach the offending
|
|
145
|
+
* value, so a failure deep in a nested map still says where it is.
|
|
146
|
+
*
|
|
147
|
+
* @type {(scope: readonly string[]) => (lock: LockMap) => string | null}
|
|
148
|
+
*/
|
|
149
|
+
const lockError = scope => lock => {
|
|
150
|
+
for (const [subject, value] of definedEntries(lock)) {
|
|
151
|
+
const path = [...scope, subject]
|
|
152
|
+
const message = typeof value === 'string'
|
|
153
|
+
? (isHash(value) ? null : `lock value for ${path.join('/')} is not a valid hash: ${value}`)
|
|
154
|
+
: lockError(path)(value)
|
|
155
|
+
if (message !== null) { return message }
|
|
156
|
+
}
|
|
157
|
+
return null
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The first reason a structurally valid lock map is not a valid one, or `null`
|
|
162
|
+
* — {@link lockError} rooted at the empty scope, so a reported path is
|
|
163
|
+
* relative to the map itself.
|
|
164
|
+
*
|
|
165
|
+
* Exported because `fjs/media/lock` validates the very same map as a
|
|
166
|
+
* standalone blob: one recursive schema and one semantic check, so a map means
|
|
167
|
+
* the same thing inline and shared, and the two forms cannot drift.
|
|
168
|
+
*
|
|
169
|
+
* @type {(lock: LockMap) => string | null}
|
|
170
|
+
*/
|
|
171
|
+
export const lockMapError = lockError([])
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The first reason a structurally valid `lock` field is not a valid one, or
|
|
175
|
+
* `null`. A map is checked entry by entry ({@link lockMapError}); a string is
|
|
176
|
+
* a reference to a `vnd.fjs.lock` blob and is checked as a cbase32 hash and
|
|
177
|
+
* nothing more — this module is pure format with no store access, so whether
|
|
178
|
+
* the blob exists, and what its bindings mean once fetched, stay a resolver's
|
|
179
|
+
* business exactly as they do for `snapshot`.
|
|
180
|
+
*
|
|
181
|
+
* @type {(value: LockField) => string | null}
|
|
182
|
+
*/
|
|
183
|
+
export const lockFieldError = value =>
|
|
184
|
+
typeof value === 'string'
|
|
185
|
+
? (isHash(value) ? null : `lock reference is not a valid hash: ${value}`)
|
|
186
|
+
: lockMapError(value)
|
|
187
|
+
|
|
83
188
|
/**
|
|
84
189
|
* Checks the semantic refinements the structural schema can't express on an
|
|
85
190
|
* already shape-valid revision: every `parents` entry and the `snapshot` must
|
|
86
|
-
* decode as a cbase32 hash ({@link isHash}),
|
|
191
|
+
* decode as a cbase32 hash ({@link isHash}), the `lock` field must too —
|
|
192
|
+
* every direct value at every depth of an inline map, or the shared-lock
|
|
193
|
+
* reference itself ({@link lockFieldError}) — and `generation` must be a
|
|
87
194
|
* non-negative *safe* integer. `subject` is not checked — it is an identity
|
|
88
|
-
* string, never a snapshot reference, so any string is valid
|
|
195
|
+
* string, never a snapshot reference, so any string is valid, and the same
|
|
196
|
+
* goes for a lock map's keys, which are subjects.
|
|
89
197
|
*
|
|
90
198
|
* `generation` uses `Number.isSafeInteger`, not `Number.isInteger`: a value at
|
|
91
199
|
* or above `2 ** 53` passes `isInteger` but is no longer uniquely
|
|
@@ -113,9 +221,8 @@ export const checkReferences = r => {
|
|
|
113
221
|
if (!isHash(p)) { return error(`parent is not a valid hash: ${p}`) }
|
|
114
222
|
}
|
|
115
223
|
if (!isHash(r.snapshot)) { return error(`snapshot is not a valid hash: ${r.snapshot}`) }
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
224
|
+
const lockMessage = r.lock === undefined ? null : lockFieldError(r.lock)
|
|
225
|
+
if (lockMessage !== null) { return error(lockMessage) }
|
|
119
226
|
if (!Number.isSafeInteger(r.generation) || r.generation < 0) {
|
|
120
227
|
return error(`generation must be a non-negative safe integer: ${r.generation}`)
|
|
121
228
|
}
|
|
@@ -126,13 +233,14 @@ export const checkReferences = r => {
|
|
|
126
233
|
* Validates an already-parsed JSON value as a `revision` BLOB: structural
|
|
127
234
|
* (rtti) validation followed by the hash / generation semantic checks.
|
|
128
235
|
*
|
|
236
|
+
* `RevisionError` is the union of the two stages' own error types, so each
|
|
237
|
+
* failure reaches the caller as it was raised — `ValidationError` from the
|
|
238
|
+
* schema, `string` from {@link checkReferences} — which is exactly what
|
|
239
|
+
* `okThen` produces here.
|
|
240
|
+
*
|
|
129
241
|
* @type {(value: Unknown) => Result<Revision, RevisionError>}
|
|
130
242
|
*/
|
|
131
|
-
export const validate = value =>
|
|
132
|
-
const [t, v] = validateShape(value)
|
|
133
|
-
if (t === 'error') { return error(v) }
|
|
134
|
-
return checkReferences(v)
|
|
135
|
-
}
|
|
243
|
+
export const validate = value => okThen(checkReferences)(validateShape(value))
|
|
136
244
|
|
|
137
245
|
/**
|
|
138
246
|
* Decodes `text` as a `revision` BLOB: JSON-parses it, then validates it per
|
|
@@ -141,11 +249,7 @@ export const validate = value => {
|
|
|
141
249
|
*
|
|
142
250
|
* @type {(text: string) => Result<Revision, RevisionError>}
|
|
143
251
|
*/
|
|
144
|
-
export const decodeText = text =>
|
|
145
|
-
const [t, v] = parseJson(text)
|
|
146
|
-
if (t === 'error') { return error(v) }
|
|
147
|
-
return validate(v)
|
|
148
|
-
}
|
|
252
|
+
export const decodeText = text => okThen(validate)(parseJson(text))
|
|
149
253
|
|
|
150
254
|
/** {@link checkReferences} as the `boolean` refinement a {@link DialectEntry} takes.
|
|
151
255
|
* @type {(r: Revision) => boolean}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Object as JsonObject } from '../json/types.ts'
|
|
3
|
+
* @import { LockMap } from './types.ts'
|
|
4
|
+
*/
|
|
1
5
|
export declare const proof: {
|
|
2
6
|
dialectAndMediaType: () => void;
|
|
3
7
|
isHash: {
|
|
@@ -24,6 +28,13 @@ export declare const proof: {
|
|
|
24
28
|
malformedLockRejected: () => void;
|
|
25
29
|
invalidHashLockRejected: () => void;
|
|
26
30
|
aliasHashLockAccepted: () => void;
|
|
31
|
+
nestedLockAccepted: () => void;
|
|
32
|
+
deeplyNestedLockAccepted: () => void;
|
|
33
|
+
malformedNestedLockRejected: () => void;
|
|
34
|
+
invalidNestedHashLockRejected: () => void;
|
|
35
|
+
sharedLockReferenceAccepted: () => void;
|
|
36
|
+
invalidSharedLockReferenceRejected: () => void;
|
|
37
|
+
nestedValueIsStillNotAReference: () => void;
|
|
27
38
|
wrongDialectRejected: () => void;
|
|
28
39
|
missingSubjectRejected: () => void;
|
|
29
40
|
extraFieldsAccepted: () => void;
|
|
@@ -36,6 +47,9 @@ export declare const proof: {
|
|
|
36
47
|
};
|
|
37
48
|
encodeText: {
|
|
38
49
|
recursivelySortsObjectsLexicographically: () => void;
|
|
50
|
+
sortsNestedLockKeys: () => void;
|
|
51
|
+
equivalentNestedLockOrdersConverge: () => void;
|
|
52
|
+
serializesSharedLockReferenceAsAString: () => void;
|
|
39
53
|
preservesArrayOrder: () => void;
|
|
40
54
|
parsedEquivalentSourcesConverge: () => void;
|
|
41
55
|
};
|