jazz-tools 0.19.10 → 0.19.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.
Files changed (112) hide show
  1. package/.turbo/turbo-build.log +58 -54
  2. package/CHANGELOG.md +23 -0
  3. package/dist/{chunk-FFEEPZEG.js → chunk-AGF4HEDH.js} +61 -28
  4. package/dist/chunk-AGF4HEDH.js.map +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/inspector/account-switcher.d.ts +4 -0
  7. package/dist/inspector/account-switcher.d.ts.map +1 -0
  8. package/dist/inspector/chunk-YQNK5Y7B.js +4108 -0
  9. package/dist/inspector/chunk-YQNK5Y7B.js.map +1 -0
  10. package/dist/inspector/contexts/node.d.ts +19 -0
  11. package/dist/inspector/contexts/node.d.ts.map +1 -0
  12. package/dist/inspector/{custom-element-P76EIWEV.js → custom-element-KYV64IOC.js} +1057 -918
  13. package/dist/inspector/custom-element-KYV64IOC.js.map +1 -0
  14. package/dist/inspector/{viewer/new-app.d.ts → in-app.d.ts} +3 -3
  15. package/dist/inspector/in-app.d.ts.map +1 -0
  16. package/dist/inspector/index.d.ts +0 -11
  17. package/dist/inspector/index.d.ts.map +1 -1
  18. package/dist/inspector/index.js +56 -3910
  19. package/dist/inspector/index.js.map +1 -1
  20. package/dist/inspector/pages/home.d.ts +2 -0
  21. package/dist/inspector/pages/home.d.ts.map +1 -0
  22. package/dist/inspector/register-custom-element.js +1 -1
  23. package/dist/inspector/router/context.d.ts +12 -0
  24. package/dist/inspector/router/context.d.ts.map +1 -0
  25. package/dist/inspector/router/hash-router.d.ts +7 -0
  26. package/dist/inspector/router/hash-router.d.ts.map +1 -0
  27. package/dist/inspector/router/in-memory-router.d.ts +7 -0
  28. package/dist/inspector/router/in-memory-router.d.ts.map +1 -0
  29. package/dist/inspector/router/index.d.ts +5 -0
  30. package/dist/inspector/router/index.d.ts.map +1 -0
  31. package/dist/inspector/standalone.d.ts +6 -0
  32. package/dist/inspector/standalone.d.ts.map +1 -0
  33. package/dist/inspector/standalone.js +420 -0
  34. package/dist/inspector/standalone.js.map +1 -0
  35. package/dist/inspector/tests/router/hash-router.test.d.ts +2 -0
  36. package/dist/inspector/tests/router/hash-router.test.d.ts.map +1 -0
  37. package/dist/inspector/tests/router/in-memory-router.test.d.ts +2 -0
  38. package/dist/inspector/tests/router/in-memory-router.test.d.ts.map +1 -0
  39. package/dist/inspector/tests/utils/transactions-changes.test.d.ts +2 -0
  40. package/dist/inspector/tests/utils/transactions-changes.test.d.ts.map +1 -0
  41. package/dist/inspector/ui/modal.d.ts +1 -0
  42. package/dist/inspector/ui/modal.d.ts.map +1 -1
  43. package/dist/inspector/utils/transactions-changes.d.ts +13 -13
  44. package/dist/inspector/utils/transactions-changes.d.ts.map +1 -1
  45. package/dist/inspector/viewer/breadcrumbs.d.ts +1 -7
  46. package/dist/inspector/viewer/breadcrumbs.d.ts.map +1 -1
  47. package/dist/inspector/viewer/header.d.ts +7 -0
  48. package/dist/inspector/viewer/header.d.ts.map +1 -0
  49. package/dist/inspector/viewer/page-stack.d.ts +4 -13
  50. package/dist/inspector/viewer/page-stack.d.ts.map +1 -1
  51. package/dist/inspector/viewer/page.d.ts.map +1 -1
  52. package/dist/react/index.js +4 -1
  53. package/dist/react/index.js.map +1 -1
  54. package/dist/react/provider.d.ts.map +1 -1
  55. package/dist/react-core/index.js +2 -2
  56. package/dist/react-core/index.js.map +1 -1
  57. package/dist/react-native/index.js +4 -1
  58. package/dist/react-native/index.js.map +1 -1
  59. package/dist/react-native-core/index.js +4 -1
  60. package/dist/react-native-core/index.js.map +1 -1
  61. package/dist/react-native-core/provider.d.ts.map +1 -1
  62. package/dist/testing.js +1 -1
  63. package/dist/tools/coValues/account.d.ts +7 -1
  64. package/dist/tools/coValues/account.d.ts.map +1 -1
  65. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  66. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +8 -1
  67. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  68. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  69. package/dist/tools/subscribe/SubscriptionScope.d.ts +3 -6
  70. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  71. package/dist/tools/testing.d.ts.map +1 -1
  72. package/package.json +9 -4
  73. package/src/inspector/account-switcher.tsx +440 -0
  74. package/src/inspector/contexts/node.tsx +129 -0
  75. package/src/inspector/custom-element.tsx +2 -2
  76. package/src/inspector/in-app.tsx +61 -0
  77. package/src/inspector/index.tsx +2 -22
  78. package/src/inspector/pages/home.tsx +77 -0
  79. package/src/inspector/router/context.ts +21 -0
  80. package/src/inspector/router/hash-router.tsx +128 -0
  81. package/src/inspector/{viewer/use-page-path.ts → router/in-memory-router.tsx} +31 -29
  82. package/src/inspector/router/index.ts +4 -0
  83. package/src/inspector/standalone.tsx +60 -0
  84. package/src/inspector/tests/router/hash-router.test.tsx +847 -0
  85. package/src/inspector/tests/router/in-memory-router.test.tsx +724 -0
  86. package/src/inspector/tests/utils/transactions-changes.test.ts +102 -0
  87. package/src/inspector/ui/icons/add-icon.tsx +3 -3
  88. package/src/inspector/ui/modal.tsx +5 -2
  89. package/src/inspector/utils/history.ts +6 -6
  90. package/src/inspector/utils/transactions-changes.ts +37 -3
  91. package/src/inspector/viewer/breadcrumbs.tsx +5 -11
  92. package/src/inspector/viewer/header.tsx +67 -0
  93. package/src/inspector/viewer/history-view.tsx +13 -13
  94. package/src/inspector/viewer/page-stack.tsx +18 -26
  95. package/src/inspector/viewer/page.tsx +0 -1
  96. package/src/react/provider.tsx +6 -1
  97. package/src/react-core/hooks.ts +2 -2
  98. package/src/react-core/tests/useSuspenseCoState.test.tsx +47 -0
  99. package/src/react-native-core/provider.tsx +6 -1
  100. package/src/tools/coValues/account.ts +13 -2
  101. package/src/tools/implementation/ContextManager.ts +10 -0
  102. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +8 -1
  103. package/src/tools/subscribe/SubscriptionScope.ts +61 -39
  104. package/src/tools/tests/account.test.ts +11 -4
  105. package/src/tools/tests/schema.resolved.test.ts +3 -3
  106. package/tsup.config.ts +1 -0
  107. package/dist/chunk-FFEEPZEG.js.map +0 -1
  108. package/dist/inspector/custom-element-P76EIWEV.js.map +0 -1
  109. package/dist/inspector/viewer/new-app.d.ts.map +0 -1
  110. package/dist/inspector/viewer/use-page-path.d.ts +0 -10
  111. package/dist/inspector/viewer/use-page-path.d.ts.map +0 -1
  112. package/src/inspector/viewer/new-app.tsx +0 -156
