cojson 0.8.38 → 0.8.41
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 +15 -0
- package/dist/native/PeerState.js +11 -2
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/{SyncStateSubscriptionManager.js → SyncStateManager.js} +35 -24
- package/dist/native/SyncStateManager.js.map +1 -0
- package/dist/native/coValueCore.js +25 -5
- package/dist/native/coValueCore.js.map +1 -1
- package/dist/native/coValues/coMap.js +98 -103
- package/dist/native/coValues/coMap.js.map +1 -1
- package/dist/native/coValues/coStream.js +17 -6
- package/dist/native/coValues/coStream.js.map +1 -1
- package/dist/native/coValues/group.js +127 -39
- package/dist/native/coValues/group.js.map +1 -1
- package/dist/native/exports.js.map +1 -1
- package/dist/native/localNode.js +5 -2
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/permissions.js +51 -3
- package/dist/native/permissions.js.map +1 -1
- package/dist/native/sync.js +34 -10
- package/dist/native/sync.js.map +1 -1
- package/dist/web/PeerState.js +11 -2
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/{SyncStateSubscriptionManager.js → SyncStateManager.js} +35 -24
- package/dist/web/SyncStateManager.js.map +1 -0
- package/dist/web/coValueCore.js +25 -5
- package/dist/web/coValueCore.js.map +1 -1
- package/dist/web/coValues/coMap.js +98 -103
- package/dist/web/coValues/coMap.js.map +1 -1
- package/dist/web/coValues/coStream.js +17 -6
- package/dist/web/coValues/coStream.js.map +1 -1
- package/dist/web/coValues/group.js +127 -39
- package/dist/web/coValues/group.js.map +1 -1
- package/dist/web/exports.js.map +1 -1
- package/dist/web/localNode.js +5 -2
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/permissions.js +51 -3
- package/dist/web/permissions.js.map +1 -1
- package/dist/web/sync.js +34 -10
- package/dist/web/sync.js.map +1 -1
- package/package.json +3 -5
- package/src/PeerState.ts +12 -2
- package/src/{SyncStateSubscriptionManager.ts → SyncStateManager.ts} +48 -35
- package/src/coValueCore.ts +43 -9
- package/src/coValues/coMap.ts +126 -127
- package/src/coValues/coStream.ts +27 -10
- package/src/coValues/group.ts +218 -50
- package/src/exports.ts +2 -1
- package/src/localNode.ts +5 -2
- package/src/permissions.ts +71 -8
- package/src/sync.ts +57 -23
- package/src/tests/PeerState.test.ts +49 -0
- package/src/tests/PriorityBasedMessageQueue.test.ts +6 -73
- package/src/tests/{SyncStateSubscriptionManager.test.ts → SyncStateManager.test.ts} +109 -25
- package/src/tests/coMap.test.ts +2 -2
- package/src/tests/group.test.ts +338 -47
- package/src/tests/permissions.test.ts +324 -0
- package/src/tests/sync.test.ts +112 -71
- package/src/tests/testUtils.ts +126 -17
- package/dist/native/SyncStateSubscriptionManager.js.map +0 -1
- package/dist/web/SyncStateSubscriptionManager.js.map +0 -1
package/src/coValues/coMap.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CoID, RawCoValue } from "../coValue.js";
|
|
2
|
-
import { CoValueCore
|
|
2
|
+
import { CoValueCore } from "../coValueCore.js";
|
|
3
3
|
import { AgentID, 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";
|
|
@@ -46,14 +47,14 @@ export class RawCoMapView<
|
|
|
46
47
|
/** @internal */
|
|
47
48
|
latestTxMadeAt: number;
|
|
48
49
|
/** @internal */
|
|
49
|
-
|
|
50
|
+
ops: {
|
|
50
51
|
[Key in keyof Shape & string]?: MapOp<Key, Shape[Key]>[];
|
|
51
52
|
};
|
|
52
53
|
/** @internal */
|
|
53
|
-
|
|
54
|
+
knownTransactions: CoValueKnownState["sessions"];
|
|
54
55
|
|
|
55
56
|
/** @internal */
|
|
56
|
-
|
|
57
|
+
ignorePrivateTransactions: boolean;
|
|
57
58
|
/** @internal */
|
|
58
59
|
atTimeFilter?: number = undefined;
|
|
59
60
|
/** @category 6. Meta */
|
|
@@ -64,123 +65,81 @@ export class RawCoMapView<
|
|
|
64
65
|
core: CoValueCore,
|
|
65
66
|
options?: {
|
|
66
67
|
ignorePrivateTransactions: boolean;
|
|
67
|
-
atTime?: number;
|
|
68
|
-
validSortedTransactions?: DecryptedTransaction[];
|
|
69
|
-
cachedOps?: {
|
|
70
|
-
[Key in keyof Shape & string]?: MapOp<Key, Shape[Key]>[];
|
|
71
|
-
};
|
|
72
68
|
},
|
|
73
69
|
) {
|
|
74
70
|
this.id = core.id as CoID<this>;
|
|
75
71
|
this.core = core;
|
|
76
|
-
this.latest = {};
|
|
77
72
|
this.latestTxMadeAt = 0;
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
this.
|
|
73
|
+
this.ignorePrivateTransactions =
|
|
74
|
+
options?.ignorePrivateTransactions ?? false;
|
|
75
|
+
this.ops = {};
|
|
76
|
+
this.latest = {};
|
|
77
|
+
this.knownTransactions = {};
|
|
81
78
|
|
|
82
|
-
this.
|
|
79
|
+
this.processNewTransactions();
|
|
83
80
|
}
|
|
84
81
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return this.validSortedTransactions;
|
|
82
|
+
processNewTransactions() {
|
|
83
|
+
if (this.isTimeTravelEntity()) {
|
|
84
|
+
throw new Error("Cannot process transactions on a time travel entity");
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
const
|
|
92
|
-
ignorePrivateTransactions:
|
|
93
|
-
this.options?.ignorePrivateTransactions ?? false,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
this.validSortedTransactions = validSortedTransactions;
|
|
97
|
-
|
|
98
|
-
return validSortedTransactions;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private resetCachedValues() {
|
|
102
|
-
this.validSortedTransactions = undefined;
|
|
103
|
-
this.cachedOps = undefined;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private processLatestTransactions() {
|
|
107
|
-
// Reset all internal state and cached values
|
|
108
|
-
this.latest = {};
|
|
109
|
-
this.latestTxMadeAt = 0;
|
|
87
|
+
const { ops } = this;
|
|
110
88
|
|
|
111
|
-
const
|
|
89
|
+
const changedEntries = new Map<
|
|
90
|
+
keyof typeof ops,
|
|
91
|
+
NonNullable<(typeof ops)[keyof typeof ops]>
|
|
92
|
+
>();
|
|
112
93
|
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (madeAt > this.latestTxMadeAt) {
|
|
121
|
-
this.latestTxMadeAt = madeAt;
|
|
122
|
-
}
|
|
94
|
+
const nextValidTransactions = this.core.getValidTransactions({
|
|
95
|
+
ignorePrivateTransactions: this.ignorePrivateTransactions,
|
|
96
|
+
knownTransactions: this.knownTransactions,
|
|
97
|
+
});
|
|
123
98
|
|
|
99
|
+
for (const { txID, changes, madeAt } of nextValidTransactions) {
|
|
124
100
|
for (let changeIdx = 0; changeIdx < changes.length; changeIdx++) {
|
|
125
101
|
const change = changes[changeIdx] as MapOpPayload<
|
|
126
102
|
keyof Shape & string,
|
|
127
103
|
Shape[keyof Shape & string]
|
|
128
104
|
>;
|
|
129
|
-
const entry =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
change,
|
|
136
|
-
};
|
|
137
|
-
} else if (madeAt >= entry.madeAt) {
|
|
138
|
-
entry.txID = txID;
|
|
139
|
-
entry.madeAt = madeAt;
|
|
140
|
-
entry.changeIdx = changeIdx;
|
|
141
|
-
entry.change = change;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
revalidateTransactions() {
|
|
148
|
-
this.resetCachedValues();
|
|
149
|
-
this.processLatestTransactions();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
private getOps() {
|
|
153
|
-
if (this.cachedOps) {
|
|
154
|
-
return this.cachedOps;
|
|
155
|
-
}
|
|
105
|
+
const entry = {
|
|
106
|
+
txID,
|
|
107
|
+
madeAt,
|
|
108
|
+
changeIdx,
|
|
109
|
+
change,
|
|
110
|
+
};
|
|
156
111
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
112
|
+
if (madeAt > this.latestTxMadeAt) {
|
|
113
|
+
this.latestTxMadeAt = madeAt;
|
|
114
|
+
}
|
|
160
115
|
|
|
161
|
-
|
|
162
|
-
for (let changeIdx = 0; changeIdx < changes.length; changeIdx++) {
|
|
163
|
-
const change = changes[changeIdx] as MapOpPayload<
|
|
164
|
-
keyof Shape & string,
|
|
165
|
-
Shape[keyof Shape & string]
|
|
166
|
-
>;
|
|
167
|
-
let entries = ops[change.key];
|
|
116
|
+
const entries = ops[change.key];
|
|
168
117
|
if (!entries) {
|
|
169
|
-
entries = [];
|
|
118
|
+
const entries = [entry];
|
|
170
119
|
ops[change.key] = entries;
|
|
120
|
+
changedEntries.set(change.key, entries);
|
|
121
|
+
} else {
|
|
122
|
+
entries.push(entry);
|
|
123
|
+
changedEntries.set(change.key, entries);
|
|
171
124
|
}
|
|
172
|
-
|
|
173
|
-
txID,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
change,
|
|
177
|
-
});
|
|
125
|
+
this.knownTransactions[txID.sessionID] = Math.max(
|
|
126
|
+
this.knownTransactions[txID.sessionID] ?? 0,
|
|
127
|
+
txID.txIndex,
|
|
128
|
+
);
|
|
178
129
|
}
|
|
179
130
|
}
|
|
180
131
|
|
|
181
|
-
|
|
132
|
+
for (const entries of changedEntries.values()) {
|
|
133
|
+
entries.sort(this.core.compareTransactions);
|
|
134
|
+
}
|
|
182
135
|
|
|
183
|
-
|
|
136
|
+
for (const [key, entries] of changedEntries.entries()) {
|
|
137
|
+
this.latest[key] = entries[entries.length - 1];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
isTimeTravelEntity() {
|
|
142
|
+
return Boolean(this.atTimeFilter);
|
|
184
143
|
}
|
|
185
144
|
|
|
186
145
|
/** @category 6. Meta */
|
|
@@ -198,14 +157,11 @@ export class RawCoMapView<
|
|
|
198
157
|
if (time >= this.latestTxMadeAt) {
|
|
199
158
|
return this;
|
|
200
159
|
} else {
|
|
201
|
-
const clone =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
validSortedTransactions: this.validSortedTransactions,
|
|
207
|
-
});
|
|
208
|
-
Object.setPrototypeOf(clone, this);
|
|
160
|
+
const clone = Object.create(this) as RawCoMapView<Shape, Meta>;
|
|
161
|
+
|
|
162
|
+
clone.atTimeFilter = time;
|
|
163
|
+
clone.latest = {};
|
|
164
|
+
|
|
209
165
|
return clone as this;
|
|
210
166
|
}
|
|
211
167
|
}
|
|
@@ -218,12 +174,12 @@ export class RawCoMapView<
|
|
|
218
174
|
return undefined;
|
|
219
175
|
}
|
|
220
176
|
|
|
221
|
-
const atTimeFilter = this.
|
|
177
|
+
const atTimeFilter = this.atTimeFilter;
|
|
222
178
|
|
|
223
179
|
if (atTimeFilter) {
|
|
224
|
-
return this.
|
|
180
|
+
return this.ops[key]?.filter((op) => op.madeAt <= atTimeFilter);
|
|
225
181
|
} else {
|
|
226
|
-
return this.
|
|
182
|
+
return this.ops[key];
|
|
227
183
|
}
|
|
228
184
|
}
|
|
229
185
|
|
|
@@ -232,36 +188,64 @@ export class RawCoMapView<
|
|
|
232
188
|
*
|
|
233
189
|
* @category 1. Reading */
|
|
234
190
|
keys<K extends keyof Shape & string = keyof Shape & string>(): K[] {
|
|
235
|
-
return (Object.keys(this.
|
|
236
|
-
const
|
|
191
|
+
return (Object.keys(this.ops) as K[]).filter((key) => {
|
|
192
|
+
const entry = this.getRaw(key);
|
|
237
193
|
|
|
238
|
-
if (
|
|
194
|
+
if (entry === undefined) {
|
|
239
195
|
return false;
|
|
240
196
|
}
|
|
241
197
|
|
|
242
|
-
if (
|
|
198
|
+
if (entry.change.op === "del") {
|
|
243
199
|
return false;
|
|
244
|
-
} else {
|
|
245
|
-
return true;
|
|
246
200
|
}
|
|
201
|
+
|
|
202
|
+
return true;
|
|
247
203
|
});
|
|
248
204
|
}
|
|
249
205
|
|
|
206
|
+
getRaw<K extends keyof Shape & string>(key: K) {
|
|
207
|
+
let latestChange = this.latest[key];
|
|
208
|
+
|
|
209
|
+
if (latestChange === undefined) {
|
|
210
|
+
const entries = this.ops[key];
|
|
211
|
+
|
|
212
|
+
// Time travel values are lazily computed
|
|
213
|
+
if (entries && !(key in this.latest)) {
|
|
214
|
+
const atTimeFilter = this.atTimeFilter;
|
|
215
|
+
|
|
216
|
+
if (!atTimeFilter) {
|
|
217
|
+
latestChange = entries[entries.length - 1];
|
|
218
|
+
} else {
|
|
219
|
+
latestChange = entries.findLast((op) => op.madeAt <= atTimeFilter);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.latest[key] = latestChange;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (latestChange === undefined) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return latestChange;
|
|
231
|
+
}
|
|
232
|
+
|
|
250
233
|
/**
|
|
251
234
|
* Returns the current value for the given key.
|
|
252
235
|
*
|
|
253
236
|
* @category 1. Reading
|
|
254
237
|
**/
|
|
255
238
|
get<K extends keyof Shape & string>(key: K): Shape[K] | undefined {
|
|
256
|
-
const
|
|
257
|
-
|
|
239
|
+
const entry = this.getRaw(key);
|
|
240
|
+
|
|
241
|
+
if (entry === undefined) {
|
|
258
242
|
return undefined;
|
|
259
243
|
}
|
|
260
244
|
|
|
261
|
-
if (
|
|
245
|
+
if (entry.change.op === "del") {
|
|
262
246
|
return undefined;
|
|
263
247
|
} else {
|
|
264
|
-
return
|
|
248
|
+
return entry.change.value as Shape[K];
|
|
265
249
|
}
|
|
266
250
|
}
|
|
267
251
|
|
|
@@ -273,7 +257,7 @@ export class RawCoMapView<
|
|
|
273
257
|
[K in keyof Shape & string]: Shape[K];
|
|
274
258
|
}> = {};
|
|
275
259
|
|
|
276
|
-
for (const key of Object.keys(this.
|
|
260
|
+
for (const key of Object.keys(this.ops) as (keyof Shape & string)[]) {
|
|
277
261
|
const value = this.get(key);
|
|
278
262
|
if (value !== undefined) {
|
|
279
263
|
object[key] = value;
|
|
@@ -294,9 +278,9 @@ export class RawCoMapView<
|
|
|
294
278
|
|
|
295
279
|
/** @category 5. Edit history */
|
|
296
280
|
nthEditAt<K extends keyof Shape & string>(key: K, n: number) {
|
|
297
|
-
const ops = this.
|
|
281
|
+
const ops = this.ops[key];
|
|
298
282
|
|
|
299
|
-
const atTimeFilter = this.
|
|
283
|
+
const atTimeFilter = this.atTimeFilter;
|
|
300
284
|
const entry = ops?.[n];
|
|
301
285
|
|
|
302
286
|
if (!entry) {
|
|
@@ -321,24 +305,31 @@ export class RawCoMapView<
|
|
|
321
305
|
value?: Shape[K];
|
|
322
306
|
}
|
|
323
307
|
| undefined {
|
|
324
|
-
const
|
|
325
|
-
const lastEntry = ops?.[ops.length - 1];
|
|
308
|
+
const entry = this.getRaw(key);
|
|
326
309
|
|
|
327
|
-
if (!
|
|
310
|
+
if (!entry) {
|
|
328
311
|
return undefined;
|
|
329
312
|
}
|
|
330
313
|
|
|
331
|
-
return operationToEditEntry(
|
|
314
|
+
return operationToEditEntry(entry);
|
|
332
315
|
}
|
|
333
316
|
|
|
334
317
|
/** @category 5. Edit history */
|
|
335
318
|
*editsAt<K extends keyof Shape & string>(key: K) {
|
|
336
|
-
const
|
|
337
|
-
|
|
319
|
+
const entries = this.ops[key];
|
|
320
|
+
|
|
321
|
+
if (!entries) {
|
|
338
322
|
return;
|
|
339
323
|
}
|
|
340
324
|
|
|
341
|
-
|
|
325
|
+
const atTimeFilter = this.atTimeFilter;
|
|
326
|
+
|
|
327
|
+
for (const entry of entries) {
|
|
328
|
+
// Entries are sorted by madeAt
|
|
329
|
+
if (atTimeFilter && entry.madeAt > atTimeFilter) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
342
333
|
yield operationToEditEntry(entry);
|
|
343
334
|
}
|
|
344
335
|
}
|
|
@@ -374,6 +365,10 @@ export class RawCoMap<
|
|
|
374
365
|
value: Shape[K],
|
|
375
366
|
privacy: "private" | "trusting" = "private",
|
|
376
367
|
): void {
|
|
368
|
+
if (this.isTimeTravelEntity()) {
|
|
369
|
+
throw new Error("Cannot set value on a time travel entity");
|
|
370
|
+
}
|
|
371
|
+
|
|
377
372
|
this.core.makeTransaction(
|
|
378
373
|
[
|
|
379
374
|
{
|
|
@@ -385,7 +380,7 @@ export class RawCoMap<
|
|
|
385
380
|
privacy,
|
|
386
381
|
);
|
|
387
382
|
|
|
388
|
-
this.
|
|
383
|
+
this.processNewTransactions();
|
|
389
384
|
}
|
|
390
385
|
|
|
391
386
|
/** Delete the given key (setting it to undefined).
|
|
@@ -400,6 +395,10 @@ export class RawCoMap<
|
|
|
400
395
|
key: keyof Shape & string,
|
|
401
396
|
privacy: "private" | "trusting" = "private",
|
|
402
397
|
) {
|
|
398
|
+
if (this.isTimeTravelEntity()) {
|
|
399
|
+
throw new Error("Cannot delete value on a time travel entity");
|
|
400
|
+
}
|
|
401
|
+
|
|
403
402
|
this.core.makeTransaction(
|
|
404
403
|
[
|
|
405
404
|
{
|
|
@@ -410,7 +409,7 @@ export class RawCoMap<
|
|
|
410
409
|
privacy,
|
|
411
410
|
);
|
|
412
411
|
|
|
413
|
-
this.
|
|
412
|
+
this.processNewTransactions();
|
|
414
413
|
}
|
|
415
414
|
}
|
|
416
415
|
|
package/src/coValues/coStream.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { CoID, RawCoValue } from "../coValue.js";
|
|
|
3
3
|
import { CoValueCore } from "../coValueCore.js";
|
|
4
4
|
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
5
5
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
6
|
+
import { CoValueKnownState } from "../sync.js";
|
|
6
7
|
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
|
|
7
8
|
import { isAccountID } from "../typeUtils/isAccountID.js";
|
|
8
9
|
import { isCoValue } from "../typeUtils/isCoValue.js";
|
|
@@ -52,13 +53,16 @@ export class RawCoStreamView<
|
|
|
52
53
|
items: {
|
|
53
54
|
[key: SessionID]: CoStreamItem<Item>[];
|
|
54
55
|
};
|
|
56
|
+
/** @internal */
|
|
57
|
+
knownTransactions: CoValueKnownState["sessions"];
|
|
55
58
|
readonly _item!: Item;
|
|
56
59
|
|
|
57
60
|
constructor(core: CoValueCore) {
|
|
58
61
|
this.id = core.id as CoID<this>;
|
|
59
62
|
this.core = core;
|
|
60
63
|
this.items = {};
|
|
61
|
-
this.
|
|
64
|
+
this.knownTransactions = {};
|
|
65
|
+
this.processNewTransactions();
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
get headerMeta(): Meta {
|
|
@@ -75,14 +79,13 @@ export class RawCoStreamView<
|
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
/** @internal */
|
|
78
|
-
protected
|
|
79
|
-
|
|
82
|
+
protected processNewTransactions() {
|
|
83
|
+
const changeEntries = new Set<CoStreamItem<Item>[]>();
|
|
80
84
|
|
|
81
|
-
for (const {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} of this.core.getValidSortedTransactions()) {
|
|
85
|
+
for (const { txID, madeAt, changes } of this.core.getValidTransactions({
|
|
86
|
+
ignorePrivateTransactions: false,
|
|
87
|
+
knownTransactions: this.knownTransactions,
|
|
88
|
+
})) {
|
|
86
89
|
for (const changeUntyped of changes) {
|
|
87
90
|
const change = changeUntyped as Item;
|
|
88
91
|
let entries = this.items[txID.sessionID];
|
|
@@ -91,7 +94,21 @@ export class RawCoStreamView<
|
|
|
91
94
|
this.items[txID.sessionID] = entries;
|
|
92
95
|
}
|
|
93
96
|
entries.push({ value: change, madeAt, tx: txID });
|
|
97
|
+
changeEntries.add(entries);
|
|
94
98
|
}
|
|
99
|
+
this.knownTransactions[txID.sessionID] = Math.max(
|
|
100
|
+
this.knownTransactions[txID.sessionID] ?? 0,
|
|
101
|
+
txID.txIndex,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const entries of changeEntries) {
|
|
106
|
+
entries.sort(
|
|
107
|
+
(a, b) =>
|
|
108
|
+
a.madeAt - b.madeAt ||
|
|
109
|
+
(a.tx.sessionID < b.tx.sessionID ? -1 : 1) ||
|
|
110
|
+
a.tx.txIndex - b.tx.txIndex,
|
|
111
|
+
);
|
|
95
112
|
}
|
|
96
113
|
}
|
|
97
114
|
|
|
@@ -255,7 +272,7 @@ export class RawCoStream<
|
|
|
255
272
|
{
|
|
256
273
|
push(item: Item, privacy: "private" | "trusting" = "private"): void {
|
|
257
274
|
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
|
|
258
|
-
this.
|
|
275
|
+
this.processNewTransactions();
|
|
259
276
|
}
|
|
260
277
|
}
|
|
261
278
|
|
|
@@ -343,7 +360,7 @@ export class RawBinaryCoStream<
|
|
|
343
360
|
): void {
|
|
344
361
|
this.core.makeTransaction([item], privacy);
|
|
345
362
|
if (updateView) {
|
|
346
|
-
this.
|
|
363
|
+
this.processNewTransactions();
|
|
347
364
|
}
|
|
348
365
|
}
|
|
349
366
|
|