@superbee/core 0.1.6 → 0.2.0-pre.1
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/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +29 -7
- package/dist/backend.js.map +1 -1
- package/dist/bundle-ops.d.ts +42 -0
- package/dist/bundle-ops.d.ts.map +1 -0
- package/dist/bundle-ops.js +88 -0
- package/dist/bundle-ops.js.map +1 -0
- package/dist/bundle.d.ts +8 -27
- package/dist/bundle.d.ts.map +1 -1
- package/dist/bundle.js +9 -66
- package/dist/bundle.js.map +1 -1
- package/dist/document-field-actions.d.ts +95 -0
- package/dist/document-field-actions.d.ts.map +1 -0
- package/dist/document-field-actions.js +261 -0
- package/dist/document-field-actions.js.map +1 -0
- package/dist/document-mutation.d.ts +46 -2
- package/dist/document-mutation.d.ts.map +1 -1
- package/dist/document-mutation.js +79 -19
- package/dist/document-mutation.js.map +1 -1
- package/dist/document-write-policy.d.ts +0 -1
- package/dist/document-write-policy.d.ts.map +1 -1
- package/dist/document-write-policy.js +3 -2
- package/dist/document-write-policy.js.map +1 -1
- package/dist/engine.d.ts +2 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +2 -1
- package/dist/engine.js.map +1 -1
- package/dist/freshness.d.ts +10 -7
- package/dist/freshness.d.ts.map +1 -1
- package/dist/freshness.js +14 -11
- package/dist/freshness.js.map +1 -1
- package/dist/frontmatter-contract.d.ts +2 -2
- package/dist/frontmatter-contract.js +2 -2
- package/dist/frontmatter.d.ts +3 -1
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +7 -4
- package/dist/frontmatter.js.map +1 -1
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-backend.d.ts +165 -0
- package/dist/indexeddb-backend.d.ts.map +1 -0
- package/dist/indexeddb-backend.js +718 -0
- package/dist/indexeddb-backend.js.map +1 -0
- package/dist/journaled-backend.d.ts +178 -0
- package/dist/journaled-backend.d.ts.map +1 -0
- package/dist/journaled-backend.js +77 -0
- package/dist/journaled-backend.js.map +1 -0
- package/dist/kind-field-mutation.d.ts +15 -0
- package/dist/kind-field-mutation.d.ts.map +1 -0
- package/dist/kind-field-mutation.js +160 -0
- package/dist/kind-field-mutation.js.map +1 -0
- package/dist/kinds.d.ts.map +1 -1
- package/dist/kinds.js +3 -1
- package/dist/kinds.js.map +1 -1
- package/dist/meaningful-change-time.d.ts +6 -6
- package/dist/meaningful-change-time.d.ts.map +1 -1
- package/dist/meaningful-change-time.js +12 -13
- package/dist/meaningful-change-time.js.map +1 -1
- package/dist/mutation.d.ts.map +1 -1
- package/dist/mutation.js +2 -2
- package/dist/mutation.js.map +1 -1
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +2 -1
- package/dist/page.js.map +1 -1
- package/dist/platform.d.ts +161 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +77 -0
- package/dist/platform.js.map +1 -0
- package/dist/recipes.d.ts +3 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +4 -4
- package/dist/recipes.js.map +1 -1
- package/dist/remote-backend.d.ts +28 -0
- package/dist/remote-backend.d.ts.map +1 -1
- package/dist/remote-backend.js +75 -2
- package/dist/remote-backend.js.map +1 -1
- package/dist/remote-operations.d.ts +60 -0
- package/dist/remote-operations.d.ts.map +1 -0
- package/dist/remote-operations.js +110 -0
- package/dist/remote-operations.js.map +1 -0
- package/dist/sha256.d.ts +21 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +114 -0
- package/dist/sha256.js.map +1 -0
- package/dist/storage.d.ts +5 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +7 -1
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/uncertain-write.d.ts +142 -0
- package/dist/uncertain-write.d.ts.map +1 -0
- package/dist/uncertain-write.js +174 -0
- package/dist/uncertain-write.js.map +1 -0
- package/dist/version-transport.d.ts +7 -0
- package/dist/version-transport.d.ts.map +1 -1
- package/dist/version-transport.js +9 -0
- package/dist/version-transport.js.map +1 -1
- package/dist/versioning.d.ts +9 -3
- package/dist/versioning.d.ts.map +1 -1
- package/dist/versioning.js +14 -10
- package/dist/versioning.js.map +1 -1
- package/package.json +42 -3
package/dist/sha256.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous SHA-256 (FIPS 180-4) with no runtime dependency.
|
|
3
|
+
*
|
|
4
|
+
* Version tokens are minted by {@link contentVersion}, {@link versionOfBytes} and
|
|
5
|
+
* {@link blobVersion} in `versioning.ts`, and every host that holds a working copy of a
|
|
6
|
+
* bundle must mint byte-identical tokens: the Node engine, the in-memory adapter, and a
|
|
7
|
+
* browser-local working copy in SaaS mode. A `node:crypto` import cannot be bundled for the
|
|
8
|
+
* browser, and WebCrypto's `subtle.digest` is asynchronous, which would change the
|
|
9
|
+
* synchronous version contract every backend relies on. One pure implementation shared by
|
|
10
|
+
* every runtime removes the divergence risk entirely; `test/sha256-parity.test.ts` proves it
|
|
11
|
+
* against `node:crypto` byte for byte.
|
|
12
|
+
*
|
|
13
|
+
* UTF-8 encoding goes through `TextEncoder`, which is a global in Node 18+ and in browsers.
|
|
14
|
+
* It encodes a lone surrogate as U+FFFD (EF BF BD), exactly as Node's `"utf8"` string
|
|
15
|
+
* encoding does, so string hashes agree across runtimes for malformed input as well.
|
|
16
|
+
*/
|
|
17
|
+
const K = new Uint32Array([
|
|
18
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
19
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
20
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
21
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
22
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
23
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
24
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
25
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
26
|
+
]);
|
|
27
|
+
const INITIAL_STATE = new Uint32Array([
|
|
28
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
29
|
+
]);
|
|
30
|
+
const encoder = new TextEncoder();
|
|
31
|
+
function rotr(value, bits) {
|
|
32
|
+
return (value >>> bits) | (value << (32 - bits));
|
|
33
|
+
}
|
|
34
|
+
/** Absorb one 64-byte block at `offset` of `view` into the running state `h`. */
|
|
35
|
+
function compress(h, w, view, offset) {
|
|
36
|
+
for (let i = 0; i < 16; i++) {
|
|
37
|
+
w[i] = view.getUint32(offset + i * 4);
|
|
38
|
+
}
|
|
39
|
+
for (let i = 16; i < 64; i++) {
|
|
40
|
+
const w15 = w[i - 15];
|
|
41
|
+
const w2 = w[i - 2];
|
|
42
|
+
const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ (w15 >>> 3);
|
|
43
|
+
const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ (w2 >>> 10);
|
|
44
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0;
|
|
45
|
+
}
|
|
46
|
+
let a = h[0];
|
|
47
|
+
let b = h[1];
|
|
48
|
+
let c = h[2];
|
|
49
|
+
let d = h[3];
|
|
50
|
+
let e = h[4];
|
|
51
|
+
let f = h[5];
|
|
52
|
+
let g = h[6];
|
|
53
|
+
let hh = h[7];
|
|
54
|
+
for (let i = 0; i < 64; i++) {
|
|
55
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
56
|
+
const ch = (e & f) ^ (~e & g);
|
|
57
|
+
const t1 = (hh + S1 + ch + K[i] + w[i]) >>> 0;
|
|
58
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
59
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
60
|
+
const t2 = (S0 + maj) >>> 0;
|
|
61
|
+
hh = g;
|
|
62
|
+
g = f;
|
|
63
|
+
f = e;
|
|
64
|
+
e = (d + t1) >>> 0;
|
|
65
|
+
d = c;
|
|
66
|
+
c = b;
|
|
67
|
+
b = a;
|
|
68
|
+
a = (t1 + t2) >>> 0;
|
|
69
|
+
}
|
|
70
|
+
h[0] = (h[0] + a) >>> 0;
|
|
71
|
+
h[1] = (h[1] + b) >>> 0;
|
|
72
|
+
h[2] = (h[2] + c) >>> 0;
|
|
73
|
+
h[3] = (h[3] + d) >>> 0;
|
|
74
|
+
h[4] = (h[4] + e) >>> 0;
|
|
75
|
+
h[5] = (h[5] + f) >>> 0;
|
|
76
|
+
h[6] = (h[6] + g) >>> 0;
|
|
77
|
+
h[7] = (h[7] + hh) >>> 0;
|
|
78
|
+
}
|
|
79
|
+
/** Lowercase hex SHA-256 of exact bytes. Works on any `Uint8Array` view, including a pooled Node `Buffer`. */
|
|
80
|
+
export function sha256HexOfBytes(bytes) {
|
|
81
|
+
const h = new Uint32Array(INITIAL_STATE);
|
|
82
|
+
const w = new Uint32Array(64);
|
|
83
|
+
const length = bytes.byteLength;
|
|
84
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, length);
|
|
85
|
+
// Full blocks are absorbed in place so a large blob is never copied.
|
|
86
|
+
const fullBlocks = length >>> 6;
|
|
87
|
+
for (let block = 0; block < fullBlocks; block++) {
|
|
88
|
+
compress(h, w, view, block * 64);
|
|
89
|
+
}
|
|
90
|
+
// The tail carries the remaining bytes, the 0x80 terminator, zero padding, and the
|
|
91
|
+
// 64-bit big-endian bit length, in one or two blocks.
|
|
92
|
+
const remaining = length - fullBlocks * 64;
|
|
93
|
+
const tail = new Uint8Array(remaining + 1 + 8 > 64 ? 128 : 64);
|
|
94
|
+
tail.set(bytes.subarray(fullBlocks * 64));
|
|
95
|
+
tail[remaining] = 0x80;
|
|
96
|
+
const tailView = new DataView(tail.buffer);
|
|
97
|
+
const bitLengthHigh = Math.floor(length / 0x20000000);
|
|
98
|
+
const bitLengthLow = (length << 3) >>> 0;
|
|
99
|
+
tailView.setUint32(tail.length - 8, bitLengthHigh);
|
|
100
|
+
tailView.setUint32(tail.length - 4, bitLengthLow);
|
|
101
|
+
for (let offset = 0; offset < tail.length; offset += 64) {
|
|
102
|
+
compress(h, w, tailView, offset);
|
|
103
|
+
}
|
|
104
|
+
let hex = "";
|
|
105
|
+
for (let i = 0; i < 8; i++) {
|
|
106
|
+
hex += h[i].toString(16).padStart(8, "0");
|
|
107
|
+
}
|
|
108
|
+
return hex;
|
|
109
|
+
}
|
|
110
|
+
/** Lowercase hex SHA-256 of a string's UTF-8 bytes. */
|
|
111
|
+
export function sha256HexOfUtf8(input) {
|
|
112
|
+
return sha256HexOfBytes(encoder.encode(input));
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=sha256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../src/sha256.ts"],"names":[],"mappings":"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"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -3,5 +3,9 @@ export type { BlobKey, ConceptId, DeleteOptions, Frontmatter, HeadResult, OkfDoc
|
|
|
3
3
|
export { InvalidInputError } from "./errors.js";
|
|
4
4
|
export { MalformedDocumentError } from "./frontmatter-contract.js";
|
|
5
5
|
export { RESERVED_FILENAMES, assertSafeBlobKey, assertSafeConceptId, assertSafeReservedDir, conceptIdFromPath, isReservedFile, pathFromConceptId, toPosix, } from "./paths.js";
|
|
6
|
-
export { VersionConflict, stripETagWrapper } from "./version-transport.js";
|
|
6
|
+
export { VersionConflict, isContentVersion, stripETagWrapper } from "./version-transport.js";
|
|
7
|
+
export { IntentHoldConflict, IntentStateConflict } from "./journaled-backend.js";
|
|
8
|
+
export type { IntentPatch, IntentRecord, JournaledBackend, JournaledReadResult, JournaledWriteOptions, MetaRecord, NewIntentRecord, } from "./journaled-backend.js";
|
|
9
|
+
export { isRequestIdentity } from "./uncertain-write.js";
|
|
10
|
+
export type { Outcome } from "./uncertain-write.js";
|
|
7
11
|
//# sourceMappingURL=storage.d.ts.map
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,YAAY,EACV,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,YAAY,EACV,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG7F,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACjF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/storage.js
CHANGED
|
@@ -2,5 +2,11 @@
|
|
|
2
2
|
export { InvalidInputError } from "./errors.js";
|
|
3
3
|
export { MalformedDocumentError } from "./frontmatter-contract.js";
|
|
4
4
|
export { RESERVED_FILENAMES, assertSafeBlobKey, assertSafeConceptId, assertSafeReservedDir, conceptIdFromPath, isReservedFile, pathFromConceptId, toPosix, } from "./paths.js";
|
|
5
|
-
export { VersionConflict, stripETagWrapper } from "./version-transport.js";
|
|
5
|
+
export { VersionConflict, isContentVersion, stripETagWrapper } from "./version-transport.js";
|
|
6
|
+
// The journaled-backend seam: what an adapter adds to `StorageBackend` to host a browser-local
|
|
7
|
+
// working copy's intent journal. Runtime-neutral, like the seam it extends.
|
|
8
|
+
export { IntentHoldConflict, IntentStateConflict } from "./journaled-backend.js";
|
|
9
|
+
// The wire request identity (`WriteOptions.requestId`) and the outcome shape an authority records
|
|
10
|
+
// for it: runtime-neutral, so Worker and browser consumers reach them through this seam.
|
|
11
|
+
export { isRequestIdentity } from "./uncertain-write.js";
|
|
6
12
|
//# sourceMappingURL=storage.js.map
|
package/dist/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAqB1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAqB1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,+FAA+F;AAC/F,4EAA4E;AAC5E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAUjF,kGAAkG;AAClG,yFAAyF;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -177,6 +177,12 @@ export interface WriteOptions {
|
|
|
177
177
|
* affects CAS or cross-backend token parity.
|
|
178
178
|
*/
|
|
179
179
|
agent?: string;
|
|
180
|
+
/**
|
|
181
|
+
* OPTIONAL durable request identity. A remote backend sends it as the wire's `Idempotency-Key`
|
|
182
|
+
* so the authority applies the write at most once under that key and can report its outcome
|
|
183
|
+
* later; every other backend ignores it. Minted once per intent and reused verbatim on retry.
|
|
184
|
+
*/
|
|
185
|
+
requestId?: string;
|
|
180
186
|
}
|
|
181
187
|
/**
|
|
182
188
|
* Options controlling a conditional {@link StorageBackend.delete} / {@link
|
|
@@ -196,6 +202,12 @@ export interface DeleteOptions {
|
|
|
196
202
|
* regardless of `expectedVersion` (idempotency, AXI P6: absence is success, not failure).
|
|
197
203
|
*/
|
|
198
204
|
expectedVersion?: Version;
|
|
205
|
+
/**
|
|
206
|
+
* OPTIONAL durable request identity, sent by a remote backend as `Idempotency-Key` exactly as
|
|
207
|
+
* {@link WriteOptions.requestId} is. The wire requires `expectedVersion` alongside it: an
|
|
208
|
+
* identified delete must name the revision it removes. Other backends ignore it.
|
|
209
|
+
*/
|
|
210
|
+
requestId?: string;
|
|
199
211
|
}
|
|
200
212
|
/** Optional backend capabilities reported without adapter-class inference. */
|
|
201
213
|
export interface StorageCapabilities {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,uJAAuJ;IACvJ,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iHAAiH;IACjH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qFAAqF;AACrF,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,EAAE,EAAE,SAAS,CAAC;IACd,+BAA+B;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+EAA+E;AAC/E,MAAM,WAAW,MAAM;IACrB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,uGAAuG;AACvG,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,GAAG,EAAE,WAAW,CAAC;IACjB,iIAAiI;IACjI,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,EAAE,EAAE,SAAS,CAAC;IACd,8CAA8C;IAC9C,WAAW,EAAE,WAAW,CAAC;IACzB,mKAAmK;IACnK,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,KAAK,EAAE,UAAU,CAAC;IAClB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,+GAA+G;AAC/G,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,iHAAiH;IACjH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared uncertain-write primitive: durable request identity, unknown-outcome handling, and
|
|
3
|
+
* acknowledgement reconciliation for a write whose delivery to a shared authority may be lost.
|
|
4
|
+
*
|
|
5
|
+
* A network write has three answers, not two: the authority applied it, refused it, or the
|
|
6
|
+
* client cannot tell (a dropped response, a timeout, a transport error). Retrying a write in the
|
|
7
|
+
* third case is only safe when the authority can recognize the retry as the same request, so
|
|
8
|
+
* every write carries a {@link OperationIntent.requestId} minted once when the intent is first
|
|
9
|
+
* recorded and never reminted, and every transport offers {@link OperationTransport.lookup} to
|
|
10
|
+
* fetch the authority's recorded outcome for that id.
|
|
11
|
+
*
|
|
12
|
+
* This module is owned by core so the browser-local sync component and bounded CLI remote
|
|
13
|
+
* operations consume one primitive rather than each defining unknown-outcome handling. It
|
|
14
|
+
* imports no Node builtin and bundles for the browser. The only injected time source is the
|
|
15
|
+
* `sleep` used for the submission deadline and the delay between lookups; there is no
|
|
16
|
+
* injectable clock, and a transport's own latency is real.
|
|
17
|
+
*/
|
|
18
|
+
import type { Version } from "./types.js";
|
|
19
|
+
/** The operation an intent performs. Only document writes exist today; the union is open. */
|
|
20
|
+
export type OperationKind = "document.write" | (string & {});
|
|
21
|
+
/**
|
|
22
|
+
* The journal states of an intent. `unknown` is the primitive's own classification of an
|
|
23
|
+
* exhausted attempt: the authority may or may not hold the write, and a later attempt begins
|
|
24
|
+
* with a lookup rather than a submission.
|
|
25
|
+
*/
|
|
26
|
+
export type OperationState = "pending" | "in_flight" | "acknowledged" | "conflict" | "refused" | "unknown";
|
|
27
|
+
/** A recorded local write awaiting a shared outcome. */
|
|
28
|
+
export interface OperationIntent {
|
|
29
|
+
/** Durable request identity: minted once at record time, reused verbatim on every retry. */
|
|
30
|
+
requestId: string;
|
|
31
|
+
kind: OperationKind;
|
|
32
|
+
/** The target the operation applies to; a concept id for `document.write`. */
|
|
33
|
+
target: string;
|
|
34
|
+
/** The shared version the local edit was made against, or `null` for a create. */
|
|
35
|
+
base: Version | null;
|
|
36
|
+
/** The content-addressed version of `content`. */
|
|
37
|
+
local: Version;
|
|
38
|
+
/** The serialized document: the comparison content reconciliation needs later. */
|
|
39
|
+
content: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
/**
|
|
42
|
+
* Submissions made or durably claimed so far. A non-zero count means the authority may already
|
|
43
|
+
* hold the write, so delivery begins with a lookup rather than a submission; a journal records
|
|
44
|
+
* the count before a submission leaves, never only after its outcome is known.
|
|
45
|
+
*/
|
|
46
|
+
attempts: number;
|
|
47
|
+
state: OperationState;
|
|
48
|
+
}
|
|
49
|
+
/** The authority's answer for one request identity. */
|
|
50
|
+
export type Outcome = {
|
|
51
|
+
kind: "committed";
|
|
52
|
+
version: Version;
|
|
53
|
+
} | {
|
|
54
|
+
kind: "conflict";
|
|
55
|
+
actual: Version | null;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "refused";
|
|
58
|
+
code: string;
|
|
59
|
+
message: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: "unknown";
|
|
62
|
+
};
|
|
63
|
+
/** A transport to a shared authority that records outcomes by request identity. */
|
|
64
|
+
export interface OperationTransport {
|
|
65
|
+
/** Deliver the intent once; a repeated `requestId` must return the recorded outcome unchanged. */
|
|
66
|
+
submit(intent: OperationIntent, options?: {
|
|
67
|
+
signal?: AbortSignal;
|
|
68
|
+
}): Promise<Outcome>;
|
|
69
|
+
/** The recorded outcome for `requestId`, or `null` when the authority never recorded it. */
|
|
70
|
+
lookup(requestId: string): Promise<Outcome | null>;
|
|
71
|
+
}
|
|
72
|
+
/** Wait `ms`, resolving early and harmlessly when `signal` aborts. Injected by tests. */
|
|
73
|
+
export type Sleep = (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
74
|
+
export interface UncertainWriteOptions {
|
|
75
|
+
/** How long one submission may take before its outcome is treated as unknown. */
|
|
76
|
+
deadlineMs?: number;
|
|
77
|
+
/** Lookups attempted after an unknown submission before giving up (default 3). */
|
|
78
|
+
maxLookups?: number;
|
|
79
|
+
/** Delay between lookups (default 250 ms; the injected `sleep` decides what that means). */
|
|
80
|
+
lookupDelayMs?: number;
|
|
81
|
+
/** Submissions permitted in one call, counting the first (default 2). */
|
|
82
|
+
maxSubmissions?: number;
|
|
83
|
+
/** Timer; defaults to a `setTimeout` sleep. */
|
|
84
|
+
sleep?: Sleep;
|
|
85
|
+
}
|
|
86
|
+
export interface UncertainWriteResult {
|
|
87
|
+
/** The intent with `attempts` and `state` advanced to reflect this call. */
|
|
88
|
+
intent: OperationIntent;
|
|
89
|
+
outcome: Outcome;
|
|
90
|
+
/** How many times `lookup` was called in this call. */
|
|
91
|
+
lookups: number;
|
|
92
|
+
}
|
|
93
|
+
/** Refusal codes that mean the caller's authorization is gone rather than the content wrong. */
|
|
94
|
+
export declare const AUTHORIZATION_REFUSAL_CODES: ReadonlySet<string>;
|
|
95
|
+
/** True when a refusal reports lost permission, which pauses further shared operations. */
|
|
96
|
+
export declare function isAuthorizationRefusal(outcome: Outcome): boolean;
|
|
97
|
+
/** The journal state an outcome settles an intent into. */
|
|
98
|
+
export declare function stateForOutcome(outcome: Outcome): OperationState;
|
|
99
|
+
/** The longest request identity the wire accepts as `Idempotency-Key`. */
|
|
100
|
+
export declare const REQUEST_ID_MAX_LENGTH = 128;
|
|
101
|
+
/**
|
|
102
|
+
* True when `value` is a request identity the wire accepts: 1 to {@link REQUEST_ID_MAX_LENGTH}
|
|
103
|
+
* printable ASCII characters with no space, and neither `.` nor `..`, which URL normalization
|
|
104
|
+
* folds away so the lookup route could never name them. One rule, checked by the client before
|
|
105
|
+
* a header is built and by the reference router before a key is claimed, so the two sides cannot
|
|
106
|
+
* disagree about which keys identify a write. A minted UUID always satisfies it.
|
|
107
|
+
*/
|
|
108
|
+
export declare function isRequestIdentity(value: string): boolean;
|
|
109
|
+
/** A fresh request identity. UUIDs come from the platform's `crypto` in both Node and browsers. */
|
|
110
|
+
export declare function mintRequestId(): string;
|
|
111
|
+
/**
|
|
112
|
+
* The outcome as it applies to `intent`. A conflict whose `actual` is the intent's own `local`
|
|
113
|
+
* version means the shared head already holds exactly this content, so the write is committed
|
|
114
|
+
* at that version. This is the wire's post-expiry compare-and-swap property: a committed write
|
|
115
|
+
* whose acknowledgement was lost and whose recorded outcome expired from the authority's
|
|
116
|
+
* retention window is resubmitted with its original `base`, which no longer matches, and the
|
|
117
|
+
* authority answers a conflict against the version the client itself committed. The mapping
|
|
118
|
+
* depends only on the outcome and the intent, so the primitive owns it and every consumer
|
|
119
|
+
* settles such a write as acknowledged rather than presenting it as a concurrent edit. Every
|
|
120
|
+
* other conflict, including one against an absent head (`actual: null`), is returned unchanged.
|
|
121
|
+
*/
|
|
122
|
+
export declare function settleAgainstIntent(outcome: Outcome, intent: OperationIntent): Outcome;
|
|
123
|
+
/**
|
|
124
|
+
* Deliver `intent` and settle it against the authority's recorded outcome.
|
|
125
|
+
*
|
|
126
|
+
* Flow: when the intent has never been submitted, submit it; when it has (`attempts > 0`), or
|
|
127
|
+
* when a submission's outcome is unknown, look the request identity up. A positive lookup
|
|
128
|
+
* settles the intent. A `null` lookup proves the authority never recorded the request, so a
|
|
129
|
+
* resubmission with the same `requestId` is the first delivery and is allowed, up to
|
|
130
|
+
* `maxSubmissions`. A lookup that fails leaves the outcome unknown and the intent for a later
|
|
131
|
+
* call.
|
|
132
|
+
*
|
|
133
|
+
* No resubmission happens without a `null` lookup because a blind retry after an unknown
|
|
134
|
+
* outcome is unsound: on an authority without request identity the retry applies the write
|
|
135
|
+
* twice, and even on one with it the retry can only ever learn what the lookup already knew.
|
|
136
|
+
* The lookup is what turns "unknown" into a fact before any second delivery.
|
|
137
|
+
*
|
|
138
|
+
* Every outcome passes through {@link settleAgainstIntent} before it is returned, so a conflict
|
|
139
|
+
* that names the intent's own version is reported as committed at that version.
|
|
140
|
+
*/
|
|
141
|
+
export declare function performUncertainWrite(transport: OperationTransport, intent: OperationIntent, options?: UncertainWriteOptions): Promise<UncertainWriteResult>;
|
|
142
|
+
//# sourceMappingURL=uncertain-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uncertain-write.d.ts","sourceRoot":"","sources":["../src/uncertain-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE7D;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3G,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,4FAA4F;IAC5F,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,kDAAkD;IAClD,KAAK,EAAE,OAAO,CAAC;IACf,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,uDAAuD;AACvD,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,4FAA4F;IAC5F,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACpD;AAED,yFAAyF;AACzF,MAAM,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExE,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gGAAgG;AAChG,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAAgF,CAAC;AAE7I,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEhE;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAWhE;AAED,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,mGAAmG;AACnG,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAqBD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAKtF;AAwBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC,CAyC/B"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared uncertain-write primitive: durable request identity, unknown-outcome handling, and
|
|
3
|
+
* acknowledgement reconciliation for a write whose delivery to a shared authority may be lost.
|
|
4
|
+
*
|
|
5
|
+
* A network write has three answers, not two: the authority applied it, refused it, or the
|
|
6
|
+
* client cannot tell (a dropped response, a timeout, a transport error). Retrying a write in the
|
|
7
|
+
* third case is only safe when the authority can recognize the retry as the same request, so
|
|
8
|
+
* every write carries a {@link OperationIntent.requestId} minted once when the intent is first
|
|
9
|
+
* recorded and never reminted, and every transport offers {@link OperationTransport.lookup} to
|
|
10
|
+
* fetch the authority's recorded outcome for that id.
|
|
11
|
+
*
|
|
12
|
+
* This module is owned by core so the browser-local sync component and bounded CLI remote
|
|
13
|
+
* operations consume one primitive rather than each defining unknown-outcome handling. It
|
|
14
|
+
* imports no Node builtin and bundles for the browser. The only injected time source is the
|
|
15
|
+
* `sleep` used for the submission deadline and the delay between lookups; there is no
|
|
16
|
+
* injectable clock, and a transport's own latency is real.
|
|
17
|
+
*/
|
|
18
|
+
/** Refusal codes that mean the caller's authorization is gone rather than the content wrong. */
|
|
19
|
+
export const AUTHORIZATION_REFUSAL_CODES = new Set(["AUTH_REQUIRED", "FORBIDDEN", "UNAUTHORIZED", "PERMISSION_DENIED"]);
|
|
20
|
+
/** True when a refusal reports lost permission, which pauses further shared operations. */
|
|
21
|
+
export function isAuthorizationRefusal(outcome) {
|
|
22
|
+
return outcome.kind === "refused" && AUTHORIZATION_REFUSAL_CODES.has(outcome.code);
|
|
23
|
+
}
|
|
24
|
+
/** The journal state an outcome settles an intent into. */
|
|
25
|
+
export function stateForOutcome(outcome) {
|
|
26
|
+
switch (outcome.kind) {
|
|
27
|
+
case "committed":
|
|
28
|
+
return "acknowledged";
|
|
29
|
+
case "conflict":
|
|
30
|
+
return "conflict";
|
|
31
|
+
case "refused":
|
|
32
|
+
return "refused";
|
|
33
|
+
case "unknown":
|
|
34
|
+
return "unknown";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** The longest request identity the wire accepts as `Idempotency-Key`. */
|
|
38
|
+
export const REQUEST_ID_MAX_LENGTH = 128;
|
|
39
|
+
/**
|
|
40
|
+
* True when `value` is a request identity the wire accepts: 1 to {@link REQUEST_ID_MAX_LENGTH}
|
|
41
|
+
* printable ASCII characters with no space, and neither `.` nor `..`, which URL normalization
|
|
42
|
+
* folds away so the lookup route could never name them. One rule, checked by the client before
|
|
43
|
+
* a header is built and by the reference router before a key is claimed, so the two sides cannot
|
|
44
|
+
* disagree about which keys identify a write. A minted UUID always satisfies it.
|
|
45
|
+
*/
|
|
46
|
+
export function isRequestIdentity(value) {
|
|
47
|
+
if (value === "." || value === "..")
|
|
48
|
+
return false;
|
|
49
|
+
return value.length >= 1 && value.length <= REQUEST_ID_MAX_LENGTH && /^[!-~]+$/.test(value);
|
|
50
|
+
}
|
|
51
|
+
/** A fresh request identity. UUIDs come from the platform's `crypto` in both Node and browsers. */
|
|
52
|
+
export function mintRequestId() {
|
|
53
|
+
const cryptoApi = globalThis.crypto;
|
|
54
|
+
if (cryptoApi && typeof cryptoApi.randomUUID === "function")
|
|
55
|
+
return cryptoApi.randomUUID();
|
|
56
|
+
throw new Error("mintRequestId requires crypto.randomUUID in this host.");
|
|
57
|
+
}
|
|
58
|
+
const defaultSleep = (ms, signal) => new Promise((resolve) => {
|
|
59
|
+
if (signal?.aborted) {
|
|
60
|
+
resolve();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const timer = setTimeout(() => {
|
|
64
|
+
signal?.removeEventListener("abort", onAbort);
|
|
65
|
+
resolve();
|
|
66
|
+
}, ms);
|
|
67
|
+
function onAbort() {
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
resolve();
|
|
70
|
+
}
|
|
71
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
72
|
+
});
|
|
73
|
+
const UNKNOWN = { kind: "unknown" };
|
|
74
|
+
/**
|
|
75
|
+
* The outcome as it applies to `intent`. A conflict whose `actual` is the intent's own `local`
|
|
76
|
+
* version means the shared head already holds exactly this content, so the write is committed
|
|
77
|
+
* at that version. This is the wire's post-expiry compare-and-swap property: a committed write
|
|
78
|
+
* whose acknowledgement was lost and whose recorded outcome expired from the authority's
|
|
79
|
+
* retention window is resubmitted with its original `base`, which no longer matches, and the
|
|
80
|
+
* authority answers a conflict against the version the client itself committed. The mapping
|
|
81
|
+
* depends only on the outcome and the intent, so the primitive owns it and every consumer
|
|
82
|
+
* settles such a write as acknowledged rather than presenting it as a concurrent edit. Every
|
|
83
|
+
* other conflict, including one against an absent head (`actual: null`), is returned unchanged.
|
|
84
|
+
*/
|
|
85
|
+
export function settleAgainstIntent(outcome, intent) {
|
|
86
|
+
if (outcome.kind === "conflict" && outcome.actual !== null && outcome.actual === intent.local) {
|
|
87
|
+
return { kind: "committed", version: outcome.actual };
|
|
88
|
+
}
|
|
89
|
+
return outcome;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* One submission under a deadline. A transport rejection or a deadline overrun both yield
|
|
93
|
+
* `unknown`: the request may have reached the authority, so nothing here decides otherwise.
|
|
94
|
+
*/
|
|
95
|
+
async function submitOnce(transport, intent, deadlineMs, sleep) {
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
const attempt = transport.submit(intent, { signal: controller.signal }).then((outcome) => ({ settled: true, outcome }), () => ({ settled: true, outcome: UNKNOWN }));
|
|
98
|
+
if (deadlineMs === undefined)
|
|
99
|
+
return (await attempt).outcome;
|
|
100
|
+
const timerControl = new AbortController();
|
|
101
|
+
const deadline = sleep(deadlineMs, timerControl.signal).then(() => ({ settled: false }));
|
|
102
|
+
const first = await Promise.race([attempt, deadline]);
|
|
103
|
+
if (first.settled) {
|
|
104
|
+
timerControl.abort();
|
|
105
|
+
return first.outcome;
|
|
106
|
+
}
|
|
107
|
+
controller.abort();
|
|
108
|
+
return UNKNOWN;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Deliver `intent` and settle it against the authority's recorded outcome.
|
|
112
|
+
*
|
|
113
|
+
* Flow: when the intent has never been submitted, submit it; when it has (`attempts > 0`), or
|
|
114
|
+
* when a submission's outcome is unknown, look the request identity up. A positive lookup
|
|
115
|
+
* settles the intent. A `null` lookup proves the authority never recorded the request, so a
|
|
116
|
+
* resubmission with the same `requestId` is the first delivery and is allowed, up to
|
|
117
|
+
* `maxSubmissions`. A lookup that fails leaves the outcome unknown and the intent for a later
|
|
118
|
+
* call.
|
|
119
|
+
*
|
|
120
|
+
* No resubmission happens without a `null` lookup because a blind retry after an unknown
|
|
121
|
+
* outcome is unsound: on an authority without request identity the retry applies the write
|
|
122
|
+
* twice, and even on one with it the retry can only ever learn what the lookup already knew.
|
|
123
|
+
* The lookup is what turns "unknown" into a fact before any second delivery.
|
|
124
|
+
*
|
|
125
|
+
* Every outcome passes through {@link settleAgainstIntent} before it is returned, so a conflict
|
|
126
|
+
* that names the intent's own version is reported as committed at that version.
|
|
127
|
+
*/
|
|
128
|
+
export async function performUncertainWrite(transport, intent, options = {}) {
|
|
129
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
130
|
+
const maxLookups = Math.max(1, options.maxLookups ?? 3);
|
|
131
|
+
const maxSubmissions = Math.max(1, options.maxSubmissions ?? 2);
|
|
132
|
+
const lookupDelayMs = options.lookupDelayMs ?? 250;
|
|
133
|
+
let attempts = intent.attempts;
|
|
134
|
+
let submissions = 0;
|
|
135
|
+
let lookups = 0;
|
|
136
|
+
const finish = (raw) => {
|
|
137
|
+
const outcome = settleAgainstIntent(raw, intent);
|
|
138
|
+
return { intent: { ...intent, attempts, state: stateForOutcome(outcome) }, outcome, lookups };
|
|
139
|
+
};
|
|
140
|
+
// A previously submitted intent starts at the lookup, never at a submission.
|
|
141
|
+
let needSubmission = attempts === 0;
|
|
142
|
+
for (;;) {
|
|
143
|
+
if (needSubmission) {
|
|
144
|
+
if (submissions >= maxSubmissions)
|
|
145
|
+
return finish(UNKNOWN);
|
|
146
|
+
submissions += 1;
|
|
147
|
+
attempts += 1;
|
|
148
|
+
const outcome = await submitOnce(transport, { ...intent, attempts, state: "in_flight" }, options.deadlineMs, sleep);
|
|
149
|
+
if (outcome.kind !== "unknown")
|
|
150
|
+
return finish(outcome);
|
|
151
|
+
}
|
|
152
|
+
needSubmission = false;
|
|
153
|
+
let recorded;
|
|
154
|
+
for (let round = 0; round < maxLookups; round++) {
|
|
155
|
+
if (round > 0)
|
|
156
|
+
await sleep(lookupDelayMs);
|
|
157
|
+
lookups += 1;
|
|
158
|
+
try {
|
|
159
|
+
recorded = await transport.lookup(intent.requestId);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
recorded = undefined;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
if (recorded === undefined)
|
|
168
|
+
return finish(UNKNOWN);
|
|
169
|
+
if (recorded !== null)
|
|
170
|
+
return finish(recorded);
|
|
171
|
+
needSubmission = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=uncertain-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uncertain-write.js","sourceRoot":"","sources":["../src/uncertain-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/** Runtime-neutral version transport primitives shared by storage adapters and HTTP clients. */
|
|
2
2
|
import type { Version } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* True only for a content-addressed {@link Version} token as every conforming backend mints it:
|
|
5
|
+
* `sha256:` followed by 64 lowercase hex characters. One rule, shared by the reference router
|
|
6
|
+
* (an identified delete's premise) and the View registry (an entry pin), so no adapter carries
|
|
7
|
+
* its own reading of what a version looks like.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isContentVersion(value: unknown): value is Version;
|
|
3
10
|
/** Recover a bare version token from a quoted or weak HTTP ETag. */
|
|
4
11
|
export declare function stripETagWrapper(raw: string): string;
|
|
5
12
|
/** Typed optimistic-concurrency rejection raised by every conforming backend. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-transport.d.ts","sourceRoot":"","sources":["../src/version-transport.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOpD;AAED,iFAAiF;AACjF,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,qBAAqB;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;gBAEpB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;CASzE"}
|
|
1
|
+
{"version":3,"file":"version-transport.d.ts","sourceRoot":"","sources":["../src/version-transport.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAEjE;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOpD;AAED,iFAAiF;AACjF,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,qBAAqB;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;gBAEpB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;CASzE"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
/** Runtime-neutral version transport primitives shared by storage adapters and HTTP clients. */
|
|
2
|
+
/**
|
|
3
|
+
* True only for a content-addressed {@link Version} token as every conforming backend mints it:
|
|
4
|
+
* `sha256:` followed by 64 lowercase hex characters. One rule, shared by the reference router
|
|
5
|
+
* (an identified delete's premise) and the View registry (an entry pin), so no adapter carries
|
|
6
|
+
* its own reading of what a version looks like.
|
|
7
|
+
*/
|
|
8
|
+
export function isContentVersion(value) {
|
|
9
|
+
return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
10
|
+
}
|
|
2
11
|
/** Recover a bare version token from a quoted or weak HTTP ETag. */
|
|
3
12
|
export function stripETagWrapper(raw) {
|
|
4
13
|
let value = raw.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-transport.js","sourceRoot":"","sources":["../src/version-transport.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAIhG,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AACjF,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACtB,IAAI,GAAG,iBAAiB,CAAC;IAClC,EAAE,CAAS;IACX,QAAQ,CAAiB;IACzB,MAAM,CAAiB;IAEhC,YAAY,EAAU,EAAE,QAAwB,EAAE,MAAsB;QACtE,KAAK,CACH,wBAAwB,EAAE,eAAe,QAAQ,IAAI,QAAQ,WAAW,MAAM,IAAI,MAAM,GAAG;YACzF,8DAA8D,CACjE,CAAC;QACF,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"version-transport.js","sourceRoot":"","sources":["../src/version-transport.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAIhG;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AACjF,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACtB,IAAI,GAAG,iBAAiB,CAAC;IAClC,EAAE,CAAS;IACX,QAAQ,CAAiB;IACzB,MAAM,CAAiB;IAEhC,YAAY,EAAU,EAAE,QAAwB,EAAE,MAAsB;QACtE,KAAK,CACH,wBAAwB,EAAE,eAAe,QAAQ,IAAI,QAAQ,WAAW,MAAM,IAAI,MAAM,GAAG;YACzF,8DAA8D,CACjE,CAAC;QACF,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|
package/dist/versioning.d.ts
CHANGED
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
* the caller's `expectedVersion` no longer matches the backend's current version.
|
|
18
18
|
*
|
|
19
19
|
* Nothing here touches the filesystem — hashing and attribution are backend-neutral,
|
|
20
|
-
* which is precisely why the memory adapter can reuse them.
|
|
20
|
+
* which is precisely why the memory adapter can reuse them. The digest itself lives in
|
|
21
|
+
* `sha256.ts`, a pure implementation with no `node:*` import, so this module and the memory
|
|
22
|
+
* adapter bundle for the browser and mint the same tokens there.
|
|
21
23
|
*/
|
|
22
24
|
import type { OkfDocument, Version } from "./types.js";
|
|
23
|
-
export { VersionConflict, stripETagWrapper } from "./version-transport.js";
|
|
25
|
+
export { VersionConflict, isContentVersion, stripETagWrapper } from "./version-transport.js";
|
|
24
26
|
/** Lowercase hex SHA-256 of a UTF-8 string. The version tokens' underlying digest. */
|
|
25
27
|
export declare function sha256Hex(input: string): string;
|
|
26
28
|
/**
|
|
@@ -43,6 +45,10 @@ export declare function versionOfBytes(raw: string): Version;
|
|
|
43
45
|
* of adapter, exactly as {@link contentVersion} is for documents.
|
|
44
46
|
*/
|
|
45
47
|
export declare function blobVersion(bytes: Uint8Array): Version;
|
|
46
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* A local identity for unattributed writes: `$USER`/`$USERNAME`/`$LOGNAME`, else `"local"`.
|
|
50
|
+
* A browser host has no `process` global, so the environment lookup is guarded and such a
|
|
51
|
+
* host attributes to `"local"`.
|
|
52
|
+
*/
|
|
47
53
|
export declare function defaultActor(): string;
|
|
48
54
|
//# sourceMappingURL=versioning.d.ts.map
|
package/dist/versioning.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../src/versioning.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../src/versioning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAExD;AAED,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
|