@openlfcp/shared-objects 0.1.5 → 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} +9 -3
- 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 +2 -2
- package/dist/index.js +2 -2
- package/dist/replica.d.ts +32 -2
- package/dist/replica.js +154 -195
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { LfcpError } from "@openlfcp/core";
|
|
2
|
+
import { ProfileInvalidError } from "../profile-invalid.js";
|
|
3
|
+
import { type CheckedChange } from "./framing.js";
|
|
4
|
+
import type { ReferenceHistory } from "./references.js";
|
|
5
|
+
/**
|
|
6
|
+
* SHARED-OBJECTS-PROFILE-01 §14.1, the sequence admission, for any profile
|
|
7
|
+
* that inherits it (SHARED-SECTIONS-PROFILE-01 §2): which received changes
|
|
8
|
+
* the engine may apply, in which order, and why the others wait or are
|
|
9
|
+
* refused. It reads the document through `DocumentSequences` and knows no
|
|
10
|
+
* profile semantics; a profile adds its own checks through `accept`.
|
|
11
|
+
*/
|
|
12
|
+
/** What admission needs to know of the document. */
|
|
13
|
+
export interface DocumentSequences {
|
|
14
|
+
/** Whether the document holds the change with this hex hash. */
|
|
15
|
+
hasChange(hash: string): boolean;
|
|
16
|
+
/** The actor's latest sequence number in the document; 0 when it has none. */
|
|
17
|
+
latestSeq(actor: string): number;
|
|
18
|
+
/**
|
|
19
|
+
* The document's changes as §11.4 reads them. When given, a change whose
|
|
20
|
+
* operations refer outside its causal history is refused; admitBatch adds
|
|
21
|
+
* the changes it admits (the caller rebuilds it if the engine then fails).
|
|
22
|
+
*/
|
|
23
|
+
readonly references?: ReferenceHistory;
|
|
24
|
+
}
|
|
25
|
+
/** A change admission refused: held (§14.1, POST-001) or invalid. */
|
|
26
|
+
export interface RefusedChange {
|
|
27
|
+
readonly change: CheckedChange;
|
|
28
|
+
readonly error: LfcpError;
|
|
29
|
+
/**
|
|
30
|
+
* The actor and sequence number belong to a different change of the
|
|
31
|
+
* document (ACTOR_EQUIVOCATION): a profile holds it and retries it after a
|
|
32
|
+
* rebuild that removes changes; it is not profile-invalid.
|
|
33
|
+
*/
|
|
34
|
+
readonly held: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface BatchAdmission {
|
|
37
|
+
/** Changes to apply, in an order where each comes after its dependencies. */
|
|
38
|
+
readonly admitted: readonly CheckedChange[];
|
|
39
|
+
/** Changes the document holds already. */
|
|
40
|
+
readonly duplicates: readonly CheckedChange[];
|
|
41
|
+
/** Changes whose dependencies are neither in the document nor admitted. */
|
|
42
|
+
readonly waiting: readonly CheckedChange[];
|
|
43
|
+
/** Held and invalid changes, in the order they were decided. */
|
|
44
|
+
readonly refused: readonly RefusedChange[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Admits many changes at once: each once its dependencies inside the batch
|
|
48
|
+
* are admitted (Kahn's order), against the document and the batch so far.
|
|
49
|
+
* A taken sequence is held, a change naming an actor the document does not
|
|
50
|
+
* know or skipping a sequence is INVALID_AUTOMERGE_BYTES (§11.1, §14.1),
|
|
51
|
+
* and `accept` (the profile's own checks, e.g. §11.2 depth) may refuse by
|
|
52
|
+
* throwing; a refused change does not stop the others, and the changes
|
|
53
|
+
* that depend on it wait. `changes` must hold each hash once.
|
|
54
|
+
*/
|
|
55
|
+
export declare function admitBatch(changes: readonly CheckedChange[], doc: DocumentSequences, accept?: (change: CheckedChange) => void): BatchAdmission;
|
|
56
|
+
/** One change against the document (receiveChange): what §14.1 says of it. */
|
|
57
|
+
export type ChangeAdmission = {
|
|
58
|
+
readonly kind: "duplicate";
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: "missing";
|
|
61
|
+
readonly missing: readonly string[];
|
|
62
|
+
}
|
|
63
|
+
/** Its actor and sequence belong to another change: held (§14.1, POST-001). */
|
|
64
|
+
| {
|
|
65
|
+
readonly kind: "held";
|
|
66
|
+
readonly error: LfcpError;
|
|
67
|
+
} | {
|
|
68
|
+
readonly kind: "invalid";
|
|
69
|
+
readonly error: ProfileInvalidError;
|
|
70
|
+
}
|
|
71
|
+
/** The actor's next change, every dependency present: the engine may apply it. */
|
|
72
|
+
| {
|
|
73
|
+
readonly kind: "next";
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* One change: a duplicate, missing dependencies, a held sequence, an actor
|
|
77
|
+
* the document does not know (§11.1) or a skipped sequence (§14.1), checked
|
|
78
|
+
* in that order before the engine sees it; or the actor's next change.
|
|
79
|
+
*/
|
|
80
|
+
export declare function admitChange(change: CheckedChange, doc: DocumentSequences): ChangeAdmission;
|
|
81
|
+
//# sourceMappingURL=sequence.d.ts.map
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { LfcpError } from "@openlfcp/core";
|
|
2
|
+
import { ProfileInvalidError } from "../profile-invalid.js";
|
|
3
|
+
import { parsedOf } from "./framing.js";
|
|
4
|
+
/** §11.4: a refusal for a change whose operations refer outside its history, or null. */
|
|
5
|
+
function referenceRefusal(c, doc) {
|
|
6
|
+
const rule = doc.references?.check(parsedOf(c)) ?? null;
|
|
7
|
+
return rule === null
|
|
8
|
+
? null
|
|
9
|
+
: new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", `the change's operations refer outside its causal history (§11.4 ${rule})`);
|
|
10
|
+
}
|
|
11
|
+
const held = (c) => new LfcpError("ACTOR_EQUIVOCATION", `actor ${c.actor} sequence ${c.seq} already has a different change (§26.2)`);
|
|
12
|
+
/**
|
|
13
|
+
* Admits many changes at once: each once its dependencies inside the batch
|
|
14
|
+
* are admitted (Kahn's order), against the document and the batch so far.
|
|
15
|
+
* A taken sequence is held, a change naming an actor the document does not
|
|
16
|
+
* know or skipping a sequence is INVALID_AUTOMERGE_BYTES (§11.1, §14.1),
|
|
17
|
+
* and `accept` (the profile's own checks, e.g. §11.2 depth) may refuse by
|
|
18
|
+
* throwing; a refused change does not stop the others, and the changes
|
|
19
|
+
* that depend on it wait. `changes` must hold each hash once.
|
|
20
|
+
*/
|
|
21
|
+
export function admitBatch(changes, doc, accept = () => undefined) {
|
|
22
|
+
const all = [...changes];
|
|
23
|
+
const index = new Map(all.map((c, i) => [c.hash, i]));
|
|
24
|
+
const blocking = all.map(() => 0);
|
|
25
|
+
const unreachable = all.map(() => false);
|
|
26
|
+
const children = new Map();
|
|
27
|
+
all.forEach((c, i) => {
|
|
28
|
+
for (const d of c.deps) {
|
|
29
|
+
if (doc.hasChange(d))
|
|
30
|
+
continue;
|
|
31
|
+
if (index.has(d)) {
|
|
32
|
+
blocking[i] = blocking[i] + 1;
|
|
33
|
+
children.set(d, [...(children.get(d) ?? []), i]);
|
|
34
|
+
}
|
|
35
|
+
else
|
|
36
|
+
unreachable[i] = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const seqs = new Map();
|
|
40
|
+
const latest = (actor) => seqs.get(actor) ?? doc.latestSeq(actor);
|
|
41
|
+
const admitted = [];
|
|
42
|
+
const duplicates = [];
|
|
43
|
+
const refused = [];
|
|
44
|
+
const done = all.map(() => false);
|
|
45
|
+
const ready = all.flatMap((_, i) => (blocking[i] === 0 && !unreachable[i] ? [i] : []));
|
|
46
|
+
for (let k = 0; k < ready.length; k++) {
|
|
47
|
+
const i = ready[k];
|
|
48
|
+
const c = all[i];
|
|
49
|
+
done[i] = true;
|
|
50
|
+
if (doc.hasChange(c.hash))
|
|
51
|
+
duplicates.push(c);
|
|
52
|
+
else if (c.seq <= latest(c.actor)) {
|
|
53
|
+
refused.push({ change: c, error: held(c), held: true });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
else if (c.otherActors.some((a) => latest(a) === 0)) {
|
|
57
|
+
refused.push({
|
|
58
|
+
change: c,
|
|
59
|
+
error: new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", `the change names an actor unknown to this document (§11.1)`),
|
|
60
|
+
held: false,
|
|
61
|
+
});
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
else if (c.seq !== latest(c.actor) + 1) {
|
|
65
|
+
refused.push({
|
|
66
|
+
change: c,
|
|
67
|
+
error: new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", `actor ${c.actor} sequence ${c.seq} skips sequence ${latest(c.actor) + 1} (§14.1)`),
|
|
68
|
+
held: false,
|
|
69
|
+
});
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const references = referenceRefusal(c, doc);
|
|
74
|
+
if (references !== null) {
|
|
75
|
+
refused.push({ change: c, error: references, held: false });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
accept(c);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
refused.push({ change: c, error: e, held: false });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
seqs.set(c.actor, c.seq);
|
|
86
|
+
doc.references?.add(c.hash, parsedOf(c));
|
|
87
|
+
admitted.push(c);
|
|
88
|
+
}
|
|
89
|
+
for (const child of children.get(c.hash) ?? []) {
|
|
90
|
+
blocking[child] = blocking[child] - 1;
|
|
91
|
+
if (blocking[child] === 0 && !unreachable[child])
|
|
92
|
+
ready.push(child);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return Object.freeze({
|
|
96
|
+
admitted: Object.freeze(admitted),
|
|
97
|
+
duplicates: Object.freeze(duplicates),
|
|
98
|
+
waiting: Object.freeze(all.filter((_, i) => !done[i])),
|
|
99
|
+
refused: Object.freeze(refused),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* One change: a duplicate, missing dependencies, a held sequence, an actor
|
|
104
|
+
* the document does not know (§11.1) or a skipped sequence (§14.1), checked
|
|
105
|
+
* in that order before the engine sees it; or the actor's next change.
|
|
106
|
+
*/
|
|
107
|
+
export function admitChange(change, doc) {
|
|
108
|
+
if (doc.hasChange(change.hash))
|
|
109
|
+
return { kind: "duplicate" };
|
|
110
|
+
const missing = change.deps.filter((d) => !doc.hasChange(d));
|
|
111
|
+
if (missing.length > 0)
|
|
112
|
+
return { kind: "missing", missing: Object.freeze(missing) };
|
|
113
|
+
const latest = doc.latestSeq(change.actor);
|
|
114
|
+
if (change.seq <= latest)
|
|
115
|
+
return { kind: "held", error: held(change) };
|
|
116
|
+
const unknown = change.otherActors.find((a) => doc.latestSeq(a) === 0);
|
|
117
|
+
if (unknown !== undefined)
|
|
118
|
+
return {
|
|
119
|
+
kind: "invalid",
|
|
120
|
+
error: new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", `the change names actor ${unknown}, unknown to this document (§11.1)`),
|
|
121
|
+
};
|
|
122
|
+
if (change.seq !== latest + 1)
|
|
123
|
+
return {
|
|
124
|
+
kind: "invalid",
|
|
125
|
+
error: new ProfileInvalidError("INVALID_AUTOMERGE_BYTES", `actor ${change.actor} sequence ${change.seq} skips sequence ${latest + 1} (§14.1)`),
|
|
126
|
+
};
|
|
127
|
+
// §11.4: checked only; the caller adds the change once the engine applied it.
|
|
128
|
+
const references = referenceRefusal(change, doc);
|
|
129
|
+
if (references !== null)
|
|
130
|
+
return { kind: "invalid", error: references };
|
|
131
|
+
return { kind: "next" };
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=sequence.js.map
|
package/dist/data-profile.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DataUnitId, type PrincipalId, type ResourceId } from "@openlfcp/core";
|
|
2
|
-
import { type CheckedChange } from "./
|
|
2
|
+
import { type CheckedChange } from "./admission/framing.js";
|
|
3
3
|
import { type ObjectChange, type ReplicaOptions, SharedObjectsReplica } from "./replica.js";
|
|
4
4
|
/**
|
|
5
5
|
* The Shared Objects Data Profile handler (LFCP-033): what a profile-
|
package/dist/data-profile.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LfcpError, toHex, } from "@openlfcp/core";
|
|
2
|
-
import {
|
|
2
|
+
import { checkChangeActor } from "./admission/actor.js";
|
|
3
|
+
import { frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./admission/framing.js";
|
|
3
4
|
import { SharedObjectsReplica } from "./replica.js";
|
|
4
|
-
import { ProfileInvalidError } from "./validate.js";
|
|
5
5
|
import { deriveActorId, PROFILE_ID } from "./values.js";
|
|
6
6
|
export class SharedObjectsDataProfile {
|
|
7
7
|
dataProfile = PROFILE_ID;
|
|
@@ -139,11 +139,7 @@ export class SharedObjectsDataProfile {
|
|
|
139
139
|
// §8, §11 (SO-SEC1): a unit carries only changes of its signer's §8
|
|
140
140
|
// actor, so no Principal can write into another Principal's Automerge
|
|
141
141
|
// history. Anything else is PROFILE_INVALID / CHANGE_ACTOR_MISMATCH.
|
|
142
|
-
const bound = (change) =>
|
|
143
|
-
if (change.actor !== actor)
|
|
144
|
-
throw new ProfileInvalidError("CHANGE_ACTOR_MISMATCH", `the change's Automerge actor ${change.actor} is not the §8 actor ${actor} of the unit's signer (§11, SO-SEC1)`);
|
|
145
|
-
return change;
|
|
146
|
-
};
|
|
142
|
+
const bound = (change) => checkChangeActor(change, actor);
|
|
147
143
|
return {
|
|
148
144
|
dataProfile: PROFILE_ID,
|
|
149
145
|
encode: (change) => frameChange(bound(change).bytes),
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Automerge binding (LFCP-031).
|
|
5
5
|
*/
|
|
6
6
|
export declare const PACKAGE = "@openlfcp/shared-objects";
|
|
7
|
-
export { type CheckedChange, checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./
|
|
8
|
-
export { CHANGE_LIMITS, type ChunkExpansion, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, type SnapshotLimits, } from "./
|
|
7
|
+
export { type CheckedChange, checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./admission/framing.js";
|
|
8
|
+
export { CHANGE_LIMITS, type ChunkExpansion, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, type SnapshotLimits, } from "./admission/limits.js";
|
|
9
9
|
export { type SharedObjectsApplyResult, type SharedObjectsBatchResult, type SharedObjectsCheckpoint, type SharedObjectsCodec, SharedObjectsDataProfile, type SharedObjectsDiagnostic, type SharedObjectsExcludeResult, type SharedObjectsSnapshotCodec, type SharedObjectsUnit, } from "./data-profile.js";
|
|
10
10
|
export { applyBatchChecked, applyChecked, type BatchReceiveResult, type BuiltReplica, isWasmTrap, type LocalChange, type ObjectChange, ObjectIdCollisionError, type ObjectStatus, type ReceiveResult, type ReplicaIntent, type ReplicaOptions, type ReplicaValidation, type ResolveFieldConflict, resolveFieldConflict, SCALAR_FIELDS, type ScalarField, type ScalarView, SharedObjectsReplica, type TaskView, } from "./replica.js";
|
|
11
11
|
export { addTag, assign, cancel, clearDue, clearScheduled, complete, createTask, deleteTask, type NewTask, type ParsedTask, ProfileError, parseTask, removeTag, reopen, restoreTask, setDue, setPriority, setScheduled, setStatus, setTitle, type Task, type TaskChange, type TaskIntent, type TaskPriority, type TaskStatus, taskToJson, unassign, } from "./task.js";
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Automerge binding (LFCP-031).
|
|
5
5
|
*/
|
|
6
6
|
export const PACKAGE = "@openlfcp/shared-objects";
|
|
7
|
-
export { checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./
|
|
8
|
-
export { CHANGE_LIMITS, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, } from "./
|
|
7
|
+
export { checkChange, checkSaveHeader, frameChange, frameSnapshot, unframeChange, unframeSnapshot, } from "./admission/framing.js";
|
|
8
|
+
export { CHANGE_LIMITS, checkChangeExpansion, checkSnapshotExpansion, MAX_DOCUMENT_DEPTH, SNAPSHOT_LIMITS_FLOOR, } from "./admission/limits.js";
|
|
9
9
|
export { SharedObjectsDataProfile, } from "./data-profile.js";
|
|
10
10
|
export { applyBatchChecked, applyChecked, isWasmTrap, ObjectIdCollisionError, resolveFieldConflict, SCALAR_FIELDS, SharedObjectsReplica, } from "./replica.js";
|
|
11
11
|
export { addTag, assign, cancel, clearDue, clearScheduled, complete, createTask, deleteTask, ProfileError, parseTask, removeTag, reopen, restoreTask, setDue, setPriority, setScheduled, setStatus, setTitle, taskToJson, unassign, } from "./task.js";
|
package/dist/replica.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as A from "@automerge/automerge";
|
|
2
2
|
import { LfcpError, type ObjectId, type PrincipalId, type ResourceId } from "@openlfcp/core";
|
|
3
|
-
import { type CheckedChange } from "./
|
|
4
|
-
import { type SnapshotLimits } from "./
|
|
3
|
+
import { type CheckedChange } from "./admission/framing.js";
|
|
4
|
+
import { type SnapshotLimits } from "./admission/limits.js";
|
|
5
5
|
import { type Task, type TaskIntent } from "./task.js";
|
|
6
6
|
import { type Json, type ProfileProblem, type RootValidation } from "./validate.js";
|
|
7
7
|
/**
|
|
@@ -141,13 +141,43 @@ export interface BuiltReplica {
|
|
|
141
141
|
readonly unapplied: readonly CheckedChange[];
|
|
142
142
|
}
|
|
143
143
|
type Doc = A.Doc<Record<string, unknown>>;
|
|
144
|
+
type AMap = Record<string, unknown>;
|
|
144
145
|
/** §30: an object's maps and lists nest at most this many levels (the field's own map is 1). */
|
|
145
146
|
export declare const MAX_VALUE_DEPTH = 64;
|
|
147
|
+
/**
|
|
148
|
+
* §99: the Task under `id` of `objects` (the document's `objects` map) with
|
|
149
|
+
* conflict metadata, or undefined if there is no object or it is not a Task.
|
|
150
|
+
* Shared by the Shared Objects and the Shared Sections replicas.
|
|
151
|
+
*/
|
|
152
|
+
export declare function taskView(doc: A.Doc<unknown>, objects: AMap | undefined, id: string): TaskView | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* §74.1 problems of one object as stored at `/objects/<id>` of `doc`: its
|
|
155
|
+
* logical values, every collaborative Text in it (§30) and every concurrent
|
|
156
|
+
* value of its scalar registers (§45), one diagnostic per field. Shared by
|
|
157
|
+
* every profile whose Tasks are SOP Tasks (SHARED-SECTIONS-PROFILE-01 §2).
|
|
158
|
+
*/
|
|
159
|
+
export declare function storedObjectProblems(doc: A.Doc<unknown>, stored: AMap, id: string): ProfileProblem[];
|
|
160
|
+
/** A Task intent checked against the stored objects, ready to write inside a change. */
|
|
161
|
+
export interface PreparedTaskIntent {
|
|
162
|
+
/** The Task it writes. */
|
|
163
|
+
readonly id: string;
|
|
164
|
+
/** Writes the intent into the `objects` map of a change's document. */
|
|
165
|
+
readonly perform: (objects: Record<string, unknown>) => void;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Checks one Task intent against `objects`, the stored objects map of
|
|
169
|
+
* `doc`, before anything is written: §21 no reuse of an Object ID on
|
|
170
|
+
* create, §74 the Task after the intent is valid, and no Text left in a
|
|
171
|
+
* field it writes. Throws ProfileError or ObjectIdCollisionError. Shared by
|
|
172
|
+
* every profile whose Tasks are SOP Tasks (SHARED-SECTIONS-PROFILE-01 §2).
|
|
173
|
+
*/
|
|
174
|
+
export declare function prepareTaskIntent(doc: A.Doc<unknown>, objects: Record<string, unknown>, intent: ReplicaIntent): PreparedTaskIntent;
|
|
146
175
|
/**
|
|
147
176
|
* Whether a thrown value is a wasm trap (the engine's module is dead, not
|
|
148
177
|
* the change refused): it is rethrown as it is, never turned into
|
|
149
178
|
* INVALID_AUTOMERGE_BYTES, so a crash-loop breaker sees it.
|
|
150
179
|
*/
|
|
180
|
+
/** A wasm trap (RuntimeError, or a terminated module): fatal, not a refusable change. */
|
|
151
181
|
export declare function isWasmTrap(e: unknown): boolean;
|
|
152
182
|
/**
|
|
153
183
|
* Applies one change that passed the receive checks. Automerge can throw
|