@openlfcp/shared-objects 0.1.1 → 0.1.2
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 +2 -2
- package/package.json +3 -3
- package/dist/automerge-bytes.d.ts +0 -37
- package/dist/automerge-bytes.js +0 -95
- package/dist/chunk-limits.d.ts +0 -58
- package/dist/chunk-limits.js +0 -457
- package/dist/data-profile.d.ts +0 -159
- package/dist/data-profile.js +0 -311
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -15
- package/dist/profile-invalid.d.ts +0 -12
- package/dist/profile-invalid.js +0 -15
- package/dist/replica.d.ts +0 -277
- package/dist/replica.js +0 -1039
- package/dist/task.d.ts +0 -159
- package/dist/task.js +0 -192
- package/dist/validate.d.ts +0 -70
- package/dist/validate.js +0 -196
- package/dist/values.d.ts +0 -52
- package/dist/values.js +0 -163
- package/dist/wasm.d.ts +0 -33
- package/dist/wasm.js +0 -58
package/dist/replica.d.ts
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
2
|
-
import { LfcpError, type ObjectId, type PrincipalId, type ResourceId } from "@openlfcp/core";
|
|
3
|
-
import { type CheckedChange } from "./automerge-bytes.js";
|
|
4
|
-
import { type SnapshotLimits } from "./chunk-limits.js";
|
|
5
|
-
import { type Task, type TaskIntent } from "./task.js";
|
|
6
|
-
import { type Json, type ProfileProblem, type RootValidation } from "./validate.js";
|
|
7
|
-
/**
|
|
8
|
-
* The Automerge binding of SHARED-OBJECTS-PROFILE-01 (LFCP-031): one
|
|
9
|
-
* Resource's replica of the org.openlfcp.shared-objects.v1 document.
|
|
10
|
-
*
|
|
11
|
-
* - The actor is always the §8 actor of (Resource, Principal), set
|
|
12
|
-
* explicitly; §9 actor state safety is enforced with `minSeq`.
|
|
13
|
-
* - One semantic intent is exactly one Automerge change (§10, §12), with
|
|
14
|
-
* time 0 (informational, and a wall clock would leak edit times) and the
|
|
15
|
-
* intent name as message. An intent that changes nothing makes no change.
|
|
16
|
-
* - Writes touch single properties only, so unknown fields, extension
|
|
17
|
-
* namespaces and object types survive (§70-§72). Objects are never
|
|
18
|
-
* removed: deletion is the lifecycle tombstone (§54-§56).
|
|
19
|
-
* - Scalar conflicts stay visible (§44-§47) and are resolved by a new
|
|
20
|
-
* causal write (§69); tags and assignees are add-wins maps (§39-§43).
|
|
21
|
-
*
|
|
22
|
-
* Receiving is pure profile work: LFCP verification, decryption and
|
|
23
|
-
* authorization come first (§95, LFCP-033).
|
|
24
|
-
*/
|
|
25
|
-
/** The conflict-preserving scalar registers of a Task (§44). */
|
|
26
|
-
export declare const SCALAR_FIELDS: readonly ["lifecycle", "title", "status", "due", "scheduled", "completion_date", "priority"];
|
|
27
|
-
export type ScalarField = (typeof SCALAR_FIELDS)[number];
|
|
28
|
-
/** §69 task.resolve_field_conflict: write `value` (null clears a date) after the merged conflicts. */
|
|
29
|
-
export interface ResolveFieldConflict {
|
|
30
|
-
readonly intent: "task.resolve_field_conflict";
|
|
31
|
-
readonly id: ObjectId;
|
|
32
|
-
readonly field: ScalarField;
|
|
33
|
-
readonly value: string | null;
|
|
34
|
-
}
|
|
35
|
-
export type ReplicaIntent = TaskIntent | ResolveFieldConflict;
|
|
36
|
-
/** task.resolve_field_conflict (§69). */
|
|
37
|
-
export declare function resolveFieldConflict(id: ObjectId, field: ScalarField, value: string | null): ResolveFieldConflict;
|
|
38
|
-
/** §21: two concurrent objects under one Object ID: OBJECT_ID_COLLISION, a profile error of its own, not PROFILE_INVALID. */
|
|
39
|
-
export declare class ObjectIdCollisionError extends LfcpError {
|
|
40
|
-
readonly objectId: string;
|
|
41
|
-
constructor(objectId: string);
|
|
42
|
-
}
|
|
43
|
-
/** §99: a scalar register's provisional value and every concurrent value. */
|
|
44
|
-
export interface ScalarView {
|
|
45
|
-
/** Automerge's deterministic visible value; provisional while conflicted. Undefined when absent. */
|
|
46
|
-
readonly value: Json | undefined;
|
|
47
|
-
/** Every concurrent value, sorted by JSON: none when absent, one when resolved. */
|
|
48
|
-
readonly values: readonly Json[];
|
|
49
|
-
readonly conflicted: boolean;
|
|
50
|
-
}
|
|
51
|
-
export type ObjectStatus = "ready" | "profile_invalid" | "object_id_collision";
|
|
52
|
-
/** §99: a Task with its conflict metadata. */
|
|
53
|
-
export interface TaskView {
|
|
54
|
-
readonly id: string;
|
|
55
|
-
readonly status: ObjectStatus;
|
|
56
|
-
readonly problems: readonly ProfileProblem[];
|
|
57
|
-
/** The provisional Task, when every visible value is valid. */
|
|
58
|
-
readonly task: Task | undefined;
|
|
59
|
-
readonly fields: {
|
|
60
|
-
readonly [F in ScalarField]: ScalarView;
|
|
61
|
-
};
|
|
62
|
-
readonly tags: readonly string[];
|
|
63
|
-
readonly assignees: readonly string[];
|
|
64
|
-
}
|
|
65
|
-
/** §100: what one change did to one object. */
|
|
66
|
-
export interface ObjectChange {
|
|
67
|
-
readonly resource: ResourceId;
|
|
68
|
-
readonly objectId: string;
|
|
69
|
-
readonly objectType: string | undefined;
|
|
70
|
-
/** Top-level fields written, sorted. */
|
|
71
|
-
readonly fields: readonly string[];
|
|
72
|
-
readonly conflictsAppeared: readonly string[];
|
|
73
|
-
readonly conflictsDisappeared: readonly string[];
|
|
74
|
-
/** "rebuild": the state was rebuilt without some changes (§14.1, G-EP7). */
|
|
75
|
-
readonly origin: "local" | "remote" | "rebuild";
|
|
76
|
-
}
|
|
77
|
-
/** A local intent's Automerge change, ready to become a Data Unit. */
|
|
78
|
-
export interface LocalChange {
|
|
79
|
-
readonly intent: string;
|
|
80
|
-
/** The exact Automerge change bytes. */
|
|
81
|
-
readonly change: Uint8Array;
|
|
82
|
-
/** §11: the Data Unit plaintext [1, change]. */
|
|
83
|
-
readonly plaintext: Uint8Array;
|
|
84
|
-
readonly hash: string;
|
|
85
|
-
readonly seq: number;
|
|
86
|
-
readonly objects: readonly ObjectChange[];
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* The outcome of receiving one change. A change whose dependencies are not
|
|
90
|
-
* all here is not applied and not invalid: the caller buffers it and offers
|
|
91
|
-
* it again later (LFCP-033).
|
|
92
|
-
*/
|
|
93
|
-
export type ReceiveResult = {
|
|
94
|
-
readonly status: "applied";
|
|
95
|
-
readonly change: CheckedChange;
|
|
96
|
-
readonly objects: readonly ObjectChange[];
|
|
97
|
-
} | {
|
|
98
|
-
readonly status: "duplicate";
|
|
99
|
-
readonly change: CheckedChange;
|
|
100
|
-
} | {
|
|
101
|
-
readonly status: "missing_dependencies";
|
|
102
|
-
readonly change: CheckedChange;
|
|
103
|
-
readonly missing: readonly string[];
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* The outcome of receiving many changes at once (receiveChanges): the
|
|
107
|
-
* changes merged, those already held, those still missing a dependency
|
|
108
|
-
* (not handed to Automerge, §14.1), and those refused with their error.
|
|
109
|
-
*/
|
|
110
|
-
export interface BatchReceiveResult {
|
|
111
|
-
readonly applied: readonly CheckedChange[];
|
|
112
|
-
readonly duplicates: readonly CheckedChange[];
|
|
113
|
-
readonly waiting: readonly CheckedChange[];
|
|
114
|
-
readonly refused: readonly {
|
|
115
|
-
readonly change: CheckedChange;
|
|
116
|
-
readonly error: LfcpError;
|
|
117
|
-
}[];
|
|
118
|
-
/** §100 notifications for everything the batch changed. */
|
|
119
|
-
readonly objects: readonly ObjectChange[];
|
|
120
|
-
}
|
|
121
|
-
/** Root validation plus §21 collisions and the G-SC3 scalar-string rule. */
|
|
122
|
-
export interface ReplicaValidation extends RootValidation {
|
|
123
|
-
/** Object IDs with concurrent objects (OBJECT_ID_COLLISION, §21). */
|
|
124
|
-
readonly collisions: readonly string[];
|
|
125
|
-
}
|
|
126
|
-
export interface ReplicaOptions {
|
|
127
|
-
readonly resource: ResourceId;
|
|
128
|
-
/** The writing Principal; with the Resource it fixes the §8 actor. */
|
|
129
|
-
readonly principal: PrincipalId;
|
|
130
|
-
/**
|
|
131
|
-
* §9: the highest change sequence this actor is known to have used
|
|
132
|
-
* (persisted by the caller, LFCP-035). If the loaded state is behind it,
|
|
133
|
-
* local writes are refused: they would start an unrelated history under
|
|
134
|
-
* sequences already used.
|
|
135
|
-
*/
|
|
136
|
-
readonly minSeq?: number;
|
|
137
|
-
}
|
|
138
|
-
/** A replica built from a change set; `unapplied` lacks dependencies in that set. */
|
|
139
|
-
export interface BuiltReplica {
|
|
140
|
-
readonly replica: SharedObjectsReplica;
|
|
141
|
-
readonly unapplied: readonly CheckedChange[];
|
|
142
|
-
}
|
|
143
|
-
type Doc = A.Doc<Record<string, unknown>>;
|
|
144
|
-
/** §30: an object's maps and lists nest at most this many levels (the field's own map is 1). */
|
|
145
|
-
export declare const MAX_VALUE_DEPTH = 64;
|
|
146
|
-
/**
|
|
147
|
-
* Applies one change that passed the receive checks. Automerge can throw
|
|
148
|
-
* after changing the document in place (a change that skips a sequence
|
|
149
|
-
* number stays in its graph without its operations), so on any engine error
|
|
150
|
-
* the handle is dropped: the document is rebuilt from the changes it held,
|
|
151
|
-
* which must give back the heads it had. A wasm trap is rethrown as it
|
|
152
|
-
* is: the module is dead, and only a restart recovers. Exported for tests.
|
|
153
|
-
*/
|
|
154
|
-
export declare function applyChecked(doc: Doc, bytes: Uint8Array): {
|
|
155
|
-
readonly next: Doc;
|
|
156
|
-
} | {
|
|
157
|
-
readonly restored: Doc;
|
|
158
|
-
readonly error: Error;
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* applyChecked for a batch of admitted changes, in one engine call. On any
|
|
162
|
-
* engine error the handle is dropped and the document as it was before is
|
|
163
|
-
* rebuilt from the changes it held minus the batch, checked against the
|
|
164
|
-
* heads it had. Exported for tests.
|
|
165
|
-
*/
|
|
166
|
-
export declare function applyBatchChecked(doc: Doc, batch: readonly CheckedChange[]): {
|
|
167
|
-
readonly next: Doc;
|
|
168
|
-
} | {
|
|
169
|
-
readonly restored: Doc;
|
|
170
|
-
readonly error: Error;
|
|
171
|
-
};
|
|
172
|
-
export declare class SharedObjectsReplica {
|
|
173
|
-
#private;
|
|
174
|
-
readonly resource: ResourceId;
|
|
175
|
-
/** The §8 Automerge actor ID. */
|
|
176
|
-
readonly actorId: Uint8Array;
|
|
177
|
-
private constructor();
|
|
178
|
-
/** §16: a new Resource document. The initial change is the Resource's first Data Unit. */
|
|
179
|
-
static create(opts: ReplicaOptions): {
|
|
180
|
-
replica: SharedObjectsReplica;
|
|
181
|
-
change: LocalChange;
|
|
182
|
-
};
|
|
183
|
-
/** A replica with no state yet, that receives the Resource's changes. */
|
|
184
|
-
static empty(opts: ReplicaOptions): SharedObjectsReplica;
|
|
185
|
-
/**
|
|
186
|
-
* Loads an Automerge full save: a received Snapshot image (§13), checked
|
|
187
|
-
* against `limits` (§13.1, at least the floor) before Automerge loads it,
|
|
188
|
-
* or this device's own persisted state ("local-state", not limited).
|
|
189
|
-
* Throws PROFILE_INVALID / INVALID_AUTOMERGE_BYTES.
|
|
190
|
-
*/
|
|
191
|
-
static fromSave(save: Uint8Array, opts: ReplicaOptions, limits?: SnapshotLimits | "local-state"): SharedObjectsReplica;
|
|
192
|
-
/** §13: loads a Snapshot plaintext [1, save]; later Data Units are received after it. */
|
|
193
|
-
static fromSnapshot(plaintext: Uint8Array, opts: ReplicaOptions): SharedObjectsReplica;
|
|
194
|
-
/**
|
|
195
|
-
* The replica of exactly an accepted change set: its state depends only
|
|
196
|
-
* on the set, not on the order. Changes whose dependencies are not in the
|
|
197
|
-
* set are returned as unapplied.
|
|
198
|
-
*/
|
|
199
|
-
static fromChanges(changes: Iterable<Uint8Array>, opts: ReplicaOptions): BuiltReplica;
|
|
200
|
-
/**
|
|
201
|
-
* §14.1 (G-EP7): this replica rebuilt from its own changes minus
|
|
202
|
-
* `exclude` (change hashes). Changes that depend on an excluded change are
|
|
203
|
-
* unapplied too. An excluded change of this actor is not lost state (§9):
|
|
204
|
-
* the rebuilt replica writes on from its own sequence, reusing the
|
|
205
|
-
* sequence numbers of the removed changes. A replica that was already
|
|
206
|
-
* behind its persisted sequence stays refused.
|
|
207
|
-
*/
|
|
208
|
-
rebuildWithout(exclude: Iterable<string>): BuiltReplica;
|
|
209
|
-
/**
|
|
210
|
-
* This replica merged with an Automerge full save (a loaded Snapshot,
|
|
211
|
-
* §13): the save's document plus every change of this replica, so local
|
|
212
|
-
* work the Snapshot does not hold is kept. The §9 sequence carries over.
|
|
213
|
-
* Throws PROFILE_INVALID / INVALID_AUTOMERGE_BYTES when the save does not load.
|
|
214
|
-
*/
|
|
215
|
-
mergeSave(save: Uint8Array): BuiltReplica;
|
|
216
|
-
/** An empty replica of the same Resource and actor that keeps the §9 sequence (nothing reused). */
|
|
217
|
-
emptied(): SharedObjectsReplica;
|
|
218
|
-
/** The highest change sequence of this replica's own actor in its state. */
|
|
219
|
-
get actorSeq(): number;
|
|
220
|
-
/** §9: false when the state is behind the persisted sequence, so local writes are refused. */
|
|
221
|
-
get writable(): boolean;
|
|
222
|
-
/** Hex hashes of the current heads, sorted. */
|
|
223
|
-
heads(): string[];
|
|
224
|
-
hasChange(hash: string): boolean;
|
|
225
|
-
/** Every change of the state, dependencies first. */
|
|
226
|
-
changes(): Uint8Array[];
|
|
227
|
-
/** The Automerge full save of the state. */
|
|
228
|
-
save(): Uint8Array;
|
|
229
|
-
/** §13: the Snapshot plaintext [1, save]. */
|
|
230
|
-
snapshot(): Uint8Array;
|
|
231
|
-
/**
|
|
232
|
-
* The logical root: scalar strings (and Text) read as strings, object keys
|
|
233
|
-
* in canonical order, so JSON.stringify(root()) is comparable across
|
|
234
|
-
* replicas holding the same state.
|
|
235
|
-
*/
|
|
236
|
-
root(): Json;
|
|
237
|
-
/** The logical object stored under `id` (its visible value), if any. */
|
|
238
|
-
getObject(id: string): Json | undefined;
|
|
239
|
-
objectIds(): string[];
|
|
240
|
-
/** §45: every conflicted top-level field of every object, with its concurrent values sorted. */
|
|
241
|
-
conflicts(): Record<string, Record<string, Json[]>>;
|
|
242
|
-
/** §21: Object IDs under which concurrent objects were created. */
|
|
243
|
-
collisions(): string[];
|
|
244
|
-
/** §73-§77 validation of the visible state, every concurrent scalar value and G-SC3, plus §21 collisions. */
|
|
245
|
-
validate(): ReplicaValidation;
|
|
246
|
-
/** §99: the Task under `id` with conflict metadata, or undefined if there is no object or it is not a Task. */
|
|
247
|
-
task(id: string): TaskView | undefined;
|
|
248
|
-
/**
|
|
249
|
-
* Applies one intent as exactly one Automerge change (§10) and returns it,
|
|
250
|
-
* or null when the intent changes nothing (removing an absent tag,
|
|
251
|
-
* clearing an absent date). The resulting object must be profile-valid;
|
|
252
|
-
* an object already invalid or collided is not written (§76, §21) unless
|
|
253
|
-
* the write repairs it.
|
|
254
|
-
*/
|
|
255
|
-
apply(intent: ReplicaIntent): LocalChange | null;
|
|
256
|
-
/** §11: receives a Data Unit plaintext [1, change]. Throws PROFILE_INVALID / INVALID_AUTOMERGE_BYTES for invalid bytes. */
|
|
257
|
-
receive(plaintext: Uint8Array): ReceiveResult;
|
|
258
|
-
/** Receives one bare Automerge change (persisted or reference bytes). */
|
|
259
|
-
receiveChange(bytes: Uint8Array): ReceiveResult;
|
|
260
|
-
/**
|
|
261
|
-
* Receives many changes at once: store replay, catch-up, a Snapshot's
|
|
262
|
-
* remainder. Same rules as receiveChange (§14.1: no change with a
|
|
263
|
-
* missing dependency reaches Automerge; a taken sequence is
|
|
264
|
-
* ACTOR_EQUIVOCATION; a skipped one INVALID_AUTOMERGE_BYTES), but the
|
|
265
|
-
* admitted changes go to Automerge in ONE call: one change per call is
|
|
266
|
-
* quadratic (10 000 changes: ~12 s against ~70 ms as one batch).
|
|
267
|
-
*
|
|
268
|
-
* The changes may come in any order, duplicated: each is admitted once
|
|
269
|
-
* its dependencies inside the batch are (Kahn's order). A refused change
|
|
270
|
-
* does not stop the others; changes that depend on it wait. If Automerge
|
|
271
|
-
* fails anyway, the document is restored and the admitted changes are
|
|
272
|
-
* received one at a time, which isolates the failing one.
|
|
273
|
-
*/
|
|
274
|
-
receiveChanges(changes: Iterable<Uint8Array | CheckedChange>): BatchReceiveResult;
|
|
275
|
-
}
|
|
276
|
-
export {};
|
|
277
|
-
//# sourceMappingURL=replica.d.ts.map
|