functionalscript 0.45.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +10 -0
- package/fjs/asn.1/proof.f.mjs +16 -0
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -3
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +28 -14
- package/fjs/bnf/descent/module.f.mjs +122 -77
- package/fjs/bnf/descent/proof.f.d.mts +2 -0
- package/fjs/bnf/descent/proof.f.mjs +117 -31
- package/fjs/bnf/descent/types.d.ts +12 -14
- package/fjs/bnf/ll1/module.f.d.mts +64 -22
- package/fjs/bnf/ll1/module.f.mjs +214 -154
- package/fjs/bnf/ll1/proof.f.d.mts +15 -2
- package/fjs/bnf/ll1/proof.f.mjs +323 -149
- package/fjs/bnf/ll1/types.d.ts +16 -24
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +1 -3
- package/fjs/cas/cli/proof.f.mjs +44 -33
- package/fjs/cas/evo/module.f.d.mts +64 -18
- package/fjs/cas/evo/module.f.mjs +148 -70
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +305 -223
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +129 -128
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/config/module.f.d.mts +2 -2
- package/fjs/ci/config/module.f.mjs +2 -2
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.mjs +2 -2
- package/fjs/ci/proof.f.mjs +9 -5
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.mjs +17 -16
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/types.d.ts +1 -1
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +1 -0
- package/fjs/crypto/sha2/proof.f.mjs +24 -0
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/dev/module.f.d.mts +13 -4
- package/fjs/dev/module.f.mjs +56 -27
- package/fjs/dev/update/module.f.d.mts +9 -4
- package/fjs/dev/update/module.f.mjs +14 -10
- package/fjs/dev/update/proof.f.d.mts +1 -3
- package/fjs/dev/update/proof.f.mjs +10 -5
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +13 -3
- package/fjs/djs/parser/module.f.mjs +117 -16
- package/fjs/djs/parser/proof.f.d.mts +5 -1
- package/fjs/djs/parser/proof.f.mjs +274 -12
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +18 -2
- package/fjs/djs/proof.f.mjs +187 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +61 -15
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +99 -60
- package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
- package/fjs/djs/tokenizer/proof.f.mjs +74 -67
- package/fjs/djs/transpiler/module.f.d.mts +12 -7
- package/fjs/djs/transpiler/module.f.mjs +82 -56
- package/fjs/djs/transpiler/types.d.ts +7 -3
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +14 -11
- package/fjs/effects/list/module.f.mjs +13 -11
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +2 -1
- package/fjs/effects/memory/module.f.mjs +3 -4
- package/fjs/effects/memory/proof.f.mjs +13 -7
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +20 -4
- package/fjs/effects/mock/module.f.mjs +37 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +4 -2
- package/fjs/effects/module.f.d.mts +466 -280
- package/fjs/effects/module.f.mjs +537 -299
- package/fjs/effects/module.mjs +2 -1
- package/fjs/effects/node/memory/module.d.mts +4 -2
- package/fjs/effects/node/memory/module.mjs +6 -3
- package/fjs/effects/node/memory/proof.mjs +10 -4
- package/fjs/effects/node/module.d.mts +4 -3
- package/fjs/effects/node/module.f.d.mts +168 -33
- package/fjs/effects/node/module.f.mjs +256 -52
- package/fjs/effects/node/module.mjs +57 -34
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +18 -4
- package/fjs/effects/node/virtual/module.f.mjs +110 -68
- package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
- package/fjs/effects/node/virtual/proof.f.mjs +190 -9
- package/fjs/effects/proof.f.d.mts +69 -37
- package/fjs/effects/proof.f.mjs +410 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/module.f.d.mts +19 -12
- package/fjs/emergent_testing/module.f.mjs +93 -33
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +166 -32
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +2 -0
- package/fjs/fsm/proof.f.mjs +83 -114
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/js/keywords/proof.f.d.mts +3 -0
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +26 -6
- package/fjs/js/tokenizer/module.f.mjs +145 -159
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +4 -4
- package/fjs/mcp/module.f.mjs +6 -6
- package/fjs/mcp/proof.f.d.mts +5 -3
- package/fjs/mcp/proof.f.mjs +112 -46
- package/fjs/media/html/module.f.mjs +1 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +114 -70
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +33 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.mjs +9 -9
- package/fjs/media/json/schema/module.f.mjs +3 -13
- package/fjs/media/json/schema/proof.f.d.mts +0 -1
- package/fjs/media/json/schema/proof.f.mjs +1 -2
- package/fjs/media/json/serializer/module.f.d.mts +32 -1
- package/fjs/media/json/serializer/module.f.mjs +64 -2
- package/fjs/media/json/tokenizer/module.f.mjs +7 -3
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +78 -7
- package/fjs/media/revision/module.f.mjs +119 -12
- package/fjs/media/revision/proof.f.d.mts +10 -0
- package/fjs/media/revision/proof.f.mjs +88 -0
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +33 -15
- package/fjs/media/type/module.f.mjs +35 -29
- package/fjs/media/type/proof.f.d.mts +2 -1
- package/fjs/media/type/proof.f.mjs +30 -10
- package/fjs/module.f.mjs +29 -8
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/proof.f.d.mts +3 -3
- package/fjs/proof.f.mjs +36 -10
- package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
- package/fjs/protocol/json_rpc/module.f.mjs +3 -3
- package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +13 -4
- package/fjs/protocol/mcp/proof.f.mjs +193 -61
- package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
- package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
- package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +0 -1
- package/fjs/sul/id/module.f.mjs +2 -3
- package/fjs/sul/level/hash/module.f.mjs +2 -1
- package/fjs/sul/level/hash/proof.f.mjs +2 -2
- package/fjs/sul/module.f.mjs +18 -13
- package/fjs/text/code_point/module.f.d.mts +8 -0
- package/fjs/text/code_point/module.f.mjs +8 -1
- package/fjs/text/code_point/proof.f.d.mts +1 -0
- package/fjs/text/code_point/proof.f.mjs +11 -0
- package/fjs/text/sgr/module.f.d.mts +4 -6
- package/fjs/text/sgr/module.f.mjs +6 -7
- package/fjs/text/utf16/module.f.mjs +7 -2
- package/fjs/text/utf16/proof.f.mjs +3 -3
- package/fjs/text/utf8/module.f.mjs +4 -2
- package/fjs/types/array/module.f.mjs +14 -2
- package/fjs/types/bit_vec/module.f.d.mts +0 -2
- package/fjs/types/bit_vec/module.f.mjs +46 -32
- package/fjs/types/bit_vec/proof.f.mjs +2 -2
- package/fjs/types/btree/remove/module.f.mjs +1 -1
- package/fjs/types/btree/set/module.f.mjs +9 -11
- package/fjs/types/btree/set/proof.f.mjs +12 -0
- package/fjs/types/byte_set/module.f.d.mts +11 -4
- package/fjs/types/byte_set/module.f.mjs +14 -6
- package/fjs/types/byte_set/proof.f.mjs +7 -7
- package/fjs/types/function/compare/module.f.mjs +10 -3
- package/fjs/types/list/module.f.d.mts +1 -1
- package/fjs/types/list/module.f.mjs +1 -1
- package/fjs/types/nullable/module.f.d.mts +18 -4
- package/fjs/types/nullable/module.f.mjs +21 -4
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/object/module.f.d.mts +12 -2
- package/fjs/types/object/module.f.mjs +11 -1
- package/fjs/types/patricia_trie/module.f.mjs +26 -11
- package/fjs/types/result/module.f.d.mts +3 -3
- package/fjs/types/result/module.f.mjs +3 -3
- package/fjs/types/rtti/common/module.f.d.mts +25 -28
- package/fjs/types/rtti/common/module.f.mjs +36 -32
- package/fjs/types/rtti/common/proof.f.mjs +5 -5
- package/fjs/types/rtti/data/module.f.d.mts +14 -0
- package/fjs/types/rtti/data/module.f.mjs +25 -2
- package/fjs/types/rtti/data/proof.f.d.mts +1 -0
- package/fjs/types/rtti/data/proof.f.mjs +25 -2
- package/fjs/types/rtti/parse/module.f.d.mts +24 -14
- package/fjs/types/rtti/parse/module.f.mjs +37 -28
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +33 -14
- package/fjs/types/rtti/proof.f.mjs +3 -1
- package/fjs/types/rtti/ts/module.f.mjs +13 -17
- package/fjs/types/rtti/ts/types.d.ts +14 -1
- package/fjs/types/sorted_set/module.f.d.mts +18 -0
- package/fjs/types/sorted_set/module.f.mjs +22 -0
- package/fjs/types/sorted_set/proof.f.d.mts +1 -0
- package/fjs/types/sorted_set/proof.f.mjs +16 -1
- package/fjs/types/uint8array/module.f.d.mts +1 -1
- package/fjs/types/uint8array/module.f.mjs +1 -1
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +4 -7
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +2 -2
- package/fjs/dev/package_json/module.f.d.mts +0 -39
- package/fjs/dev/package_json/module.f.mjs +0 -40
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/effects/eff/module.f.d.mts +0 -20
- package/fjs/effects/eff/module.f.mjs +0 -70
- package/fjs/effects/eff/proof.f.d.mts +0 -15
- package/fjs/effects/eff/proof.f.mjs +0 -69
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/types/rtti/validate/module.f.d.mts +0 -41
- package/fjs/types/rtti/validate/module.f.mjs +0 -171
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
package/fjs/cas/evo/module.f.mjs
CHANGED
|
@@ -42,18 +42,29 @@
|
|
|
42
42
|
*
|
|
43
43
|
* @module
|
|
44
44
|
*
|
|
45
|
-
* @import {
|
|
45
|
+
* @import { Operation } from '../../effects/types.ts'
|
|
46
|
+
* @import { Effect, NotImplemented } from '../../effects/types.ts'
|
|
47
|
+
* @import { EvoChannel, EvoError } from './types.ts'
|
|
46
48
|
* @import { Key, MemOp } from '../../effects/memory/types.ts'
|
|
47
49
|
* @import { Cas } from '../types.ts'
|
|
48
|
-
* @import {
|
|
50
|
+
* @import { Result } from '../../types/result/types.ts'
|
|
49
51
|
* @import { Vec } from '../../types/bit_vec/types.ts'
|
|
50
|
-
* @import {
|
|
52
|
+
* @import { Ok } from '../../types/result/types.ts'
|
|
51
53
|
* @import { List } from '../../effects/list/types.ts'
|
|
52
|
-
* @import {
|
|
54
|
+
* @import { IoChannel, IoResult } from '../../effects/node/types.ts'
|
|
55
|
+
* @import { LockField, LockMap, Revision } from '../../media/revision/types.ts'
|
|
53
56
|
* @import { Hash, Subject, RevisionData, SubjectState, Cache, Evo } from './types.ts'
|
|
54
57
|
*/
|
|
55
58
|
|
|
56
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
catchStep,
|
|
61
|
+
foldStep as ioFoldStep,
|
|
62
|
+
mapStep as ioMapStep,
|
|
63
|
+
pureError,
|
|
64
|
+
pureOk,
|
|
65
|
+
resultMapStep,
|
|
66
|
+
step as ioStep,
|
|
67
|
+
} from '../../effects/module.f.mjs'
|
|
57
68
|
import { create, read, write } from '../../effects/memory/module.f.mjs'
|
|
58
69
|
import { collectRead } from '../module.f.mjs'
|
|
59
70
|
import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.mjs'
|
|
@@ -63,11 +74,33 @@ import { ok, error, okThen } from '../../types/result/module.f.mjs'
|
|
|
63
74
|
import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.mjs'
|
|
64
75
|
import { at, definedEntries } from '../../types/object/module.f.mjs'
|
|
65
76
|
import { unwrap } from '../../types/nullable/module.f.mjs'
|
|
66
|
-
import { isNotFound } from '../../effects/node/module.f.mjs'
|
|
77
|
+
import { errorSummary, isNotFound } from '../../effects/node/module.f.mjs'
|
|
67
78
|
import { decodeText, encodeText, dialect, checkReferences, isHash } from '../../media/revision/module.f.mjs'
|
|
68
79
|
|
|
80
|
+
/**
|
|
81
|
+
* A rejected revision, tagged so it renders alongside `notImplemented` and
|
|
82
|
+
* `ioError` rather than needing a `typeof` test to be told from them.
|
|
83
|
+
*
|
|
84
|
+
* @type {(message: string) => EvoError}
|
|
85
|
+
*/
|
|
86
|
+
export const evoError = message => ['evoError', message]
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Renders an {@link EvoChannel} failure as a message.
|
|
90
|
+
*
|
|
91
|
+
* The two cases are told apart by tag and nothing else — which is the whole
|
|
92
|
+
* reason {@link EvoError} is a tuple. A rejected revision already carries a
|
|
93
|
+
* message written for a caller; a runner that could not dispatch is described
|
|
94
|
+
* by `errorSummary`, the same renderer the node channel uses, so there is one
|
|
95
|
+
* phrasing of "operation not implemented" rather than two.
|
|
96
|
+
*
|
|
97
|
+
* @type {(e: EvoChannel) => string}
|
|
98
|
+
*/
|
|
99
|
+
export const evoSummary = e => e[0] === 'evoError' ? e[1] : errorSummary(e)
|
|
100
|
+
|
|
69
101
|
/** A cache with no known subjects yet — the starting point for {@link buildCache}. */
|
|
70
|
-
|
|
102
|
+
/** @type {Cache} */
|
|
103
|
+
export const emptyCache = { bySubject: {} }
|
|
71
104
|
|
|
72
105
|
/** @type {SubjectState} */
|
|
73
106
|
const emptySubjectState = { hashes: [], parents: [], archived: [] }
|
|
@@ -93,11 +126,26 @@ const union = set => items =>
|
|
|
93
126
|
*/
|
|
94
127
|
const canonicalHash = h => vecToCBase32(unwrap(cBase32ToVec(h)))
|
|
95
128
|
|
|
96
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Canonicalizes every direct hash of a structurally validated lock map, at
|
|
131
|
+
* every depth, preserving its nested scope structure. Nested maps are scopes
|
|
132
|
+
* rather than references, so only the strings are re-spelled — the same split
|
|
133
|
+
* `fjs/media/revision`'s `checkReferences` validates along.
|
|
97
134
|
* @type {(lock: LockMap) => LockMap}
|
|
98
135
|
*/
|
|
99
136
|
const canonicalLock = lock =>
|
|
100
|
-
Object.fromEntries(definedEntries(lock).map(
|
|
137
|
+
Object.fromEntries(definedEntries(lock).map(
|
|
138
|
+
([subject, value]) => [subject, typeof value === 'string' ? canonicalHash(value) : canonicalLock(value)]))
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Canonicalizes a revision's `lock` field: a shared-lock reference is one hash
|
|
142
|
+
* to re-spell, an inline map is walked to the bottom ({@link canonicalLock}).
|
|
143
|
+
* The split is the same one `fjs/media/revision`'s `lockFieldError` validates
|
|
144
|
+
* along, so what this re-spells is exactly what was checked.
|
|
145
|
+
* @type {(value: LockField) => LockField}
|
|
146
|
+
*/
|
|
147
|
+
const canonicalLockField = value =>
|
|
148
|
+
typeof value === 'string' ? canonicalHash(value) : canonicalLock(value)
|
|
101
149
|
|
|
102
150
|
/** A subject's current heads: revision hashes seen that no other revision of the same subject names as a parent.
|
|
103
151
|
* @type {(state: SubjectState) => readonly Hash[]}
|
|
@@ -181,46 +229,62 @@ export const decodeRevisionVec = value => {
|
|
|
181
229
|
*
|
|
182
230
|
* @template {Operation} O
|
|
183
231
|
* @param {Cas<O>} cas
|
|
184
|
-
*
|
|
232
|
+
* The `never` is a decision, not an observation: reading the store *can* fail,
|
|
233
|
+
* and this maps that failure to `null` alongside "the bytes are not a
|
|
234
|
+
* revision". A scan wants exactly that — one unreadable blob must not fail the
|
|
235
|
+
* whole cache build — but the two are genuinely different answers, and this
|
|
236
|
+
* one loses the difference on purpose. Saying `never` puts that where a reader
|
|
237
|
+
* can disagree with it.
|
|
238
|
+
*
|
|
239
|
+
* @returns {(hash: Vec) => Effect<O, Revision | null, never>}
|
|
185
240
|
*/
|
|
186
241
|
export const decodeRevisionBlob = cas => hash =>
|
|
187
|
-
|
|
242
|
+
resultMapStep(
|
|
188
243
|
collectRead(cas.read(hash)),
|
|
189
|
-
([tag, value]) => tag === 'error' ? null : decodeRevisionVec(value))
|
|
244
|
+
([tag, value]) => ok(tag === 'error' ? null : decodeRevisionVec(value)))
|
|
190
245
|
|
|
191
246
|
/**
|
|
192
247
|
* Scans every hash in `cas` and builds a fresh {@link Cache} from the
|
|
193
248
|
* `vnd.fjs.revision` blobs found among them. Non-revision blobs are ignored.
|
|
194
249
|
*
|
|
250
|
+
* A store that cannot be listed is a failure of the scan, not an empty cache:
|
|
251
|
+
* the fold never starts, and the caller is told. Blobs that fail to *read*
|
|
252
|
+
* remain "not a revision" and are skipped — see {@link decodeRevisionBlob}.
|
|
253
|
+
*
|
|
195
254
|
* @template {Operation} O
|
|
196
255
|
* @param {Cas<O>} cas
|
|
197
|
-
* @returns {Effect<O, Cache>}
|
|
256
|
+
* @returns {Effect<O, Cache, IoChannel>}
|
|
198
257
|
*/
|
|
199
|
-
export const buildCache = cas =>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
258
|
+
export const buildCache = cas => {
|
|
259
|
+
// Annotated rather than inferred: the body's `ok(…)` is an `Ok<Cache>`,
|
|
260
|
+
// which unifies with `Result<S, E>` for any `E`, so the fold's error type
|
|
261
|
+
// has nothing to pin it and drifts into the accumulator's.
|
|
262
|
+
/** @type {(hash: Vec) => (cache: Cache) => Effect<O, Cache, IoChannel>} */
|
|
263
|
+
const foldOne = hash => cache =>
|
|
264
|
+
ioMapStep(
|
|
265
|
+
decodeRevisionBlob(cas)(hash),
|
|
266
|
+
revision =>
|
|
267
|
+
revision === null ? cache : addRevisionToCache(vecToCBase32(hash), revision)(cache))
|
|
268
|
+
return ioStep(cas.list(), hashes => ioFoldStep(pureOk(hashes), emptyCache, foldOne))
|
|
269
|
+
}
|
|
208
270
|
|
|
209
271
|
/**
|
|
210
272
|
* Scans `cas` once and allocates a memory slot holding the resulting {@link Cache}.
|
|
211
273
|
*
|
|
212
274
|
* @template {Operation} O
|
|
213
275
|
* @param {Cas<O>} cas
|
|
214
|
-
* @returns {Effect<O | MemOp, Key<Cache
|
|
276
|
+
* @returns {Effect<O | MemOp, Key<Cache>, IoChannel>}
|
|
215
277
|
*/
|
|
216
278
|
export const initEvo = cas =>
|
|
217
|
-
|
|
279
|
+
ioStep(buildCache(cas), cache => create(cache))
|
|
218
280
|
|
|
219
281
|
/** Reads, then rewrites, the cache at `cacheKey` with `revision` folded in at `hash`.
|
|
220
|
-
* @type {(cacheKey: Key<Cache>) => (hash: Hash) => (revision: Revision) => Effect<MemOp, void>}
|
|
282
|
+
* @type {(cacheKey: Key<Cache>) => (hash: Hash) => (revision: Revision) => Effect<MemOp, void, NotImplemented>}
|
|
221
283
|
*/
|
|
222
284
|
const foldIntoCache = cacheKey => hash => revision =>
|
|
223
|
-
|
|
285
|
+
ioStep(
|
|
286
|
+
read(cacheKey),
|
|
287
|
+
cache => write(cacheKey, addRevisionToCache(hash, revision)(cache)))
|
|
224
288
|
|
|
225
289
|
/**
|
|
226
290
|
* Folds `value` — bytes already written to a `Cas` at `hash` by some other
|
|
@@ -230,11 +294,11 @@ const foldIntoCache = cacheKey => hash => revision =>
|
|
|
230
294
|
* call can store a revision blob without going through {@link addRevision},
|
|
231
295
|
* and this is what keeps the cache honest about it without rescanning the
|
|
232
296
|
* whole store.
|
|
233
|
-
* @type {(cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void>}
|
|
297
|
+
* @type {(cacheKey: Key<Cache>) => (hash: Vec) => (value: Vec) => Effect<MemOp, void, NotImplemented>}
|
|
234
298
|
*/
|
|
235
299
|
export const syncRevision = cacheKey => hash => value => {
|
|
236
300
|
const revision = decodeRevisionVec(value)
|
|
237
|
-
return revision === null ?
|
|
301
|
+
return revision === null ? pureOk(undefined) : foldIntoCache(cacheKey)(vecToCBase32(hash))(revision)
|
|
238
302
|
}
|
|
239
303
|
|
|
240
304
|
/**
|
|
@@ -246,39 +310,39 @@ export const syncRevision = cacheKey => hash => value => {
|
|
|
246
310
|
*
|
|
247
311
|
* @template {Operation} O
|
|
248
312
|
* @param {Cas<O>} cas
|
|
249
|
-
* @returns {(parentRef: Hash) => Effect<O,
|
|
313
|
+
* @returns {(parentRef: Hash) => Effect<O, Revision, EvoError>}
|
|
250
314
|
*/
|
|
251
315
|
const resolveParent = cas => parentRef => {
|
|
252
316
|
const parentHash = cBase32ToVec(parentRef)
|
|
253
317
|
if (parentHash === null) {
|
|
254
|
-
return
|
|
318
|
+
return pureError(evoError(`invalid parent hash: ${parentRef}`))
|
|
255
319
|
}
|
|
256
|
-
return
|
|
320
|
+
return ioStep(
|
|
257
321
|
decodeRevisionBlob(cas)(parentHash),
|
|
258
|
-
parent => parent === null
|
|
322
|
+
parent => parent === null
|
|
323
|
+
? pureError(evoError(`parent is not a revision blob: ${parentRef}`))
|
|
324
|
+
: pureOk(parent))
|
|
259
325
|
}
|
|
260
326
|
|
|
261
327
|
/**
|
|
262
328
|
* Resolves and validates every entry of `parents`, in order, short-circuiting on the first failure.
|
|
263
329
|
*
|
|
330
|
+
* Short-circuiting is `foldStep`'s, not this function's. It used to be
|
|
331
|
+
* two hand-written `[0] === 'error'` tests, which is what a verdict costs when
|
|
332
|
+
* it rides in the value instead of the channel.
|
|
333
|
+
*
|
|
264
334
|
* @template {Operation} O
|
|
265
335
|
* @param {Cas<O>} cas
|
|
266
|
-
* @returns {(parents: readonly Hash[]) => Effect<O,
|
|
336
|
+
* @returns {(parents: readonly Hash[]) => Effect<O, readonly Revision[], EvoError>}
|
|
267
337
|
*/
|
|
268
338
|
const resolveParents = cas => parents => {
|
|
269
|
-
/** @type {
|
|
270
|
-
const init =
|
|
271
|
-
return
|
|
272
|
-
|
|
339
|
+
/** @type {readonly Revision[]} */
|
|
340
|
+
const init = []
|
|
341
|
+
return ioFoldStep(
|
|
342
|
+
pureOk(parents),
|
|
273
343
|
init,
|
|
274
|
-
parentRef => (/** @type {
|
|
275
|
-
|
|
276
|
-
return mapStep(
|
|
277
|
-
resolveParent(cas)(parentRef),
|
|
278
|
-
(/** @type {Result<Revision, string>} */ parentResult) =>
|
|
279
|
-
/** @type {Result<readonly Revision[], string>} */
|
|
280
|
-
(parentResult[0] === 'error' ? parentResult : ok([...acc[1], parentResult[1]])))
|
|
281
|
-
})
|
|
344
|
+
parentRef => (/** @type {readonly Revision[]} */ acc) =>
|
|
345
|
+
ioMapStep(resolveParent(cas)(parentRef), parent => [...acc, parent]))
|
|
282
346
|
}
|
|
283
347
|
|
|
284
348
|
/**
|
|
@@ -410,7 +474,7 @@ const buildRevision = input => parents => {
|
|
|
410
474
|
...revision,
|
|
411
475
|
parents: revision.parents.map(canonicalHash),
|
|
412
476
|
snapshot: canonicalHash(revision.snapshot),
|
|
413
|
-
lock: revision.lock === undefined ? undefined :
|
|
477
|
+
lock: revision.lock === undefined ? undefined : canonicalLockField(revision.lock),
|
|
414
478
|
})
|
|
415
479
|
}
|
|
416
480
|
|
|
@@ -432,27 +496,41 @@ const buildRevision = input => parents => {
|
|
|
432
496
|
*
|
|
433
497
|
* @template {Operation} O
|
|
434
498
|
* @param {Cas<O>} cas
|
|
435
|
-
*
|
|
499
|
+
* A rejected revision and an unreachable cache slot share one channel — see
|
|
500
|
+
* {@link Evo.add} — so every branch below answers `pureError`, and the
|
|
501
|
+
* successful path never re-tests what an earlier step already decided.
|
|
502
|
+
*
|
|
503
|
+
* The `Cas` write is the one place a host failure is *translated* rather than
|
|
504
|
+
* propagated: {@link catchStep} turns any `IoChannel` error into one
|
|
505
|
+
* {@link EvoError}, because a caller of this API has the same recourse to a
|
|
506
|
+
* full disk as to a malformed parent, and the store's own error vocabulary is
|
|
507
|
+
* not part of this contract.
|
|
508
|
+
*
|
|
509
|
+
* @returns {(cacheKey: Key<Cache>) => (input: RevisionData) => Effect<O | MemOp, Hash, EvoChannel>}
|
|
436
510
|
*/
|
|
437
511
|
export const addRevision = cas => cacheKey => input =>
|
|
438
|
-
|
|
512
|
+
ioStep(
|
|
439
513
|
resolveParents(cas)(input.parents),
|
|
440
|
-
(/** @type {
|
|
441
|
-
const revisionResult =
|
|
442
|
-
if (revisionResult[0] === 'error') { return
|
|
514
|
+
(/** @type {readonly Revision[]} */ parents) => {
|
|
515
|
+
const revisionResult = buildRevision(input)(parents)
|
|
516
|
+
if (revisionResult[0] === 'error') { return pureError(evoError(revisionResult[1])) }
|
|
443
517
|
const canonicalRevision = revisionResult[1]
|
|
444
518
|
const bytes = tryUtf8(encodeText(canonicalRevision))
|
|
445
519
|
if (bytes === null) {
|
|
446
|
-
return
|
|
520
|
+
return pureError(evoError('revision too large to encode'))
|
|
447
521
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
522
|
+
// Annotated so the payload's operation set infers as `never`: the
|
|
523
|
+
// list is built from `pure` cells and requests no commands of its
|
|
524
|
+
// own, which `cas.write`'s `O1` has nothing else to pin it to.
|
|
525
|
+
/** @type {Effect<O, Vec, EvoError>} */
|
|
526
|
+
const written = catchStep(
|
|
527
|
+
cas.write((nonEmpty(bytes, elEmpty()))),
|
|
528
|
+
() => pureError(evoError('failed to write revision to CAS')))
|
|
529
|
+
return ioStep(
|
|
530
|
+
written,
|
|
531
|
+
(/** @type {Vec} */ writtenHash) => {
|
|
532
|
+
const hash = vecToCBase32(writtenHash)
|
|
533
|
+
return ioMapStep(foldIntoCache(cacheKey)(hash)(canonicalRevision), () => hash)
|
|
456
534
|
})
|
|
457
535
|
})
|
|
458
536
|
|
|
@@ -474,7 +552,7 @@ const toRevisionData = ({ subject, parents, snapshot, generation, archived, lock
|
|
|
474
552
|
snapshot: canonicalHash(snapshot),
|
|
475
553
|
generation,
|
|
476
554
|
archived,
|
|
477
|
-
lock: lock === undefined ? undefined :
|
|
555
|
+
lock: lock === undefined ? undefined : canonicalLockField(lock),
|
|
478
556
|
})
|
|
479
557
|
|
|
480
558
|
/**
|
|
@@ -501,17 +579,17 @@ const toRevisionData = ({ subject, parents, snapshot, generation, archived, lock
|
|
|
501
579
|
* how far it got; recovering that difference would mean folding the chunk
|
|
502
580
|
* stream here instead of reusing `collectRead`, for a distinction no client
|
|
503
581
|
* can act on differently.
|
|
504
|
-
* @type {(hash: Hash) => (result: IoResult<Vec>) => Result<RevisionData,
|
|
582
|
+
* @type {(hash: Hash) => (result: IoResult<Vec>) => Result<RevisionData, EvoError>}
|
|
505
583
|
*/
|
|
506
584
|
const decodeReadRevision = hash => ([tag, value]) => {
|
|
507
585
|
if (tag === 'error') {
|
|
508
|
-
return error(isNotFound(value)
|
|
586
|
+
return error(evoError(isNotFound(value)
|
|
509
587
|
? `revision not found: ${hash}`
|
|
510
|
-
: `failed to read revision: ${hash}`)
|
|
588
|
+
: `failed to read revision: ${hash}`))
|
|
511
589
|
}
|
|
512
590
|
const revision = decodeRevisionVec(value)
|
|
513
591
|
return revision === null
|
|
514
|
-
? error(`not a revision blob: ${hash}`)
|
|
592
|
+
? error(evoError(`not a revision blob: ${hash}`))
|
|
515
593
|
: ok(toRevisionData(revision))
|
|
516
594
|
}
|
|
517
595
|
|
|
@@ -530,13 +608,13 @@ const decodeReadRevision = hash => ([tag, value]) => {
|
|
|
530
608
|
*
|
|
531
609
|
* @template {Operation} O
|
|
532
610
|
* @param {Cas<O>} cas
|
|
533
|
-
* @returns {(hash: Hash) => Effect<O,
|
|
611
|
+
* @returns {(hash: Hash) => Effect<O, RevisionData, EvoError>}
|
|
534
612
|
*/
|
|
535
613
|
export const readRevision = cas => hash => {
|
|
536
614
|
const hashVec = cBase32ToVec(hash)
|
|
537
615
|
return hashVec === null
|
|
538
|
-
?
|
|
539
|
-
:
|
|
616
|
+
? pureError(evoError(`invalid hash: ${hash}`))
|
|
617
|
+
: resultMapStep(collectRead(cas.read(hashVec)), decodeReadRevision(hash))
|
|
540
618
|
}
|
|
541
619
|
|
|
542
620
|
/**
|
|
@@ -549,12 +627,12 @@ export const readRevision = cas => hash => {
|
|
|
549
627
|
export const evo = cas => cacheKey => ({
|
|
550
628
|
list: archived => {
|
|
551
629
|
const listed = subjectListed(archived)
|
|
552
|
-
return
|
|
630
|
+
return ioMapStep(
|
|
553
631
|
read(cacheKey),
|
|
554
632
|
cache => definedEntries(cache.bySubject)
|
|
555
633
|
.flatMap(([subject, state]) => listed(state) ? [subject] : []))
|
|
556
634
|
},
|
|
557
|
-
head: subject =>
|
|
635
|
+
head: subject => ioMapStep(read(cacheKey), cache => {
|
|
558
636
|
const state = at(subject)(cache.bySubject)
|
|
559
637
|
return state === null ? [] : headsOf(state)
|
|
560
638
|
}),
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { Cas } from '../types.ts'
|
|
3
|
+
* @import { EvoChannel } from './types.ts'
|
|
4
|
+
* @import { Result } from '../../types/result/types.ts'
|
|
5
|
+
* @import { Effect } from '../../effects/types.ts'
|
|
6
|
+
* @import { IoChannel, NodeOp } from '../../effects/node/types.ts'
|
|
7
|
+
* @import { State } from '../../effects/node/virtual/types.ts'
|
|
3
8
|
* @import { Vec } from '../../types/bit_vec/types.ts'
|
|
4
9
|
* @import { Ok } from '../../types/result/types.ts'
|
|
5
|
-
* @import { IoResult } from '../../effects/node/types.ts'
|
|
6
10
|
* @import { List } from '../../effects/list/types.ts'
|
|
7
11
|
* @import { RevisionData } from './types.ts'
|
|
8
12
|
*/
|
|
@@ -44,9 +48,14 @@ export declare const proof: {
|
|
|
44
48
|
revisionCanonicalizesReferenceSpellings: () => void;
|
|
45
49
|
revisionRoundTripsThroughAdd: () => void;
|
|
46
50
|
revisionLockRoundTripsAndCanonicalizes: () => void;
|
|
51
|
+
revisionSharedLockReferenceRoundTripsAndCanonicalizes: () => void;
|
|
52
|
+
revisionInvalidSharedLockReferenceIsRejected: () => void;
|
|
53
|
+
revisionNestedLockRoundTripsAndCanonicalizes: () => void;
|
|
54
|
+
revisionInvalidNestedLockValueIsRejected: () => void;
|
|
47
55
|
revisionAbsentAndEmptyLocksRemainDistinct: () => void;
|
|
48
56
|
revisionInvalidLockValueIsRejected: () => void;
|
|
49
57
|
equivalentLockOrdersReuseOneCasAddress: () => void;
|
|
58
|
+
equivalentNestedLockOrdersReuseOneCasAddress: () => void;
|
|
50
59
|
syncRevisionFoldsValidRevisionIntoCache: () => void;
|
|
51
60
|
syncRevisionIgnoresNonRevisionContent: () => void;
|
|
52
61
|
evoHeadUnknownSubjectIsEmpty: () => void;
|