jazz-tools 0.19.13 → 0.19.15
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 +51 -51
- package/CHANGELOG.md +23 -0
- package/dist/{chunk-GAPMDNJY.js → chunk-R3KIZG4P.js} +47 -27
- package/dist/chunk-R3KIZG4P.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/react-native/index.js +18 -0
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native-core/ReactNativeSessionProvider.d.ts.map +1 -1
- package/dist/react-native-core/index.js +18 -0
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/CoValueBase.d.ts +13 -0
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +33 -35
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/react-native-core/ReactNativeSessionProvider.ts +29 -3
- package/src/react-native-core/tests/ReactNativeSessionProvider.test.ts +175 -3
- package/src/tools/coValues/CoValueBase.ts +24 -0
- package/src/tools/coValues/coMap.ts +1 -1
- package/src/tools/implementation/createContext.ts +2 -2
- package/src/tools/subscribe/SubscriptionScope.ts +43 -34
- package/src/tools/tests/account.test.ts +19 -0
- package/src/tools/tests/coMap.record.test.ts +43 -0
- package/src/tools/tests/coMap.test.ts +67 -1
- package/dist/chunk-GAPMDNJY.js.map +0 -1
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
} from "./errorReporting.js";
|
|
30
30
|
import {
|
|
31
31
|
createCoValue,
|
|
32
|
-
isEqualRefsToResolve,
|
|
33
32
|
myRoleForRawValue,
|
|
34
33
|
PromiseWithStatus,
|
|
35
34
|
rejectedPromise,
|
|
@@ -49,25 +48,25 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
49
48
|
/**
|
|
50
49
|
* Autoloaded child ids that are unloaded
|
|
51
50
|
*/
|
|
52
|
-
pendingAutoloadedChildren: Set<string> = new Set();
|
|
51
|
+
private pendingAutoloadedChildren: Set<string> = new Set();
|
|
53
52
|
value: SubscriptionValue<D, any> | SubscriptionValueLoading;
|
|
54
|
-
childErrors: Map<string, JazzError> = new Map();
|
|
55
|
-
validationErrors: Map<string, JazzError> = new Map();
|
|
53
|
+
private childErrors: Map<string, JazzError> = new Map();
|
|
54
|
+
private validationErrors: Map<string, JazzError> = new Map();
|
|
56
55
|
errorFromChildren: JazzError | undefined;
|
|
57
|
-
subscription: CoValueCoreSubscription;
|
|
58
|
-
dirty = false;
|
|
59
|
-
resolve: RefsToResolve<any>;
|
|
60
|
-
idsSubscribed = new Set<string>();
|
|
61
|
-
autoloaded = new Set<string>();
|
|
62
|
-
autoloadedKeys = new Set<string>();
|
|
63
|
-
skipInvalidKeys = new Set<string>();
|
|
64
|
-
totalValidTransactions = 0;
|
|
65
|
-
version = 0;
|
|
66
|
-
migrated = false;
|
|
67
|
-
migrating = false;
|
|
56
|
+
private subscription: CoValueCoreSubscription;
|
|
57
|
+
private dirty = false;
|
|
58
|
+
private resolve: RefsToResolve<any>;
|
|
59
|
+
private idsSubscribed = new Set<string>();
|
|
60
|
+
private autoloaded = new Set<string>();
|
|
61
|
+
private autoloadedKeys = new Set<string>();
|
|
62
|
+
private skipInvalidKeys = new Set<string>();
|
|
63
|
+
private totalValidTransactions = 0;
|
|
64
|
+
private version = 0;
|
|
65
|
+
private migrated = false;
|
|
66
|
+
private migrating = false;
|
|
68
67
|
closed = false;
|
|
69
68
|
|
|
70
|
-
silenceUpdates = false;
|
|
69
|
+
private silenceUpdates = false;
|
|
71
70
|
|
|
72
71
|
/**
|
|
73
72
|
* Stack trace captured at subscription creation time.
|
|
@@ -145,7 +144,9 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
145
144
|
this.dirty = true;
|
|
146
145
|
}
|
|
147
146
|
|
|
148
|
-
handleUpdate(
|
|
147
|
+
private handleUpdate(
|
|
148
|
+
update: RawCoValue | typeof CoValueLoadingState.UNAVAILABLE,
|
|
149
|
+
) {
|
|
149
150
|
if (update === CoValueLoadingState.UNAVAILABLE) {
|
|
150
151
|
if (this.value.type === CoValueLoadingState.LOADING) {
|
|
151
152
|
const error = new JazzError(this.id, CoValueLoadingState.UNAVAILABLE, [
|
|
@@ -213,7 +214,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
213
214
|
this.triggerUpdate();
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
computeChildErrors() {
|
|
217
|
+
private computeChildErrors() {
|
|
217
218
|
let issues: JazzErrorIssue[] = [];
|
|
218
219
|
let errorType: JazzError["type"] = CoValueLoadingState.UNAVAILABLE;
|
|
219
220
|
|
|
@@ -259,11 +260,11 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
259
260
|
return undefined;
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
handleChildUpdate
|
|
263
|
+
handleChildUpdate(
|
|
263
264
|
id: string,
|
|
264
265
|
value: SubscriptionValue<any, any> | SubscriptionValueLoading,
|
|
265
266
|
key?: string,
|
|
266
|
-
)
|
|
267
|
+
) {
|
|
267
268
|
if (value.type === CoValueLoadingState.LOADING) {
|
|
268
269
|
return;
|
|
269
270
|
}
|
|
@@ -296,9 +297,9 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
296
297
|
}
|
|
297
298
|
|
|
298
299
|
this.triggerUpdate();
|
|
299
|
-
}
|
|
300
|
+
}
|
|
300
301
|
|
|
301
|
-
shouldSendUpdates() {
|
|
302
|
+
private shouldSendUpdates() {
|
|
302
303
|
if (this.value.type === CoValueLoadingState.LOADING) return false;
|
|
303
304
|
|
|
304
305
|
// If the value is in error, we send the update regardless of the children statuses
|
|
@@ -309,9 +310,9 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
309
310
|
|
|
310
311
|
unloadedValue: NotLoaded<D> | undefined;
|
|
311
312
|
|
|
312
|
-
lastPromise: PromiseWithStatus<D> | undefined;
|
|
313
|
+
private lastPromise: PromiseWithStatus<D> | undefined;
|
|
313
314
|
|
|
314
|
-
getPromise() {
|
|
315
|
+
private getPromise() {
|
|
315
316
|
const currentValue = this.getCurrentValue();
|
|
316
317
|
|
|
317
318
|
if (currentValue.$isLoaded) {
|
|
@@ -403,7 +404,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
403
404
|
return unloadedValue;
|
|
404
405
|
}
|
|
405
406
|
|
|
406
|
-
lastErrorLogged: JazzError | undefined;
|
|
407
|
+
private lastErrorLogged: JazzError | undefined;
|
|
407
408
|
|
|
408
409
|
getCurrentValue(): MaybeLoaded<D> {
|
|
409
410
|
const rawValue = this.getCurrentRawValue();
|
|
@@ -420,7 +421,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
420
421
|
return rawValue;
|
|
421
422
|
}
|
|
422
423
|
|
|
423
|
-
getCurrentRawValue(): D | NotLoadedCoValueState {
|
|
424
|
+
private getCurrentRawValue(): D | NotLoadedCoValueState {
|
|
424
425
|
if (
|
|
425
426
|
this.value.type === CoValueLoadingState.UNAUTHORIZED ||
|
|
426
427
|
this.value.type === CoValueLoadingState.UNAVAILABLE
|
|
@@ -443,7 +444,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
443
444
|
return CoValueLoadingState.LOADING;
|
|
444
445
|
}
|
|
445
446
|
|
|
446
|
-
getCreationStackLines() {
|
|
447
|
+
private getCreationStackLines() {
|
|
447
448
|
const stack = this.callerStack?.stack;
|
|
448
449
|
|
|
449
450
|
if (!stack) {
|
|
@@ -474,7 +475,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
474
475
|
return result;
|
|
475
476
|
}
|
|
476
477
|
|
|
477
|
-
getError() {
|
|
478
|
+
private getError() {
|
|
478
479
|
if (
|
|
479
480
|
this.value.type === CoValueLoadingState.UNAUTHORIZED ||
|
|
480
481
|
this.value.type === CoValueLoadingState.UNAVAILABLE
|
|
@@ -487,7 +488,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
487
488
|
}
|
|
488
489
|
}
|
|
489
490
|
|
|
490
|
-
logError() {
|
|
491
|
+
private logError() {
|
|
491
492
|
const error = this.getError();
|
|
492
493
|
|
|
493
494
|
if (!error || this.lastErrorLogged === error) {
|
|
@@ -510,7 +511,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
510
511
|
}
|
|
511
512
|
}
|
|
512
513
|
|
|
513
|
-
triggerUpdate() {
|
|
514
|
+
private triggerUpdate() {
|
|
514
515
|
if (!this.shouldSendUpdates()) return;
|
|
515
516
|
if (!this.dirty) return;
|
|
516
517
|
if (this.subscribers.size === 0) return;
|
|
@@ -700,7 +701,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
700
701
|
this.silenceUpdates = false;
|
|
701
702
|
}
|
|
702
703
|
|
|
703
|
-
loadChildren() {
|
|
704
|
+
private loadChildren() {
|
|
704
705
|
const { resolve } = this;
|
|
705
706
|
|
|
706
707
|
if (this.value.type !== CoValueLoadingState.LOADED) {
|
|
@@ -816,7 +817,11 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
816
817
|
return hasChanged;
|
|
817
818
|
}
|
|
818
819
|
|
|
819
|
-
loadCoMapKey(
|
|
820
|
+
private loadCoMapKey(
|
|
821
|
+
map: CoMap,
|
|
822
|
+
key: string,
|
|
823
|
+
depth: Record<string, any> | true,
|
|
824
|
+
) {
|
|
820
825
|
if (key === "$onError") {
|
|
821
826
|
return undefined;
|
|
822
827
|
}
|
|
@@ -858,7 +863,11 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
858
863
|
return undefined;
|
|
859
864
|
}
|
|
860
865
|
|
|
861
|
-
loadCoListKey(
|
|
866
|
+
private loadCoListKey(
|
|
867
|
+
list: CoList,
|
|
868
|
+
key: string,
|
|
869
|
+
depth: Record<string, any> | true,
|
|
870
|
+
) {
|
|
862
871
|
const descriptor = list.$jazz.getItemsDescriptor();
|
|
863
872
|
|
|
864
873
|
if (!descriptor || !isRefEncoded(descriptor)) {
|
|
@@ -896,7 +905,7 @@ export class SubscriptionScope<D extends CoValue> {
|
|
|
896
905
|
return undefined;
|
|
897
906
|
}
|
|
898
907
|
|
|
899
|
-
loadChildNode(
|
|
908
|
+
private loadChildNode(
|
|
900
909
|
id: string,
|
|
901
910
|
query: RefsToResolve<any>,
|
|
902
911
|
descriptor: RefEncoded<any>,
|
|
@@ -506,4 +506,23 @@ describe("createAs", () => {
|
|
|
506
506
|
// Verify execution order
|
|
507
507
|
expect(executionOrder).toEqual(["migration", "onCreate"]);
|
|
508
508
|
});
|
|
509
|
+
test("createdBy returns undefined", async () => {
|
|
510
|
+
const CustomAccount = co.account({
|
|
511
|
+
profile: co.profile({
|
|
512
|
+
name: z.string(),
|
|
513
|
+
}),
|
|
514
|
+
root: co.map({}),
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
const worker = await createJazzTestAccount({
|
|
518
|
+
isCurrentActiveAccount: true,
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const createdAccount = await CustomAccount.createAs(worker, {
|
|
522
|
+
creationProps: { name: "Test Account" },
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
assertLoaded(createdAccount.account);
|
|
526
|
+
expect(createdAccount.account.$jazz.createdBy).toBe(undefined);
|
|
527
|
+
});
|
|
509
528
|
});
|
|
@@ -194,6 +194,49 @@ describe("CoMap.Record", async () => {
|
|
|
194
194
|
$jazz: expect.objectContaining({ id: me.$jazz.id }),
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
test("getEdits() keys should return deleted keys", () => {
|
|
199
|
+
const me = Account.getMe();
|
|
200
|
+
|
|
201
|
+
const Person = co.record(z.string(), z.string());
|
|
202
|
+
const person = Person.create({ name: "John" });
|
|
203
|
+
person.$jazz.set("name", "Jane");
|
|
204
|
+
person.$jazz.delete("name");
|
|
205
|
+
|
|
206
|
+
expect(Object.keys(person.$jazz.getEdits())).toEqual(["name"]);
|
|
207
|
+
|
|
208
|
+
const edits = person.$jazz.getEdits().name?.all;
|
|
209
|
+
|
|
210
|
+
expect(edits).toEqual([
|
|
211
|
+
expect.objectContaining({
|
|
212
|
+
value: "John",
|
|
213
|
+
key: "name",
|
|
214
|
+
ref: undefined,
|
|
215
|
+
madeAt: expect.any(Date),
|
|
216
|
+
}),
|
|
217
|
+
expect.objectContaining({
|
|
218
|
+
value: "Jane",
|
|
219
|
+
key: "name",
|
|
220
|
+
ref: undefined,
|
|
221
|
+
madeAt: expect.any(Date),
|
|
222
|
+
}),
|
|
223
|
+
expect.objectContaining({
|
|
224
|
+
value: undefined,
|
|
225
|
+
key: "name",
|
|
226
|
+
ref: undefined,
|
|
227
|
+
madeAt: expect.any(Date),
|
|
228
|
+
}),
|
|
229
|
+
]);
|
|
230
|
+
|
|
231
|
+
expect(edits?.[0]?.by).toMatchObject({
|
|
232
|
+
[TypeSym]: "Account",
|
|
233
|
+
$jazz: expect.objectContaining({ id: me.$jazz.id }),
|
|
234
|
+
});
|
|
235
|
+
expect(edits?.[1]?.by).toMatchObject({
|
|
236
|
+
[TypeSym]: "Account",
|
|
237
|
+
$jazz: expect.objectContaining({ id: me.$jazz.id }),
|
|
238
|
+
});
|
|
239
|
+
});
|
|
197
240
|
});
|
|
198
241
|
|
|
199
242
|
describe("Record resolution", async () => {
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
disableJazzTestSync,
|
|
27
27
|
getPeerConnectedToTestSyncServer,
|
|
28
28
|
runWithoutActiveAccount,
|
|
29
|
+
setActiveAccount,
|
|
29
30
|
setupJazzTestSync,
|
|
30
31
|
} from "../testing.js";
|
|
31
32
|
import { assertLoaded, setupTwoNodes, waitFor } from "./utils.js";
|
|
@@ -2316,28 +2317,93 @@ describe("CoMap migration", () => {
|
|
|
2316
2317
|
});
|
|
2317
2318
|
});
|
|
2318
2319
|
|
|
2319
|
-
describe("createdAt
|
|
2320
|
+
describe("createdAt, lastUpdatedAt, createdBy", () => {
|
|
2320
2321
|
test("empty map created time", () => {
|
|
2321
2322
|
const emptyMap = co.map({}).create({});
|
|
2322
2323
|
|
|
2323
2324
|
expect(emptyMap.$jazz.lastUpdatedAt).toEqual(emptyMap.$jazz.createdAt);
|
|
2324
2325
|
});
|
|
2325
2326
|
|
|
2327
|
+
test("empty map created by", () => {
|
|
2328
|
+
const emptyMap = co.map({}).create({});
|
|
2329
|
+
const me = Account.getMe();
|
|
2330
|
+
expect(emptyMap.$jazz.createdBy).toEqual(me.$jazz.id);
|
|
2331
|
+
});
|
|
2332
|
+
|
|
2326
2333
|
test("created time and last updated time", async () => {
|
|
2327
2334
|
const Person = co.map({
|
|
2328
2335
|
name: z.string(),
|
|
2329
2336
|
});
|
|
2337
|
+
const me = Account.getMe();
|
|
2330
2338
|
|
|
2331
2339
|
const person = Person.create({ name: "John" });
|
|
2332
2340
|
|
|
2333
2341
|
const createdAt = person.$jazz.createdAt;
|
|
2334
2342
|
expect(person.$jazz.lastUpdatedAt).toEqual(createdAt);
|
|
2335
2343
|
|
|
2344
|
+
const createdBy = person.$jazz.createdBy;
|
|
2345
|
+
expect(createdBy).toEqual(me.$jazz.id);
|
|
2346
|
+
|
|
2336
2347
|
await new Promise((r) => setTimeout(r, 10));
|
|
2337
2348
|
person.$jazz.set("name", "Jane");
|
|
2338
2349
|
|
|
2339
2350
|
expect(person.$jazz.createdAt).toEqual(createdAt);
|
|
2340
2351
|
expect(person.$jazz.lastUpdatedAt).not.toEqual(createdAt);
|
|
2352
|
+
|
|
2353
|
+
// Double check after update.
|
|
2354
|
+
expect(createdBy).toEqual(me.$jazz.id);
|
|
2355
|
+
});
|
|
2356
|
+
|
|
2357
|
+
test("createdBy does not change when updated", async () => {
|
|
2358
|
+
const Person = co.map({
|
|
2359
|
+
name: z.string(),
|
|
2360
|
+
});
|
|
2361
|
+
const me = Account.getMe();
|
|
2362
|
+
|
|
2363
|
+
const person = Person.create({ name: "John" });
|
|
2364
|
+
|
|
2365
|
+
const createdBy = person.$jazz.createdBy;
|
|
2366
|
+
expect(createdBy).toEqual(me.$jazz.id);
|
|
2367
|
+
|
|
2368
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
2369
|
+
person.$jazz.set("name", "Jane");
|
|
2370
|
+
|
|
2371
|
+
// Double check after update.
|
|
2372
|
+
expect(createdBy).toEqual(me.$jazz.id);
|
|
2373
|
+
});
|
|
2374
|
+
|
|
2375
|
+
test("createdBy is after key rotation", async () => {
|
|
2376
|
+
const Person = co.map({
|
|
2377
|
+
name: z.string(),
|
|
2378
|
+
});
|
|
2379
|
+
const me = Account.getMe();
|
|
2380
|
+
|
|
2381
|
+
// Create person
|
|
2382
|
+
const person = Person.create({ name: "John" });
|
|
2383
|
+
|
|
2384
|
+
// True created by
|
|
2385
|
+
const createdBy = person.$jazz.createdBy;
|
|
2386
|
+
|
|
2387
|
+
// Create a user, grant access, then kick to trigger key rotation.
|
|
2388
|
+
const newUser = await createJazzTestAccount();
|
|
2389
|
+
|
|
2390
|
+
person.$jazz.owner.addMember(newUser, "reader");
|
|
2391
|
+
|
|
2392
|
+
// This should trigger read key rotation
|
|
2393
|
+
person.$jazz.owner.removeMember(newUser);
|
|
2394
|
+
|
|
2395
|
+
// Now create a new user and grant access
|
|
2396
|
+
const newUser2 = await createJazzTestAccount();
|
|
2397
|
+
person.$jazz.owner.addMember(newUser2, "reader");
|
|
2398
|
+
|
|
2399
|
+
// Load the CoValue as the new user:
|
|
2400
|
+
setActiveAccount(newUser2);
|
|
2401
|
+
|
|
2402
|
+
const personLoadedAsUser2 = await Person.load(person.$jazz.id);
|
|
2403
|
+
assertLoaded(personLoadedAsUser2);
|
|
2404
|
+
const createdByPerUser2 = personLoadedAsUser2.$jazz.createdBy;
|
|
2405
|
+
// Double check after update.
|
|
2406
|
+
expect(createdBy).toEqual(createdByPerUser2);
|
|
2341
2407
|
});
|
|
2342
2408
|
});
|
|
2343
2409
|
|