cojson 0.13.10 → 0.13.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/CoValuesStore.d.ts +3 -1
- package/dist/CoValuesStore.d.ts.map +1 -1
- package/dist/CoValuesStore.js +7 -6
- package/dist/CoValuesStore.js.map +1 -1
- package/dist/PeerKnownStates.d.ts +5 -25
- package/dist/PeerKnownStates.d.ts.map +1 -1
- package/dist/PeerKnownStates.js +7 -20
- package/dist/PeerKnownStates.js.map +1 -1
- package/dist/PeerState.d.ts +14 -9
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js +51 -8
- package/dist/PeerState.js.map +1 -1
- package/dist/SyncStateManager.js +2 -2
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueCore.js +2 -2
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValueState.d.ts +21 -46
- package/dist/coValueState.d.ts.map +1 -1
- package/dist/coValueState.js +174 -246
- package/dist/coValueState.js.map +1 -1
- package/dist/coValues/coList.d.ts +13 -2
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +60 -34
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +45 -0
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +61 -11
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/coValues/group.js +2 -2
- package/dist/coValues/group.js.map +1 -1
- package/dist/exports.d.ts +2 -4
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +1 -2
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +20 -16
- package/dist/localNode.js.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +40 -92
- package/dist/sync.js.map +1 -1
- package/dist/tests/PeerKnownStates.test.js +9 -14
- package/dist/tests/PeerKnownStates.test.js.map +1 -1
- package/dist/tests/PeerState.test.js +22 -34
- package/dist/tests/PeerState.test.js.map +1 -1
- package/dist/tests/coList.test.js +63 -0
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +66 -11
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coValueState.test.js +57 -104
- package/dist/tests/coValueState.test.js.map +1 -1
- package/dist/tests/group.test.js +1 -2
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/messagesTestUtils.d.ts +4 -1
- package/dist/tests/messagesTestUtils.d.ts.map +1 -1
- package/dist/tests/messagesTestUtils.js +10 -0
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +65 -3
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +8 -8
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.test.js +6 -4
- package/dist/tests/sync.test.js.map +1 -1
- package/package.json +1 -1
- package/src/CoValuesStore.ts +9 -6
- package/src/PeerKnownStates.ts +19 -56
- package/src/PeerState.ts +69 -13
- package/src/SyncStateManager.ts +2 -2
- package/src/coValueCore.ts +2 -2
- package/src/coValueState.ts +197 -317
- package/src/coValues/coList.ts +84 -44
- package/src/coValues/coPlainText.ts +75 -11
- package/src/coValues/group.ts +2 -2
- package/src/exports.ts +0 -6
- package/src/localNode.ts +30 -21
- package/src/sync.ts +46 -95
- package/src/tests/PeerKnownStates.test.ts +9 -14
- package/src/tests/PeerState.test.ts +27 -40
- package/src/tests/coList.test.ts +83 -0
- package/src/tests/coPlainText.test.ts +81 -11
- package/src/tests/coValueState.test.ts +55 -106
- package/src/tests/group.test.ts +2 -2
- package/src/tests/messagesTestUtils.ts +12 -1
- package/src/tests/sync.mesh.test.ts +81 -3
- package/src/tests/sync.peerReconciliation.test.ts +8 -8
- package/src/tests/sync.test.ts +8 -23
- package/dist/storage/FileSystem.d.ts +0 -37
- package/dist/storage/FileSystem.d.ts.map +0 -1
- package/dist/storage/FileSystem.js +0 -48
- package/dist/storage/FileSystem.js.map +0 -1
- package/dist/storage/chunksAndKnownStates.d.ts +0 -7
- package/dist/storage/chunksAndKnownStates.d.ts.map +0 -1
- package/dist/storage/chunksAndKnownStates.js +0 -98
- package/dist/storage/chunksAndKnownStates.js.map +0 -1
- package/dist/storage/index.d.ts +0 -52
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -335
- package/dist/storage/index.js.map +0 -1
- package/src/storage/FileSystem.ts +0 -113
- package/src/storage/chunksAndKnownStates.ts +0 -137
- package/src/storage/index.ts +0 -531
package/src/coValues/coList.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { CoID, RawCoValue } from "../coValue.js";
|
|
|
2
2
|
import { CoValueCore } from "../coValueCore.js";
|
|
3
3
|
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
4
4
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
5
|
+
import { CoValueKnownState } from "../sync.js";
|
|
5
6
|
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
|
|
6
7
|
import { isCoValue } from "../typeUtils/isCoValue.js";
|
|
7
8
|
import { RawAccountID } from "./account.js";
|
|
@@ -81,6 +82,8 @@ export class RawCoListView<
|
|
|
81
82
|
madeAt: number;
|
|
82
83
|
opID: OpID;
|
|
83
84
|
}[];
|
|
85
|
+
/** @internal */
|
|
86
|
+
knownTransactions: CoValueKnownState["sessions"];
|
|
84
87
|
|
|
85
88
|
/** @internal */
|
|
86
89
|
constructor(core: CoValueCore) {
|
|
@@ -95,12 +98,24 @@ export class RawCoListView<
|
|
|
95
98
|
this.deletionsByInsertion = {};
|
|
96
99
|
this.afterStart = [];
|
|
97
100
|
this.beforeEnd = [];
|
|
101
|
+
this.knownTransactions = {};
|
|
102
|
+
|
|
103
|
+
this.processNewTransactions();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
processNewTransactions() {
|
|
107
|
+
const newTransactions = this.core.getValidTransactions({
|
|
108
|
+
ignorePrivateTransactions: false,
|
|
109
|
+
knownTransactions: this.knownTransactions,
|
|
110
|
+
});
|
|
98
111
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
if (newTransactions.length === 0) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this._cachedEntries = undefined;
|
|
117
|
+
|
|
118
|
+
for (const { txID, changes, madeAt } of newTransactions) {
|
|
104
119
|
for (const [changeIdx, changeUntyped] of changes.entries()) {
|
|
105
120
|
const change = changeUntyped as ListOpPayload<Item>;
|
|
106
121
|
|
|
@@ -192,6 +207,11 @@ export class RawCoListView<
|
|
|
192
207
|
);
|
|
193
208
|
}
|
|
194
209
|
}
|
|
210
|
+
|
|
211
|
+
this.knownTransactions[txID.sessionID] = Math.max(
|
|
212
|
+
this.knownTransactions[txID.sessionID] ?? 0,
|
|
213
|
+
txID.txIndex,
|
|
214
|
+
);
|
|
195
215
|
}
|
|
196
216
|
}
|
|
197
217
|
|
|
@@ -279,30 +299,52 @@ export class RawCoListView<
|
|
|
279
299
|
opID: OpID;
|
|
280
300
|
}[],
|
|
281
301
|
) {
|
|
282
|
-
const
|
|
283
|
-
|
|
302
|
+
const todo = [opID]; // a stack with the next item to do at the end
|
|
303
|
+
const predecessorsVisited = new Set<OpID>();
|
|
284
304
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
305
|
+
while (todo.length > 0) {
|
|
306
|
+
const currentOpID = todo[todo.length - 1]!;
|
|
307
|
+
|
|
308
|
+
const entry =
|
|
309
|
+
this.insertions[currentOpID.sessionID]?.[currentOpID.txIndex]?.[
|
|
310
|
+
currentOpID.changeIdx
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
if (!entry) {
|
|
314
|
+
throw new Error("Missing op " + currentOpID);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const shouldTraversePredecessors =
|
|
318
|
+
entry.predecessors.length > 0 && !predecessorsVisited.has(currentOpID);
|
|
319
|
+
|
|
320
|
+
// We navigate the predecessors before processing the current opID in the list
|
|
321
|
+
if (shouldTraversePredecessors) {
|
|
322
|
+
for (let i = entry.predecessors.length - 1; i >= 0; i--) {
|
|
323
|
+
todo.push(entry.predecessors[i]!);
|
|
324
|
+
}
|
|
325
|
+
predecessorsVisited.add(currentOpID);
|
|
326
|
+
} else {
|
|
327
|
+
// Remove the current opID from the todo stack to consider it processed.
|
|
328
|
+
todo.pop();
|
|
329
|
+
|
|
330
|
+
const deleted =
|
|
331
|
+
(this.deletionsByInsertion[currentOpID.sessionID]?.[
|
|
332
|
+
currentOpID.txIndex
|
|
333
|
+
]?.[currentOpID.changeIdx]?.length || 0) > 0;
|
|
334
|
+
|
|
335
|
+
if (!deleted) {
|
|
336
|
+
arr.push({
|
|
337
|
+
value: entry.value,
|
|
338
|
+
madeAt: entry.madeAt,
|
|
339
|
+
opID: currentOpID,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// traverse successors in reverse for correct insertion behavior
|
|
344
|
+
for (const successor of entry.successors) {
|
|
345
|
+
todo.push(successor);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
306
348
|
}
|
|
307
349
|
}
|
|
308
350
|
|
|
@@ -410,6 +452,15 @@ export class RawCoList<
|
|
|
410
452
|
this.appendItems([item], after, privacy);
|
|
411
453
|
}
|
|
412
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Appends `items` to the list at index `after`. If `after` is negative, it is treated as `0`.
|
|
457
|
+
*
|
|
458
|
+
* If `privacy` is `"private"` **(default)**, `items` are encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
|
|
459
|
+
*
|
|
460
|
+
* If `privacy` is `"trusting"`, `items` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
|
|
461
|
+
*
|
|
462
|
+
* @category 2. Editing
|
|
463
|
+
*/
|
|
413
464
|
appendItems(
|
|
414
465
|
items: Item[],
|
|
415
466
|
after?: number,
|
|
@@ -421,7 +472,7 @@ export class RawCoList<
|
|
|
421
472
|
? entries.length > 0
|
|
422
473
|
? entries.length - 1
|
|
423
474
|
: 0
|
|
424
|
-
: after;
|
|
475
|
+
: Math.max(0, after);
|
|
425
476
|
let opIDBefore: OpID | "start";
|
|
426
477
|
if (entries.length > 0) {
|
|
427
478
|
const entryBefore = entries[after];
|
|
@@ -450,7 +501,7 @@ export class RawCoList<
|
|
|
450
501
|
|
|
451
502
|
this.core.makeTransaction(changes, privacy);
|
|
452
503
|
|
|
453
|
-
this.
|
|
504
|
+
this.processNewTransactions();
|
|
454
505
|
}
|
|
455
506
|
|
|
456
507
|
/**
|
|
@@ -497,7 +548,7 @@ export class RawCoList<
|
|
|
497
548
|
privacy,
|
|
498
549
|
);
|
|
499
550
|
|
|
500
|
-
this.
|
|
551
|
+
this.processNewTransactions();
|
|
501
552
|
}
|
|
502
553
|
|
|
503
554
|
/** Deletes the item at index `at`.
|
|
@@ -524,7 +575,7 @@ export class RawCoList<
|
|
|
524
575
|
privacy,
|
|
525
576
|
);
|
|
526
577
|
|
|
527
|
-
this.
|
|
578
|
+
this.processNewTransactions();
|
|
528
579
|
}
|
|
529
580
|
|
|
530
581
|
replace(
|
|
@@ -552,17 +603,6 @@ export class RawCoList<
|
|
|
552
603
|
],
|
|
553
604
|
privacy,
|
|
554
605
|
);
|
|
555
|
-
this.
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/** @internal */
|
|
559
|
-
rebuildFromCore() {
|
|
560
|
-
const listAfter = new RawCoList(this.core) as this;
|
|
561
|
-
|
|
562
|
-
this.afterStart = listAfter.afterStart;
|
|
563
|
-
this.beforeEnd = listAfter.beforeEnd;
|
|
564
|
-
this.insertions = listAfter.insertions;
|
|
565
|
-
this.deletionsByInsertion = listAfter.deletionsByInsertion;
|
|
566
|
-
this._cachedEntries = undefined;
|
|
606
|
+
this.processNewTransactions();
|
|
567
607
|
}
|
|
568
608
|
}
|
|
@@ -2,6 +2,12 @@ import { CoValueCore } from "../coValueCore.js";
|
|
|
2
2
|
import { JsonObject } from "../jsonValue.js";
|
|
3
3
|
import { DeletionOpPayload, OpID, RawCoList } from "./coList.js";
|
|
4
4
|
|
|
5
|
+
declare const navigator:
|
|
6
|
+
| {
|
|
7
|
+
language: string;
|
|
8
|
+
}
|
|
9
|
+
| undefined;
|
|
10
|
+
|
|
5
11
|
export type StringifiedOpID = string & { __stringifiedOpID: true };
|
|
6
12
|
|
|
7
13
|
export function stringifyOpID(opID: OpID): StringifiedOpID {
|
|
@@ -15,6 +21,33 @@ type PlaintextIdxMapping = {
|
|
|
15
21
|
idxBeforeOpID: { [opID: StringifiedOpID]: number };
|
|
16
22
|
};
|
|
17
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A collaborative plain text implementation that supports grapheme-accurate editing.
|
|
26
|
+
*
|
|
27
|
+
* Locale support:
|
|
28
|
+
* - Locale can be specified in the meta field when creating the text: `{ meta: { locale: "ja-JP" } }`
|
|
29
|
+
* - If no locale is specified, falls back to browser's locale (`navigator.language`)
|
|
30
|
+
* - If browser locale is not available, defaults to 'en'
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // With specific locale
|
|
35
|
+
* const textJa = node.createCoValue({
|
|
36
|
+
* type: "coplaintext",
|
|
37
|
+
* ruleset: { type: "unsafeAllowAll" },
|
|
38
|
+
* meta: { locale: "ja-JP" },
|
|
39
|
+
* ...Crypto.createdNowUnique(),
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Using browser locale
|
|
43
|
+
* const text = node.createCoValue({
|
|
44
|
+
* type: "coplaintext",
|
|
45
|
+
* ruleset: { type: "unsafeAllowAll" },
|
|
46
|
+
* meta: null,
|
|
47
|
+
* ...Crypto.createdNowUnique(),
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
18
51
|
export class RawCoPlainText<
|
|
19
52
|
Meta extends JsonObject | null = JsonObject | null,
|
|
20
53
|
> extends RawCoList<string, Meta> {
|
|
@@ -36,7 +69,17 @@ export class RawCoPlainText<
|
|
|
36
69
|
"Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
|
|
37
70
|
);
|
|
38
71
|
}
|
|
39
|
-
|
|
72
|
+
|
|
73
|
+
// Use locale from meta if provided, fallback to browser locale, or 'en' as last resort
|
|
74
|
+
const effectiveLocale =
|
|
75
|
+
(core.header.meta &&
|
|
76
|
+
typeof core.header.meta === "object" &&
|
|
77
|
+
"locale" in core.header.meta
|
|
78
|
+
? (core.header.meta.locale as string)
|
|
79
|
+
: undefined) ||
|
|
80
|
+
(typeof navigator !== "undefined" ? navigator.language : "en");
|
|
81
|
+
|
|
82
|
+
this._segmenter = new Intl.Segmenter(effectiveLocale, {
|
|
40
83
|
granularity: "grapheme",
|
|
41
84
|
});
|
|
42
85
|
}
|
|
@@ -78,7 +121,16 @@ export class RawCoPlainText<
|
|
|
78
121
|
.join("");
|
|
79
122
|
}
|
|
80
123
|
|
|
81
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Inserts `text` before the character at index `idx`.
|
|
126
|
+
* If idx is 0, inserts at the start of the text.
|
|
127
|
+
*
|
|
128
|
+
* @param idx - The index of the character to insert before
|
|
129
|
+
* @param text - The text to insert
|
|
130
|
+
* @param privacy - Whether the operation should be private or trusting
|
|
131
|
+
* @category 2. Editing
|
|
132
|
+
*/
|
|
133
|
+
insertBefore(
|
|
82
134
|
idx: number,
|
|
83
135
|
text: string,
|
|
84
136
|
privacy: "private" | "trusting" = "private",
|
|
@@ -86,21 +138,33 @@ export class RawCoPlainText<
|
|
|
86
138
|
const graphemes = [...this._segmenter.segment(text)].map((g) => g.segment);
|
|
87
139
|
|
|
88
140
|
if (idx === 0) {
|
|
89
|
-
// For insertions at start,
|
|
141
|
+
// For insertions at start, prepend each character in reverse
|
|
90
142
|
for (const grapheme of graphemes.reverse()) {
|
|
91
143
|
this.prepend(grapheme, 0, privacy);
|
|
92
144
|
}
|
|
93
145
|
} else {
|
|
94
|
-
// For other insertions,
|
|
95
|
-
|
|
96
|
-
let after = idx - 1;
|
|
97
|
-
for (const grapheme of graphemes) {
|
|
98
|
-
this.append(grapheme, after, privacy);
|
|
99
|
-
after++; // Move the insertion point forward for each grapheme
|
|
100
|
-
}
|
|
146
|
+
// For other insertions, append after the previous character
|
|
147
|
+
this.appendItems(graphemes, idx - 1, privacy);
|
|
101
148
|
}
|
|
102
149
|
}
|
|
103
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Inserts `text` after the character at index `idx`.
|
|
153
|
+
*
|
|
154
|
+
* @param idx - The index of the character to insert after
|
|
155
|
+
* @param text - The text to insert
|
|
156
|
+
* @param privacy - Whether the operation should be private or trusting
|
|
157
|
+
* @category 2. Editing
|
|
158
|
+
*/
|
|
159
|
+
insertAfter(
|
|
160
|
+
idx: number,
|
|
161
|
+
text: string,
|
|
162
|
+
privacy: "private" | "trusting" = "private",
|
|
163
|
+
) {
|
|
164
|
+
const graphemes = [...this._segmenter.segment(text)].map((g) => g.segment);
|
|
165
|
+
this.appendItems(graphemes, idx, privacy);
|
|
166
|
+
}
|
|
167
|
+
|
|
104
168
|
deleteRange(
|
|
105
169
|
{ from, to }: { from: number; to: number },
|
|
106
170
|
privacy: "private" | "trusting" = "private",
|
|
@@ -123,6 +187,6 @@ export class RawCoPlainText<
|
|
|
123
187
|
}
|
|
124
188
|
this.core.makeTransaction(ops, privacy);
|
|
125
189
|
|
|
126
|
-
this.
|
|
190
|
+
this.processNewTransactions();
|
|
127
191
|
}
|
|
128
192
|
}
|
package/src/coValues/group.ts
CHANGED
|
@@ -186,8 +186,8 @@ export class RawGroup<
|
|
|
186
186
|
const child = store.get(id);
|
|
187
187
|
|
|
188
188
|
if (
|
|
189
|
-
child.
|
|
190
|
-
child.
|
|
189
|
+
child.highLevelState === "unknown" ||
|
|
190
|
+
child.highLevelState === "unavailable"
|
|
191
191
|
) {
|
|
192
192
|
child.loadFromPeers(peers).catch(() => {
|
|
193
193
|
logger.error(`Failed to load child group ${id}`);
|
package/src/exports.ts
CHANGED
|
@@ -79,8 +79,6 @@ type Value = JsonValue | AnyRawCoValue;
|
|
|
79
79
|
import { CO_VALUE_LOADING_CONFIG } from "./coValueState.js";
|
|
80
80
|
import { logger } from "./logger.js";
|
|
81
81
|
import { getPriorityFromHeader } from "./priority.js";
|
|
82
|
-
import { FileSystem } from "./storage/FileSystem.js";
|
|
83
|
-
import { BlockFilename, LSMStorage, WalFilename } from "./storage/index.js";
|
|
84
82
|
|
|
85
83
|
/** @hidden */
|
|
86
84
|
export const cojsonInternals = {
|
|
@@ -143,7 +141,6 @@ export {
|
|
|
143
141
|
CryptoProvider,
|
|
144
142
|
SyncMessage,
|
|
145
143
|
isRawCoID,
|
|
146
|
-
LSMStorage,
|
|
147
144
|
emptyKnownState,
|
|
148
145
|
RawCoPlainText,
|
|
149
146
|
stringifyOpID,
|
|
@@ -154,9 +151,6 @@ export {
|
|
|
154
151
|
|
|
155
152
|
export type {
|
|
156
153
|
Value,
|
|
157
|
-
FileSystem,
|
|
158
|
-
BlockFilename,
|
|
159
|
-
WalFilename,
|
|
160
154
|
IncomingSyncStream,
|
|
161
155
|
OutgoingSyncQueue,
|
|
162
156
|
DisconnectedError,
|
package/src/localNode.ts
CHANGED
|
@@ -126,7 +126,7 @@ export class LocalNode {
|
|
|
126
126
|
);
|
|
127
127
|
|
|
128
128
|
nodeWithAccount.account = controlledAccount;
|
|
129
|
-
nodeWithAccount.coValuesStore.
|
|
129
|
+
nodeWithAccount.coValuesStore.internalMarkMagicallyAvailable(
|
|
130
130
|
controlledAccount.id,
|
|
131
131
|
controlledAccount.core,
|
|
132
132
|
);
|
|
@@ -139,10 +139,8 @@ export class LocalNode {
|
|
|
139
139
|
// we shouldn't need this, but it fixes account data not syncing for new accounts
|
|
140
140
|
function syncAllCoValuesAfterCreateAccount() {
|
|
141
141
|
for (const coValueEntry of nodeWithAccount.coValuesStore.getValues()) {
|
|
142
|
-
if (coValueEntry.
|
|
143
|
-
void nodeWithAccount.syncManager.syncCoValue(
|
|
144
|
-
coValueEntry.state.coValue,
|
|
145
|
-
);
|
|
142
|
+
if (coValueEntry.isAvailable()) {
|
|
143
|
+
void nodeWithAccount.syncManager.syncCoValue(coValueEntry.core);
|
|
146
144
|
}
|
|
147
145
|
}
|
|
148
146
|
}
|
|
@@ -208,7 +206,10 @@ export class LocalNode {
|
|
|
208
206
|
node.syncManager.local = node;
|
|
209
207
|
|
|
210
208
|
controlledAccount.core.node = node;
|
|
211
|
-
node.coValuesStore.
|
|
209
|
+
node.coValuesStore.internalMarkMagicallyAvailable(
|
|
210
|
+
accountID,
|
|
211
|
+
controlledAccount.core,
|
|
212
|
+
);
|
|
212
213
|
controlledAccount.core._cachedContent = undefined;
|
|
213
214
|
|
|
214
215
|
const profileID = account.get("profile");
|
|
@@ -245,7 +246,7 @@ export class LocalNode {
|
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
const coValue = new CoValueCore(header, this);
|
|
248
|
-
this.coValuesStore.
|
|
249
|
+
this.coValuesStore.internalMarkMagicallyAvailable(coValue.id, coValue);
|
|
249
250
|
|
|
250
251
|
void this.syncManager.syncCoValue(coValue);
|
|
251
252
|
|
|
@@ -265,10 +266,17 @@ export class LocalNode {
|
|
|
265
266
|
|
|
266
267
|
const entry = this.coValuesStore.get(id);
|
|
267
268
|
|
|
268
|
-
if (
|
|
269
|
+
if (
|
|
270
|
+
entry.highLevelState === "unknown" ||
|
|
271
|
+
entry.highLevelState === "unavailable"
|
|
272
|
+
) {
|
|
269
273
|
const peers =
|
|
270
274
|
this.syncManager.getServerAndStoragePeers(skipLoadingFromPeer);
|
|
271
275
|
|
|
276
|
+
if (peers.length === 0) {
|
|
277
|
+
return "unavailable";
|
|
278
|
+
}
|
|
279
|
+
|
|
272
280
|
await entry.loadFromPeers(peers).catch((e) => {
|
|
273
281
|
logger.error("Error loading from peers", {
|
|
274
282
|
id,
|
|
@@ -309,8 +317,8 @@ export class LocalNode {
|
|
|
309
317
|
getLoaded<T extends RawCoValue>(id: CoID<T>): T | undefined {
|
|
310
318
|
const entry = this.coValuesStore.get(id);
|
|
311
319
|
|
|
312
|
-
if (entry.
|
|
313
|
-
return entry.
|
|
320
|
+
if (entry.isAvailable()) {
|
|
321
|
+
return entry.core.getCurrentContent() as T;
|
|
314
322
|
}
|
|
315
323
|
|
|
316
324
|
return undefined;
|
|
@@ -439,12 +447,12 @@ export class LocalNode {
|
|
|
439
447
|
expectCoValueLoaded(id: RawCoID, expectation?: string): CoValueCore {
|
|
440
448
|
const entry = this.coValuesStore.get(id);
|
|
441
449
|
|
|
442
|
-
if (entry.
|
|
450
|
+
if (!entry.isAvailable()) {
|
|
443
451
|
throw new Error(
|
|
444
|
-
`${expectation ? expectation + ": " : ""}CoValue ${id} not yet loaded. Current state: ${entry
|
|
452
|
+
`${expectation ? expectation + ": " : ""}CoValue ${id} not yet loaded. Current state: ${JSON.stringify(entry)}`,
|
|
445
453
|
);
|
|
446
454
|
}
|
|
447
|
-
return entry.
|
|
455
|
+
return entry.core;
|
|
448
456
|
}
|
|
449
457
|
|
|
450
458
|
/** @internal */
|
|
@@ -638,15 +646,13 @@ export class LocalNode {
|
|
|
638
646
|
while (coValuesToCopy.length > 0) {
|
|
639
647
|
const [coValueID, entry] = coValuesToCopy[coValuesToCopy.length - 1]!;
|
|
640
648
|
|
|
641
|
-
if (entry.
|
|
649
|
+
if (!entry.isAvailable()) {
|
|
642
650
|
coValuesToCopy.pop();
|
|
643
651
|
continue;
|
|
644
652
|
} else {
|
|
645
|
-
const allDepsCopied = entry.
|
|
653
|
+
const allDepsCopied = entry.core
|
|
646
654
|
.getDependedOnCoValues()
|
|
647
|
-
.every(
|
|
648
|
-
(dep) => newNode.coValuesStore.get(dep).state.type === "available",
|
|
649
|
-
);
|
|
655
|
+
.every((dep) => newNode.coValuesStore.get(dep).isAvailable());
|
|
650
656
|
|
|
651
657
|
if (!allDepsCopied) {
|
|
652
658
|
// move to end of queue
|
|
@@ -655,12 +661,15 @@ export class LocalNode {
|
|
|
655
661
|
}
|
|
656
662
|
|
|
657
663
|
const newCoValue = new CoValueCore(
|
|
658
|
-
entry.
|
|
664
|
+
entry.core.header,
|
|
659
665
|
newNode,
|
|
660
|
-
new Map(entry.
|
|
666
|
+
new Map(entry.core.sessionLogs),
|
|
661
667
|
);
|
|
662
668
|
|
|
663
|
-
newNode.coValuesStore.
|
|
669
|
+
newNode.coValuesStore.internalMarkMagicallyAvailable(
|
|
670
|
+
coValueID,
|
|
671
|
+
newCoValue,
|
|
672
|
+
);
|
|
664
673
|
|
|
665
674
|
coValuesToCopy.pop();
|
|
666
675
|
}
|