cojson 0.8.5 → 0.8.12
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/CHANGELOG.md +12 -0
- package/dist/native/PeerKnownStates.js +63 -0
- package/dist/native/PeerKnownStates.js.map +1 -0
- package/dist/native/PeerState.js +5 -1
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/coValueState.js +74 -0
- package/dist/native/coValueState.js.map +1 -0
- package/dist/native/exports.js +39 -0
- package/dist/native/exports.js.map +1 -0
- package/dist/native/index.native.js +2 -39
- package/dist/native/index.native.js.map +1 -1
- package/dist/native/localNode.js +29 -51
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/storage/index.js +2 -2
- package/dist/native/storage/index.js.map +1 -1
- package/dist/native/sync.js +89 -109
- package/dist/native/sync.js.map +1 -1
- package/dist/web/PeerKnownStates.js +63 -0
- package/dist/web/PeerKnownStates.js.map +1 -0
- package/dist/web/PeerState.js +5 -1
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/coValueState.js +74 -0
- package/dist/web/coValueState.js.map +1 -0
- package/dist/web/exports.js +39 -0
- package/dist/web/exports.js.map +1 -0
- package/dist/web/index.web.js +2 -39
- package/dist/web/index.web.js.map +1 -1
- package/dist/web/localNode.js +29 -51
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/storage/index.js +2 -2
- package/dist/web/storage/index.js.map +1 -1
- package/dist/web/sync.js +89 -109
- package/dist/web/sync.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerKnownStates.ts +108 -0
- package/src/PeerState.ts +8 -2
- package/src/coValueState.ts +107 -0
- package/src/exports.ts +149 -0
- package/src/index.native.ts +2 -152
- package/src/index.web.ts +2 -152
- package/src/localNode.ts +43 -90
- package/src/storage/index.ts +2 -2
- package/src/sync.ts +95 -148
- package/src/tests/PeerKnownStates.test.ts +100 -0
- package/src/tests/PeerState.test.ts +0 -11
- package/src/tests/sync.test.ts +2 -2
- package/.turbo/turbo-build.log +0 -16
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-test.log +0 -1001
package/src/localNode.ts
CHANGED
|
@@ -28,10 +28,11 @@ import {
|
|
|
28
28
|
import { RawCoValue } from "./coValue.js";
|
|
29
29
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
30
30
|
import { err, ok, okAsync, Result, ResultAsync } from "neverthrow";
|
|
31
|
+
import { CoValueState } from "./coValueState.js";
|
|
31
32
|
|
|
32
33
|
/** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
|
|
33
34
|
|
|
34
|
-
A `LocalNode` can have peers that it syncs to, for example some form of local persistence, or a sync server, such as `
|
|
35
|
+
A `LocalNode` can have peers that it syncs to, for example some form of local persistence, or a sync server, such as `cloud.jazz.tools` (Jazz Cloud).
|
|
35
36
|
|
|
36
37
|
@example
|
|
37
38
|
You typically get hold of a `LocalNode` using `jazz-react`'s `useJazz()`:
|
|
@@ -130,10 +131,9 @@ export class LocalNode {
|
|
|
130
131
|
);
|
|
131
132
|
|
|
132
133
|
nodeWithAccount.account = controlledAccount;
|
|
133
|
-
nodeWithAccount.coValues[controlledAccount.id] =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
};
|
|
134
|
+
nodeWithAccount.coValues[controlledAccount.id] = CoValueState.Available(
|
|
135
|
+
controlledAccount.core,
|
|
136
|
+
);
|
|
137
137
|
controlledAccount.core._cachedContent = undefined;
|
|
138
138
|
|
|
139
139
|
if (!controlledAccount.get("profile")) {
|
|
@@ -145,9 +145,9 @@ export class LocalNode {
|
|
|
145
145
|
for (const coValueEntry of Object.values(
|
|
146
146
|
nodeWithAccount.coValues,
|
|
147
147
|
)) {
|
|
148
|
-
if (coValueEntry.state === "
|
|
148
|
+
if (coValueEntry.state.type === "available") {
|
|
149
149
|
void nodeWithAccount.syncManager.syncCoValue(
|
|
150
|
-
coValueEntry.coValue,
|
|
150
|
+
coValueEntry.state.coValue,
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
153
|
}
|
|
@@ -214,10 +214,9 @@ export class LocalNode {
|
|
|
214
214
|
node.syncManager.local = node;
|
|
215
215
|
|
|
216
216
|
controlledAccount.core.node = node;
|
|
217
|
-
node.coValues[accountID] =
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
};
|
|
217
|
+
node.coValues[accountID] = CoValueState.Available(
|
|
218
|
+
controlledAccount.core,
|
|
219
|
+
);
|
|
221
220
|
controlledAccount.core._cachedContent = undefined;
|
|
222
221
|
|
|
223
222
|
const profileID = account.get("profile");
|
|
@@ -257,7 +256,7 @@ export class LocalNode {
|
|
|
257
256
|
}
|
|
258
257
|
|
|
259
258
|
const coValue = new CoValueCore(header, this);
|
|
260
|
-
this.coValues[coValue.id] =
|
|
259
|
+
this.coValues[coValue.id] = CoValueState.Available(coValue);
|
|
261
260
|
|
|
262
261
|
void this.syncManager.syncCoValue(coValue);
|
|
263
262
|
|
|
@@ -270,7 +269,6 @@ export class LocalNode {
|
|
|
270
269
|
options: {
|
|
271
270
|
dontLoadFrom?: PeerID;
|
|
272
271
|
dontWaitFor?: PeerID;
|
|
273
|
-
onProgress?: (progress: number) => void;
|
|
274
272
|
} = {},
|
|
275
273
|
): Promise<CoValueCore | "unavailable"> {
|
|
276
274
|
if (this.crashed) {
|
|
@@ -283,11 +281,11 @@ export class LocalNode {
|
|
|
283
281
|
if (!entry) {
|
|
284
282
|
const peersToWaitFor = new Set(
|
|
285
283
|
Object.values(this.syncManager.peers)
|
|
286
|
-
.filter((peer) => peer.
|
|
284
|
+
.filter((peer) => peer.isServerOrStoragePeer())
|
|
287
285
|
.map((peer) => peer.id),
|
|
288
286
|
);
|
|
289
287
|
if (options.dontWaitFor) peersToWaitFor.delete(options.dontWaitFor);
|
|
290
|
-
entry =
|
|
288
|
+
entry = CoValueState.Unknown(peersToWaitFor);
|
|
291
289
|
|
|
292
290
|
this.coValues[id] = entry;
|
|
293
291
|
|
|
@@ -302,10 +300,19 @@ export class LocalNode {
|
|
|
302
300
|
);
|
|
303
301
|
});
|
|
304
302
|
}
|
|
305
|
-
if (entry.state === "
|
|
306
|
-
return Promise.resolve(entry.coValue);
|
|
303
|
+
if (entry.state.type === "available") {
|
|
304
|
+
return Promise.resolve(entry.state.coValue);
|
|
307
305
|
}
|
|
308
|
-
|
|
306
|
+
|
|
307
|
+
await entry.state.ready;
|
|
308
|
+
|
|
309
|
+
const updatedEntry = this.coValues[id];
|
|
310
|
+
|
|
311
|
+
if (updatedEntry?.state.type === "available") {
|
|
312
|
+
return Promise.resolve(updatedEntry.state.coValue);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return "unavailable";
|
|
309
316
|
}
|
|
310
317
|
|
|
311
318
|
/**
|
|
@@ -315,11 +322,8 @@ export class LocalNode {
|
|
|
315
322
|
*
|
|
316
323
|
* @category 3. Low-level
|
|
317
324
|
*/
|
|
318
|
-
async load<T extends RawCoValue>(
|
|
319
|
-
id
|
|
320
|
-
onProgress?: (progress: number) => void,
|
|
321
|
-
): Promise<T | "unavailable"> {
|
|
322
|
-
const core = await this.loadCoValueCore(id, { onProgress });
|
|
325
|
+
async load<T extends RawCoValue>(id: CoID<T>): Promise<T | "unavailable"> {
|
|
326
|
+
const core = await this.loadCoValueCore(id);
|
|
323
327
|
|
|
324
328
|
if (core === "unavailable") {
|
|
325
329
|
return "unavailable";
|
|
@@ -333,8 +337,8 @@ export class LocalNode {
|
|
|
333
337
|
if (!entry) {
|
|
334
338
|
return undefined;
|
|
335
339
|
}
|
|
336
|
-
if (entry.state === "
|
|
337
|
-
return entry.coValue.getCurrentContent() as T;
|
|
340
|
+
if (entry.state.type === "available") {
|
|
341
|
+
return entry.state.coValue.getCurrentContent() as T;
|
|
338
342
|
}
|
|
339
343
|
return undefined;
|
|
340
344
|
}
|
|
@@ -465,14 +469,14 @@ export class LocalNode {
|
|
|
465
469
|
`${expectation ? expectation + ": " : ""}Unknown CoValue ${id}`,
|
|
466
470
|
);
|
|
467
471
|
}
|
|
468
|
-
if (entry.state === "
|
|
472
|
+
if (entry.state.type === "unknown") {
|
|
469
473
|
throw new Error(
|
|
470
474
|
`${
|
|
471
475
|
expectation ? expectation + ": " : ""
|
|
472
476
|
}CoValue ${id} not yet loaded`,
|
|
473
477
|
);
|
|
474
478
|
}
|
|
475
|
-
return entry.coValue;
|
|
479
|
+
return entry.state.coValue;
|
|
476
480
|
}
|
|
477
481
|
|
|
478
482
|
/** @internal */
|
|
@@ -547,7 +551,7 @@ export class LocalNode {
|
|
|
547
551
|
}
|
|
548
552
|
|
|
549
553
|
let coValue: CoValueCore;
|
|
550
|
-
|
|
554
|
+
|
|
551
555
|
try {
|
|
552
556
|
coValue = this.expectCoValueLoaded(id, expectation);
|
|
553
557
|
} catch (e) {
|
|
@@ -558,7 +562,7 @@ export class LocalNode {
|
|
|
558
562
|
error: e,
|
|
559
563
|
} satisfies LoadCoValueCoreError);
|
|
560
564
|
}
|
|
561
|
-
|
|
565
|
+
|
|
562
566
|
if (
|
|
563
567
|
coValue.header.type !== "comap" ||
|
|
564
568
|
coValue.header.ruleset.type !== "group" ||
|
|
@@ -673,13 +677,16 @@ export class LocalNode {
|
|
|
673
677
|
const [coValueID, entry] =
|
|
674
678
|
coValuesToCopy[coValuesToCopy.length - 1]!;
|
|
675
679
|
|
|
676
|
-
if (entry.state === "
|
|
680
|
+
if (entry.state.type === "unknown") {
|
|
677
681
|
coValuesToCopy.pop();
|
|
678
682
|
continue;
|
|
679
683
|
} else {
|
|
680
|
-
const allDepsCopied = entry.coValue
|
|
684
|
+
const allDepsCopied = entry.state.coValue
|
|
681
685
|
.getDependedOnCoValues()
|
|
682
|
-
.every(
|
|
686
|
+
.every(
|
|
687
|
+
(dep) =>
|
|
688
|
+
newNode.coValues[dep]?.state.type === "available",
|
|
689
|
+
);
|
|
683
690
|
|
|
684
691
|
if (!allDepsCopied) {
|
|
685
692
|
// move to end of queue
|
|
@@ -688,15 +695,13 @@ export class LocalNode {
|
|
|
688
695
|
}
|
|
689
696
|
|
|
690
697
|
const newCoValue = new CoValueCore(
|
|
691
|
-
entry.coValue.header,
|
|
698
|
+
entry.state.coValue.header,
|
|
692
699
|
newNode,
|
|
693
|
-
new Map(entry.coValue.sessionLogs),
|
|
700
|
+
new Map(entry.state.coValue.sessionLogs),
|
|
694
701
|
);
|
|
695
702
|
|
|
696
|
-
newNode.coValues[coValueID as RawCoID] =
|
|
697
|
-
|
|
698
|
-
coValue: newCoValue,
|
|
699
|
-
};
|
|
703
|
+
newNode.coValues[coValueID as RawCoID] =
|
|
704
|
+
CoValueState.Available(newCoValue);
|
|
700
705
|
|
|
701
706
|
coValuesToCopy.pop();
|
|
702
707
|
}
|
|
@@ -722,30 +727,6 @@ export class LocalNode {
|
|
|
722
727
|
}
|
|
723
728
|
}
|
|
724
729
|
|
|
725
|
-
/** @internal */
|
|
726
|
-
type CoValueState =
|
|
727
|
-
| {
|
|
728
|
-
state: "loading";
|
|
729
|
-
done: Promise<CoValueCore | "unavailable">;
|
|
730
|
-
resolve: (coValue: CoValueCore | "unavailable") => void;
|
|
731
|
-
onProgress?: (progress: number) => void;
|
|
732
|
-
firstPeerState: {
|
|
733
|
-
[peerID: string]:
|
|
734
|
-
| {
|
|
735
|
-
type: "waiting";
|
|
736
|
-
done: Promise<void>;
|
|
737
|
-
resolve: () => void;
|
|
738
|
-
}
|
|
739
|
-
| { type: "available" }
|
|
740
|
-
| { type: "unavailable" };
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
| {
|
|
744
|
-
state: "loaded";
|
|
745
|
-
coValue: CoValueCore;
|
|
746
|
-
onProgress?: (progress: number) => void;
|
|
747
|
-
};
|
|
748
|
-
|
|
749
730
|
export type LoadCoValueCoreError = {
|
|
750
731
|
type: "ErrorLoadingCoValueCore";
|
|
751
732
|
error: unknown;
|
|
@@ -770,31 +751,3 @@ export type ResolveAccountAgentError =
|
|
|
770
751
|
| LoadCoValueCoreError
|
|
771
752
|
| AccountUnavailableFromAllPeersError
|
|
772
753
|
| UnexpectedlyNotAccountError;
|
|
773
|
-
|
|
774
|
-
/** @internal */
|
|
775
|
-
export function newLoadingState(
|
|
776
|
-
currentPeerIds: Set<PeerID>,
|
|
777
|
-
onProgress?: (progress: number) => void,
|
|
778
|
-
): CoValueState {
|
|
779
|
-
let resolve: (coValue: CoValueCore | "unavailable") => void;
|
|
780
|
-
|
|
781
|
-
const promise = new Promise<CoValueCore | "unavailable">((r) => {
|
|
782
|
-
resolve = r;
|
|
783
|
-
});
|
|
784
|
-
|
|
785
|
-
return {
|
|
786
|
-
state: "loading",
|
|
787
|
-
done: promise,
|
|
788
|
-
resolve: resolve!,
|
|
789
|
-
onProgress,
|
|
790
|
-
firstPeerState: Object.fromEntries(
|
|
791
|
-
[...currentPeerIds].map((id) => {
|
|
792
|
-
let resolve: () => void;
|
|
793
|
-
const done = new Promise<void>((r) => {
|
|
794
|
-
resolve = r;
|
|
795
|
-
});
|
|
796
|
-
return [id, { type: "waiting", done, resolve: resolve! }];
|
|
797
|
-
}),
|
|
798
|
-
),
|
|
799
|
-
};
|
|
800
|
-
}
|
package/src/storage/index.ts
CHANGED
|
@@ -79,7 +79,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
79
79
|
|
|
80
80
|
if (msg.action === "content") {
|
|
81
81
|
await this.handleNewContent(msg);
|
|
82
|
-
} else {
|
|
82
|
+
} else if (msg.action === 'load' || msg.action === 'known') {
|
|
83
83
|
await this.sendNewContent(msg.id, msg, undefined);
|
|
84
84
|
}
|
|
85
85
|
} catch (e) {
|
|
@@ -560,7 +560,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
|
|
|
560
560
|
"storage",
|
|
561
561
|
{
|
|
562
562
|
peer1role: "client",
|
|
563
|
-
peer2role: "
|
|
563
|
+
peer2role: "storage",
|
|
564
564
|
trace,
|
|
565
565
|
crashOnClose: true,
|
|
566
566
|
},
|