@@ -55,6 +55,9 @@ export function JazzProviderCore<
55
55
  );
56
56
  const logoutReplacementActiveRef = useRef(false);
57
57
  logoutReplacementActiveRef.current = Boolean(logOutReplacement);
58
+ const onAnonymousAccountDiscardedEnabled = Boolean(
59
+ onAnonymousAccountDiscarded,
60
+ );
58
61
 
59
62
  const value = React.useSyncExternalStore<
60
63
  JazzContextType<InstanceOfSchema<S>> | undefined
@@ -71,7 +74,9 @@ export function JazzProviderCore<
71
74
  logOutReplacement: logoutReplacementActiveRef.current
72
75
  ? logOutReplacementRefCallback
73
76
  : undefined,
74
- onAnonymousAccountDiscarded: onAnonymousAccountDiscardedRefCallback,
77
+ onAnonymousAccountDiscarded: onAnonymousAccountDiscardedEnabled
78
+ ? onAnonymousAccountDiscardedRefCallback
79
+ : undefined,
75
80
  CryptoProvider,
76
81
  } satisfies JazzContextManagerProps<S>;
77
82
 
@@ -273,7 +273,13 @@ export class Account extends CoValueBase implements CoValue {
273
273
  creationProps: { name: string };
274
274
  onCreate?: (account: A, worker: Account) => Promise<void>;
275
275
  },
