@openlfcp/shared-objects 0.1.4 → 0.2.0-beta.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/README.md +15 -2
- package/dist/admission/actor.d.ts +16 -0
- package/dist/admission/actor.js +35 -0
- package/dist/{canonical.d.ts → admission/canonical.d.ts} +2 -0
- package/dist/{canonical.js → admission/canonical.js} +9 -2
- package/dist/{automerge-bytes.d.ts → admission/framing.d.ts} +32 -1
- package/dist/admission/framing.js +231 -0
- package/dist/admission/index.d.ts +26 -0
- package/dist/admission/index.js +26 -0
- package/dist/{chunk-limits.d.ts → admission/limits.d.ts} +11 -1
- package/dist/{chunk-limits.js → admission/limits.js} +25 -10
- package/dist/{references.d.ts → admission/references.d.ts} +1 -1
- package/dist/{references.js → admission/references.js} +11 -0
- package/dist/admission/sequence.d.ts +81 -0
- package/dist/admission/sequence.js +133 -0
- package/dist/data-profile.d.ts +1 -1
- package/dist/data-profile.js +3 -7
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/replica.d.ts +38 -2
- package/dist/replica.js +177 -214
- package/dist/sections/admission.d.ts +35 -0
- package/dist/sections/admission.js +328 -0
- package/dist/sections/data-profile.d.ts +195 -0
- package/dist/sections/data-profile.js +383 -0
- package/dist/sections/dispatch.d.ts +41 -0
- package/dist/sections/dispatch.js +33 -0
- package/dist/sections/document.d.ts +54 -0
- package/dist/sections/document.js +101 -0
- package/dist/sections/index.d.ts +18 -0
- package/dist/sections/index.js +18 -0
- package/dist/sections/replica.d.ts +412 -0
- package/dist/sections/replica.js +1149 -0
- package/dist/sections/schema.d.ts +77 -0
- package/dist/sections/schema.js +548 -0
- package/dist/sections/tree.d.ts +83 -0
- package/dist/sections/tree.js +290 -0
- package/dist/sections/values.d.ts +30 -0
- package/dist/sections/values.js +36 -0
- package/dist/values.d.ts +3 -18
- package/dist/values.js +7 -95
- package/package.json +12 -4
- package/dist/automerge-bytes.js +0 -111
package/dist/automerge-bytes.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
2
|
-
import { toHex } from "@openlfcp/core";
|
|
3
|
-
import { checkCanonicalChange } from "./canonical.js";
|
|
4
|
-
import { checkChangeExpansion } from "./chunk-limits.js";
|
|
5
|
-
import { ProfileInvalidError } from "./profile-invalid.js";
|
|
6
|
-
import { frameProfilePayload, unframeProfilePayload } from "./values.js";
|
|
7
|
-
/**
|
|
8
|
-
* Automerge byte checks of the SHARED-OBJECTS-PROFILE-01 payloads (LFCP-031):
|
|
9
|
-
* a Data Unit plaintext carries exactly one Automerge change (§11, §12), a
|
|
10
|
-
* Snapshot plaintext one Automerge full save (§13). The framing itself is
|
|
11
|
-
* frameProfilePayload / unframeProfilePayload (LFCP-030); this adds the
|
|
12
|
-
* check that the framed bytes are what they claim to be.
|
|
13
|
-
*
|
|
14
|
-
* Automerge storage chunks start with the magic bytes 85 6f 4a 83, a 4-byte
|
|
15
|
-
* checksum (the first 4 bytes of the chunk hash) and a chunk type: 0 for a
|
|
16
|
-
* document (a full save), 1 for a change, 2 for a compressed change.
|
|
17
|
-
*/
|
|
18
|
-
const MAGIC = [0x85, 0x6f, 0x4a, 0x83];
|
|
19
|
-
const CHUNK_DOCUMENT = 0;
|
|
20
|
-
const CHUNK_CHANGE = 1;
|
|
21
|
-
const CHUNK_COMPRESSED_CHANGE = 2;
|
|
22
|
-
const HEADER = 9; // magic, checksum, chunk type
|
|
23
|
-
/** §11, §13, §74.1: PROFILE_INVALID / INVALID_AUTOMERGE_BYTES. */
|
|
24
|
-
const reject = (why) => {
|
|
25
|
-
throw new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", why);
|
|
26
|
-
};
|
|
27
|
-
function chunkType(bytes, what) {
|
|
28
|
-
if (bytes.length < HEADER || MAGIC.some((b, i) => bytes[i] !== b))
|
|
29
|
-
return reject(`${what} is not an Automerge chunk`);
|
|
30
|
-
return bytes[8];
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Checks that `bytes` is exactly one valid Automerge change (§11, §12) and
|
|
34
|
-
* returns it decoded. Rejects with PROFILE_INVALID / INVALID_AUTOMERGE_BYTES: a chunk that is not a
|
|
35
|
-
* change (a document chunk is a full save, §13), bytes Automerge cannot
|
|
36
|
-
* parse, trailing bytes such as a second concatenated change, and a
|
|
37
|
-
* checksum that does not match the change hash. Automerge JS 3.5.0 parses
|
|
38
|
-
* a change without verifying its checksum, so the check is done here.
|
|
39
|
-
*/
|
|
40
|
-
export function checkChange(bytes) {
|
|
41
|
-
const type = chunkType(bytes, "the change");
|
|
42
|
-
if (type === CHUNK_COMPRESSED_CHANGE)
|
|
43
|
-
reject("a compressed Automerge change (chunk type 2): a change is uncompressed (§11)");
|
|
44
|
-
if (type !== CHUNK_CHANGE)
|
|
45
|
-
reject(`chunk type ${type} is not an Automerge change (§11)`);
|
|
46
|
-
// §11.1: what the change expands to and its structure, before Automerge decodes it.
|
|
47
|
-
const expansion = checkChangeExpansion(bytes);
|
|
48
|
-
// §11.3: the canonical encoding, by the format's properties, still before the engine.
|
|
49
|
-
const parsed = checkCanonicalChange(bytes);
|
|
50
|
-
let decoded;
|
|
51
|
-
try {
|
|
52
|
-
decoded = A.decodeChange(bytes);
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
return reject(`invalid Automerge change bytes (§11): ${e.message}`);
|
|
56
|
-
}
|
|
57
|
-
if (toHex(bytes.subarray(4, 8)) !== decoded.hash.slice(0, 8))
|
|
58
|
-
reject("the Automerge change checksum does not match its hash (§11)");
|
|
59
|
-
const checked = Object.freeze({
|
|
60
|
-
bytes: Uint8Array.from(bytes),
|
|
61
|
-
hash: decoded.hash,
|
|
62
|
-
actor: decoded.actor,
|
|
63
|
-
seq: decoded.seq,
|
|
64
|
-
deps: Object.freeze([...decoded.deps]),
|
|
65
|
-
otherActors: expansion.otherActors,
|
|
66
|
-
});
|
|
67
|
-
PARSED.set(checked, parsed);
|
|
68
|
-
return checked;
|
|
69
|
-
}
|
|
70
|
-
/** The operations checkChange read from the bytes (§11.3), for the references of §11.4. */
|
|
71
|
-
const PARSED = new WeakMap();
|
|
72
|
-
/** The change as its canonical bytes give it (§11.3), reusing the walk of checkChange. */
|
|
73
|
-
export function parsedOf(change) {
|
|
74
|
-
let p = PARSED.get(change);
|
|
75
|
-
if (p === undefined) {
|
|
76
|
-
p = checkCanonicalChange(change.bytes);
|
|
77
|
-
PARSED.set(change, p);
|
|
78
|
-
}
|
|
79
|
-
return p;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Checks that `bytes` starts as an Automerge full save (a document chunk,
|
|
83
|
-
* §13). Whether the whole image loads, checksums included, is decided by
|
|
84
|
-
* Automerge's load.
|
|
85
|
-
*/
|
|
86
|
-
export function checkSaveHeader(bytes) {
|
|
87
|
-
const type = chunkType(bytes, "the Snapshot image");
|
|
88
|
-
if (type !== CHUNK_DOCUMENT)
|
|
89
|
-
reject(`chunk type ${type} is not an Automerge document (full save, §13)`);
|
|
90
|
-
}
|
|
91
|
-
/** §11: the Data Unit plaintext [1, change] of one checked Automerge change. */
|
|
92
|
-
export function frameChange(change) {
|
|
93
|
-
checkChange(change);
|
|
94
|
-
return frameProfilePayload(change);
|
|
95
|
-
}
|
|
96
|
-
/** §11: the one Automerge change a Data Unit plaintext carries, checked. Throws PROFILE_INVALID / INVALID_AUTOMERGE_BYTES. */
|
|
97
|
-
export function unframeChange(plaintext) {
|
|
98
|
-
return checkChange(unframeProfilePayload(plaintext));
|
|
99
|
-
}
|
|
100
|
-
/** §13: the Snapshot plaintext [1, save] of an Automerge full save. */
|
|
101
|
-
export function frameSnapshot(save) {
|
|
102
|
-
checkSaveHeader(save);
|
|
103
|
-
return frameProfilePayload(save);
|
|
104
|
-
}
|
|
105
|
-
/** §13: the Automerge full save a Snapshot plaintext carries (header checked). Throws PROFILE_INVALID / INVALID_AUTOMERGE_BYTES. */
|
|
106
|
-
export function unframeSnapshot(plaintext) {
|
|
107
|
-
const save = unframeProfilePayload(plaintext);
|
|
108
|
-
checkSaveHeader(save);
|
|
109
|
-
return save;
|
|
110
|
-
}
|
|
111
|
-
//# sourceMappingURL=automerge-bytes.js.map
|