276
- ) {
276
+ ): Promise<{
277
+ credentials: {
278
+ accountID: string;
279
+ accountSecret: AgentSecret;
280
+ };
281
+ account: A;
282
+ }> {
277
283
  const crypto = worker.$jazz.localNode.crypto;
278
284
 
279
285
  const connectedPeers = cojsonInternals.connectedPeers(
@@ -290,6 +296,11 @@ export class Account extends CoValueBase implements CoValue {
290
296
  peers: [connectedPeers[0]],
291
297
  });
292
298
 
299
+ const credentials = {
300
+ accountID: account.$jazz.id,
301
+ accountSecret: account.$jazz.localNode.getCurrentAgent().agentSecret,
302
+ };
303
+
293
304
  // Load the worker inside the account node
294
305
  const loadedWorker = await Account.load(worker.$jazz.id, {
295
306
  loadAs: account,
@@ -314,7 +325,7 @@ export class Account extends CoValueBase implements CoValue {
314
325
  // Close the account node, to avoid leaking memory
315
326
  account.$jazz.localNode.gracefulShutdown();
316
327
 
317
- return createdAccount;
328
+ return { credentials, account: createdAccount };
318
329
  }
319
330
 
320
331
  static fromNode<A extends Account>(
@@ -351,6 +351,16 @@ export class JazzContextManager<
351
351
  // The storage is reachable through currentContext using the connectedPeers
352
352
  prevContext.node.removeStorage();
353
353
 
354
+ // Ensure that the new context is the only peer connected to the previous context
355
+ // This way all the changes made in the previous context are synced only to the new context
356
+ for (const peer of Object.values(prevContext.node.syncManager.peers)) {
357
+ if (!peer.closed) {
358
+ peer.gracefulShutdown();
359
+ }
360
+ }
361
+
362
+ prevContext.node.syncManager.peers = {};
363
+
354
364
  currentContext.node.syncManager.addPeer(prevAccountAsPeer);
355
365
  prevContext.node.syncManager.addPeer(currentAccountAsPeer);
356
366
 
@@ -26,6 +26,7 @@ import {
26
26
  import { CoOptionalSchema } from "./CoOptionalSchema.js";
27
27
  import { CoreResolveQuery } from "./CoValueSchema.js";
28
28
  import { withSchemaResolveQuery } from "../../schemaUtils.js";
29
+ import { AgentSecret } from "cojson";
29
30
 
30
31
  export type BaseProfileShape = {
31
32
  name: z.core.$ZodString<string>;
@@ -103,8 +104,14 @@ export class AccountSchema<
103
104
  worker: Account,
104
105
  ) => Promise<void>;
105
106
  },
107
+ ): Promise<{
108
+ credentials: {
109
+ accountID: string;
110
+ accountSecret: AgentSecret;
111
+ };
106
112
  // @ts-expect-error we can't statically enforce the schema's resolve query is a valid resolve query, but in practice it is
107
- ): Promise<Loaded<AccountSchema<Shape>, DefaultResolveQuery>> {
113
+ account: Loaded<AccountSchema<Shape>, DefaultResolveQuery>;
114
+ }> {
108
115
  // @ts-expect-error
109
116
  return this.coValueClass.createAs(worker, options);
110
117
  }
@@ -309,64 +309,86 @@ export class SubscriptionScope<D extends CoValue> {
309
309
 
310
310
  unloadedValue: NotLoaded<D> | undefined;
311
311
 
312
- lastPromise:
313
- | {
314
- value: MaybeLoaded<D> | undefined;
315
- promise: PromiseWithStatus<MaybeLoaded<D>>;
316
- }
317
- | undefined;
318
-
319
- cachePromise(value: MaybeLoaded<D>, callback: () => PromiseWithStatus<D>) {
320
- if (this.lastPromise?.value === value) {
321
- return this.lastPromise.promise;
322
- }
323
-
324
- const promise = callback();
325
- this.lastPromise = { value, promise };
326
-
327
- return promise;
328
- }
312
+ lastPromise: PromiseWithStatus<D> | undefined;
329
313
 
330
314
  getPromise() {
331
315
  const currentValue = this.getCurrentValue();
332
316
 
333
317
  if (currentValue.$isLoaded) {
334
- return resolvedPromise(currentValue);
318
+ return resolvedPromise<D>(currentValue);
335
319
  }
336
320
 
337
321
  if (currentValue.$jazz.loadingState !== CoValueLoadingState.LOADING) {
338
322
  const error = this.getError();
339
- return rejectedPromise(
323
+ return rejectedPromise<D>(
340
324
  new Error(error?.toString() ?? "Unknown error", {
341
325
  cause: this.callerStack,
342
326
  }),
343
327
  );
344
328
  }
345
329
 
346
- // We need to cache rejected promises to make React Suspense happy
347
- return this.cachePromise(currentValue, () => {
348
- return new Promise<D>((resolve, reject) => {
349
- const unsubscribe = this.subscribe(() => {
350
- const currentValue = this.getCurrentValue();
330
+ const promise = new Promise<D>((resolve, reject) => {
331
+ const unsubscribe = this.subscribe(() => {
332
+ const currentValue = this.getCurrentValue();
351
333
 
352
- if (currentValue.$jazz.loadingState === CoValueLoadingState.LOADING) {
353
- return;
354
- }
334
+ if (currentValue.$jazz.loadingState === CoValueLoadingState.LOADING) {
335
+ return;
336
+ }
355
337
 
356
- if (currentValue.$isLoaded) {
357
- resolve(currentValue);
358
- } else {
359
- reject(
360
- new Error(this.getError()?.toString() ?? "Unknown error", {
361
- cause: this.callerStack,
362
- }),
363
- );
364
- }
338
+ if (currentValue.$isLoaded) {
339
+ promise.status = "fulfilled";
340
+ promise.value = currentValue;
341
+ resolve(currentValue);
342
+ } else {
343
+ promise.status = "rejected";
344
+ promise.reason = new Error(
345
+ this.getError()?.toString() ?? "Unknown error",
346
+ {
347
+ cause: this.callerStack,
348
+ },
349
+ );
350
+ reject(
351
+ new Error(this.getError()?.toString() ?? "Unknown error", {
352
+ cause: this.callerStack,
353
+ }),
354
+ );
355
+ }
365
356
 
366
- unsubscribe();
367
- });
357
+ unsubscribe();
368
358
  });
369
- });
359
+ }) as PromiseWithStatus<D>;
360
+
361
+ promise.status = "pending";
362
+
363
+ return promise;
364
+ }
365
+
366
+ getCachedPromise() {
367
+ if (this.lastPromise) {
368
+ const value = this.getCurrentValue();
369
+
370
+ // if the value is loaded, we update the promise state
371
+ // to ensure that the value provided is always up to date
372
+ if (value.$isLoaded) {
373
+ this.lastPromise.status = "fulfilled";
374
+ this.lastPromise.value = value;
375
+ } else if (value.$jazz.loadingState !== CoValueLoadingState.LOADING) {
376
+ this.lastPromise.status = "rejected";
377
+ this.lastPromise.reason = new Error(
378
+ this.getError()?.toString() ?? "Unknown error",
379
+ {
380
+ cause: this.callerStack,
381
+ },
382
+ );
383
+ } else if (this.lastPromise.status !== "pending") {
384
+ // Value got into loading state, we need to suspend again
385
+ this.lastPromise = this.getPromise();
386
+ }
387
+ } else {
388
+ this.lastPromise = this.getPromise();
389
+ }
390
+
391
+ return this.lastPromise;
370
392
  }
371
393
 
372
394
  private getUnloadedValue(reason: NotLoadedCoValueState): NotLoaded<D> {
@@ -467,7 +467,7 @@ describe("createAs", () => {
467
467
  { owner: worker },
468
468
  );
469
469
 
470
- const createdAccount = await CustomAccount.createAs(worker, {
470
+ const created = await CustomAccount.createAs(worker, {
471
471
  creationProps: { name: "Test Account" },
472
472
  onCreate: async (account, loadedWorker) => {
473
473
  executionOrder.push("onCreate");
@@ -490,11 +490,18 @@ describe("createAs", () => {
490
490
  },
491
491
  });
492
492
 
493
- assertLoaded(createdAccount);
494
- assertLoaded(createdAccount.root);
493
+ assertLoaded(created.account);
494
+ assertLoaded(created.account.root);
495
+
496
+ expect(created.credentials.accountID).toBe(created.account.$jazz.id);
497
+ // ensure we get the created, not the creat*ing* account credentials
498
+ expect(created.credentials.accountID).not.toBe(worker.$jazz.id);
499
+ expect(created.credentials.accountSecret).not.toBe(
500
+ worker.$jazz.localNode.getCurrentAgent().agentSecret,
501
+ );
495
502
 
496
503
  // Verify onCreate was called and root was set from worker
497
- expect(createdAccount.root.value).toBe("worker-root");
504
+ expect(created.account.root.value).toBe("worker-root");
498
505
 
499
506
  // Verify execution order
500
507
  expect(executionOrder).toEqual(["migration", "onCreate"]);
@@ -246,7 +246,7 @@ describe("Schema.resolved()", () => {
246
246
  profile: true,
247
247
  });
248
248
 
249
- const account = await AccountWithProfile.createAs(serverAccount, {
249
+ const { account } = await AccountWithProfile.createAs(serverAccount, {
250
250
  creationProps: { name: "Hermes Puggington" },
251
251
  onCreate: async (account) => {
252
252
  account.$jazz.set(
@@ -405,7 +405,7 @@ describe("Schema.resolved()", () => {
405
405
  test("for Account", async () => {
406
406
  const AccountWithProfile = co.account().resolved({ profile: true });
407
407
 
408
- const account = await AccountWithProfile.createAs(serverAccount, {
408
+ const { account } = await AccountWithProfile.createAs(serverAccount, {
409
409
  creationProps: { name: "Hermes Puggington" },
410
410
  onCreate: async (account) => {
411
411
  account.$jazz.set(
@@ -561,7 +561,7 @@ describe("Schema.resolved()", () => {
561
561
  .list(TestAccount)
562
562
  .resolved({ $each: TestAccount.resolveQuery });
563
563
 
564
- const account = await TestAccount.createAs(serverAccount, {
564
+ const { account } = await TestAccount.createAs(serverAccount, {
565
565
  creationProps: { name: "Hermes Puggington" },
566
566
  onCreate: async (account) => {
567
567
  account.$jazz.set(
package/tsup.config.ts CHANGED
@@ -58,6 +58,7 @@ export default defineConfig([
58
58
  ...cfg,
59
59
  entry: {
60
60
  index: "src/inspector/index.tsx",
61
+ standalone: "src/inspector/standalone.tsx",
61
62
  },
62
63
  outDir: "dist/inspector",
63
64
  esbuildOptions: (options) => {