jazz-tools 0.18.24 → 0.18.25

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 (80) hide show
  1. package/.svelte-kit/__package__/Provider.svelte +2 -0
  2. package/.svelte-kit/__package__/Provider.svelte.d.ts.map +1 -1
  3. package/.turbo/turbo-build.log +53 -53
  4. package/CHANGELOG.md +14 -0
  5. package/dist/browser/index.js +9 -9
  6. package/dist/browser/index.js.map +1 -1
  7. package/dist/{chunk-W7JT3QUN.js → chunk-DOCEAUVD.js} +72 -35
  8. package/dist/chunk-DOCEAUVD.js.map +1 -0
  9. package/dist/{chunk-BOMSRY5H.js → chunk-M2HGBOXS.js} +2 -2
  10. package/dist/chunk-M2HGBOXS.js.map +1 -0
  11. package/dist/index.js +2 -2
  12. package/dist/inspector/{custom-element-XDJT5T57.js → custom-element-A7UAELEG.js} +3 -1
  13. package/dist/inspector/{custom-element-XDJT5T57.js.map → custom-element-A7UAELEG.js.map} +1 -1
  14. package/dist/inspector/index.js +2 -0
  15. package/dist/inspector/index.js.map +1 -1
  16. package/dist/inspector/register-custom-element.js +1 -1
  17. package/dist/inspector/viewer/use-open-inspector.d.ts.map +1 -1
  18. package/dist/inspector/viewer/use-page-path.d.ts.map +1 -1
  19. package/dist/react/index.js +4 -2
  20. package/dist/react/index.js.map +1 -1
  21. package/dist/react/provider.d.ts +2 -1
  22. package/dist/react/provider.d.ts.map +1 -1
  23. package/dist/react/ssr.js +1 -1
  24. package/dist/react/ssr.js.map +1 -1
  25. package/dist/react-native-core/index.js +12 -11
  26. package/dist/react-native-core/index.js.map +1 -1
  27. package/dist/react-native-core/provider.d.ts +2 -1
  28. package/dist/react-native-core/provider.d.ts.map +1 -1
  29. package/dist/svelte/Provider.svelte +2 -0
  30. package/dist/svelte/Provider.svelte.d.ts.map +1 -1
  31. package/dist/testing.js +4 -4
  32. package/dist/testing.js.map +1 -1
  33. package/dist/tools/auth/AuthSecretStorage.d.ts +3 -1
  34. package/dist/tools/auth/AuthSecretStorage.d.ts.map +1 -1
  35. package/dist/tools/coValues/account.d.ts +3 -3
  36. package/dist/tools/coValues/account.d.ts.map +1 -1
  37. package/dist/tools/coValues/group.d.ts +20 -1
  38. package/dist/tools/coValues/group.d.ts.map +1 -1
  39. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  40. package/dist/tools/implementation/ContextManager.d.ts +1 -0
  41. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  42. package/dist/tools/implementation/createContext.d.ts +7 -7
  43. package/dist/tools/implementation/createContext.d.ts.map +1 -1
  44. package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts +5 -0
  45. package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts.map +1 -1
  46. package/dist/tools/ssr.js +1 -1
  47. package/dist/tools/testing.d.ts.map +1 -1
  48. package/dist/worker/index.js +3 -3
  49. package/dist/worker/index.js.map +1 -1
  50. package/package.json +4 -4
  51. package/src/better-auth/database-adapter/tests/sync-utils.ts +1 -1
  52. package/src/browser/createBrowserContext.ts +9 -9
  53. package/src/browser/tests/utils.ts +2 -2
  54. package/src/inspector/viewer/use-open-inspector.ts +1 -0
  55. package/src/inspector/viewer/use-page-path.ts +1 -0
  56. package/src/react/provider.tsx +3 -0
  57. package/src/react-native-core/platform.ts +9 -9
  58. package/src/react-native-core/provider.tsx +3 -1
  59. package/src/svelte/Provider.svelte +2 -0
  60. package/src/tools/auth/AuthSecretStorage.ts +16 -9
  61. package/src/tools/coValues/account.ts +5 -5
  62. package/src/tools/coValues/group.ts +33 -0
  63. package/src/tools/coValues/interfaces.ts +4 -1
  64. package/src/tools/implementation/ContextManager.ts +7 -3
  65. package/src/tools/implementation/createContext.ts +12 -12
  66. package/src/tools/implementation/zodSchema/schemaTypes/GroupSchema.ts +7 -1
  67. package/src/tools/ssr/ssr.ts +1 -1
  68. package/src/tools/testing.ts +3 -3
  69. package/src/tools/tests/AuthSecretStorage.test.ts +59 -1
  70. package/src/tools/tests/ContextManager.test.ts +11 -1
  71. package/src/tools/tests/account.test.ts +16 -0
  72. package/src/tools/tests/coPlainText.test.ts +2 -2
  73. package/src/tools/tests/createContext.test.ts +19 -19
  74. package/src/tools/tests/deepLoading.test.ts +2 -2
  75. package/src/tools/tests/group.test.ts +59 -0
  76. package/src/tools/tests/inbox.test.ts +2 -2
  77. package/src/tools/tests/utils.ts +3 -3
  78. package/src/worker/index.ts +3 -3
  79. package/dist/chunk-BOMSRY5H.js.map +0 -1
  80. package/dist/chunk-W7JT3QUN.js.map +0 -1
@@ -90,7 +90,7 @@ export async function createJazzContextFromExistingCredentials<
90
90
  | CoreAccountSchema,
91
91
  >({
92
92
  credentials,
93
- peersToLoadFrom,
93
+ peers,
94
94
  crypto,
95
95
  storage,
96
96
  AccountSchema: PropsAccountSchema,
@@ -99,7 +99,7 @@ export async function createJazzContextFromExistingCredentials<
99
99
  asActiveAccount,
100
100
  }: {
101
101
  credentials: Credentials;
102
- peersToLoadFrom: Peer[];
102
+ peers: Peer[];
103
103
  crypto: CryptoProvider;
104
104
  AccountSchema?: S;
105
105
  sessionProvider: SessionProvider;
@@ -122,7 +122,7 @@ export async function createJazzContextFromExistingCredentials<
122
122
  accountID: credentials.accountID as unknown as CoID<RawAccount>,
123
123
  accountSecret: credentials.secret,
124
124
  sessionID: sessionID,
125
- peersToLoadFrom: peersToLoadFrom,
125
+ peers: peers,
126
126
  crypto: crypto,
127
127
  storage,
128
128
  migration: async (rawAccount, _node, creationProps) => {
@@ -162,7 +162,7 @@ export async function createJazzContextForNewAccount<
162
162
  >({
163
163
  creationProps,
164
164
  initialAgentSecret,
165
- peersToLoadFrom,
165
+ peers,
166
166
  crypto,
167
167
  AccountSchema: PropsAccountSchema,
168
168
  onLogOut,
@@ -170,7 +170,7 @@ export async function createJazzContextForNewAccount<
170
170
  }: {
171
171
  creationProps: { name: string };
172
172
  initialAgentSecret?: AgentSecret;
173
- peersToLoadFrom: Peer[];
173
+ peers: Peer[];
174
174
  crypto: CryptoProvider;
175
175
  AccountSchema?: S;
176
176
  onLogOut?: () => Promise<void>;
@@ -184,7 +184,7 @@ export async function createJazzContextForNewAccount<
184
184
 
185
185
  const { node } = await LocalNode.withNewlyCreatedAccount({
186
186
  creationProps,
187
- peersToLoadFrom,
187
+ peers,
188
188
  crypto,
189
189
  initialAgentSecret,
190
190
  storage,
@@ -219,7 +219,7 @@ export async function createJazzContext<
219
219
  >(options: {
220
220
  credentials?: AuthCredentials;
221
221
  newAccountProps?: NewAccountProps;
222
- peersToLoadFrom: Peer[];
222
+ peers: Peer[];
223
223
  crypto: CryptoProvider;
224
224
  defaultProfileName?: string;
225
225
  AccountSchema?: S;
@@ -243,7 +243,7 @@ export async function createJazzContext<
243
243
  accountID: credentials.accountID,
244
244
  secret: credentials.accountSecret,
245
245
  },
246
- peersToLoadFrom: options.peersToLoadFrom,
246
+ peers: options.peers,
247
247
  crypto,
248
248
  AccountSchema: options.AccountSchema,
249
249
  sessionProvider: options.sessionProvider,
@@ -267,7 +267,7 @@ export async function createJazzContext<
267
267
  context = await createJazzContextForNewAccount({
268
268
  creationProps,
269
269
  initialAgentSecret,
270
- peersToLoadFrom: options.peersToLoadFrom,
270
+ peers: options.peers,
271
271
  crypto,
272
272
  AccountSchema: options.AccountSchema,
273
273
  onLogOut: async () => {
@@ -293,11 +293,11 @@ export async function createJazzContext<
293
293
  }
294
294
 
295
295
  export function createAnonymousJazzContext({
296
- peersToLoadFrom,
296
+ peers,
297
297
  crypto,
298
298
  storage,
299
299
  }: {
300
- peersToLoadFrom: Peer[];
300
+ peers: Peer[];
301
301
  crypto: CryptoProvider;
302
302
  storage?: StorageAPI;
303
303
  }): JazzContextWithAgent {
@@ -309,7 +309,7 @@ export function createAnonymousJazzContext({
309
309
  crypto,
310
310
  );
311
311
 
312
- for (const peer of peersToLoadFrom) {
312
+ for (const peer of peers) {
313
313
  node.syncManager.addPeer(peer);
314
314
  }
315
315
 
@@ -14,6 +14,7 @@ import {
14
14
  import { CoreCoValueSchema } from "./CoValueSchema.js";
15
15
  import { coOptionalDefiner } from "../zodCo.js";
16
16
  import { CoOptionalSchema } from "./CoOptionalSchema.js";
17
+ import type { AccountRole, InviteSecret } from "cojson";
17
18
 
18
19
  export interface CoreGroupSchema extends CoreCoValueSchema {
19
20
  builtin: "Group";
@@ -51,7 +52,12 @@ export class GroupSchema implements CoreGroupSchema {
51
52
  ): Promise<Group | null> {
52
53
  return Group.load(id, options);
53
54
  }
54
-
55
+ createInvite<G extends Group>(
56
+ id: ID<G>,
57
+ options?: { role?: AccountRole; loadAs?: Account },
58
+ ): Promise<InviteSecret> {
59
+ return Group.createInvite(id, options);
60
+ }
55
61
  subscribe<G extends Group, const R extends RefsToResolve<G>>(
56
62
  id: ID<G>,
57
63
  listener: (value: Resolved<G, R>, unsubscribe: () => void) => void,
@@ -5,7 +5,7 @@ import { createAnonymousJazzContext } from "jazz-tools";
5
5
  export function createSSRJazzAgent(opts: { peer: string }) {
6
6
  const ssrNode = createAnonymousJazzContext({
7
7
  crypto: new PureJSCrypto(),
8
- peersToLoadFrom: [],
8
+ peers: [],
9
9
  });
10
10
 
11
11
  const wsPeer = new WebSocketPeerWithReconnection({
@@ -112,7 +112,7 @@ export async function createJazzTestAccount<
112
112
  },
113
113
  initialAgentSecret: crypto.agentSecretFromSecretSeed(secretSeed),
114
114
  crypto,
115
- peersToLoadFrom: peers,
115
+ peers: peers,
116
116
  migration: async (rawAccount, _node, creationProps) => {
117
117
  if (isMigrationActive) {
118
118
  throw new Error(
@@ -185,7 +185,7 @@ export function runWithoutActiveAccount<Result>(
185
185
  export async function createJazzTestGuest() {
186
186
  const ctx = await createAnonymousJazzContext({
187
187
  crypto: await PureJSCrypto.create(),
188
- peersToLoadFrom: [],
188
+ peers: [],
189
189
  });
190
190
 
191
191
  return {
@@ -318,7 +318,7 @@ export class TestJazzContextManager<
318
318
  credentials: authProps?.credentials,
319
319
  defaultProfileName: props.defaultProfileName,
320
320
  newAccountProps: authProps?.newAccountProps,
321
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
321
+ peers: [getPeerConnectedToTestSyncServer()],
322
322
  crypto: await TestJSCrypto.create(),
323
323
  sessionProvider: randomSessionProvider,
324
324
  authSecretStorage: this.getAuthSecretStorage(),
@@ -1,6 +1,6 @@
1
1
  // @vitest-environment happy-dom
2
2
 
3
- import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
4
4
  import { AuthSecretStorage } from "../auth/AuthSecretStorage";
5
5
  import { InMemoryKVStore } from "../auth/InMemoryKVStore.js";
6
6
  import KvStoreContext from "../auth/KvStoreContext";
@@ -428,4 +428,62 @@ describe("AuthSecretStorage", () => {
428
428
  });
429
429
  });
430
430
  });
431
+
432
+ describe("configurable secret storage key", () => {
433
+ const KEY = "test-auth-secret";
434
+ beforeEach(() => {
435
+ kvStore.clearAll();
436
+ authSecretStorage = new AuthSecretStorage(KEY);
437
+ });
438
+
439
+ afterAll(() => {
440
+ // Restore the default storage key
441
+ authSecretStorage = new AuthSecretStorage();
442
+ });
443
+
444
+ it("should throw an error if the storage key is empty", () => {
445
+ expect(() => new AuthSecretStorage("")).toThrow(
446
+ "Too small: expected string to have >=1 characters",
447
+ );
448
+ });
449
+
450
+ it("should use the configured storage key on get", async () => {
451
+ const credentials = {
452
+ accountID: "test123",
453
+ secretSeed: [1, 2, 3],
454
+ accountSecret: "secret123",
455
+ provider: "anonymous",
456
+ };
457
+ await kvStore.set(KEY, JSON.stringify(credentials));
458
+
459
+ const result = await authSecretStorage.get();
460
+
461
+ expect(result).toEqual({
462
+ accountID: "test123",
463
+ secretSeed: new Uint8Array([1, 2, 3]),
464
+ accountSecret: "secret123",
465
+ provider: "anonymous",
466
+ });
467
+ });
468
+
469
+ it("should use the configured storage key on set", async () => {
470
+ const payload = {
471
+ accountID: "test123" as ID<Account>,
472
+ secretSeed: new Uint8Array([1, 2, 3]),
473
+ accountSecret:
474
+ "secret123" as `sealerSecret_z${string}/signerSecret_z${string}`,
475
+ provider: "passphrase",
476
+ };
477
+
478
+ await authSecretStorage.set(payload);
479
+
480
+ const stored = JSON.parse((await kvStore.get(KEY))!);
481
+ expect(stored).toEqual({
482
+ accountID: "test123",
483
+ secretSeed: [1, 2, 3],
484
+ accountSecret: "secret123",
485
+ provider: "passphrase",
486
+ });
487
+ });
488
+ });
431
489
  });
@@ -56,7 +56,7 @@ class TestJazzContextManager<Acc extends Account> extends JazzContextManager<
56
56
  credentials: authProps?.credentials,
57
57
  defaultProfileName: props.defaultProfileName,
58
58
  newAccountProps: authProps?.newAccountProps,
59
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
59
+ peers: [getPeerConnectedToTestSyncServer()],
60
60
  crypto: Crypto,
61
61
  sessionProvider: randomSessionProvider,
62
62
  authSecretStorage: this.getAuthSecretStorage(),
@@ -541,6 +541,16 @@ describe("ContextManager", () => {
541
541
  ).rejects.toThrow("Props required");
542
542
  });
543
543
 
544
+ describe("configurable storage key", () => {
545
+ test("uses the configured storage key", async () => {
546
+ const KEY = "test-auth-secret";
547
+ const manager = new TestJazzContextManager<Account>({
548
+ authSecretStorageKey: KEY,
549
+ });
550
+ expect(manager.getAuthSecretStorage().getStorageKey()).toBe(KEY);
551
+ });
552
+ });
553
+
544
554
  describe("Race condition handling", () => {
545
555
  test("prevents concurrent authentication attempts", async () => {
546
556
  const account = await createJazzTestAccount();
@@ -409,3 +409,19 @@ describe("account.toJSON", () => {
409
409
  });
410
410
  });
411
411
  });
412
+
413
+ describe("accepting invites", () => {
414
+ test("accepting an invite to a Group", async () => {
415
+ const account = await createJazzTestAccount({
416
+ isCurrentActiveAccount: true,
417
+ });
418
+ const group = co.group().create();
419
+ const invite = group.$jazz.createInvite("reader");
420
+ const newAccount = await createJazzTestAccount({
421
+ isCurrentActiveAccount: true,
422
+ });
423
+ expect(group.getRoleOf(newAccount.$jazz.id)).toBeUndefined();
424
+ await newAccount.acceptInvite(group.$jazz.id, invite);
425
+ expect(group.getRoleOf(newAccount.$jazz.id)).toBe("reader");
426
+ });
427
+ });
@@ -205,7 +205,7 @@ describe("CoPlainText", () => {
205
205
  secret: me.$jazz.localNode.getCurrentAgent().agentSecret,
206
206
  },
207
207
  sessionProvider: randomSessionProvider,
208
- peersToLoadFrom: [initialAsPeer],
208
+ peers: [initialAsPeer],
209
209
  crypto: Crypto,
210
210
  asActiveAccount: true,
211
211
  });
@@ -237,7 +237,7 @@ describe("CoPlainText", () => {
237
237
  secret: me.$jazz.localNode.getCurrentAgent().agentSecret,
238
238
  },
239
239
  sessionProvider: randomSessionProvider,
240
- peersToLoadFrom: [initialAsPeer],
240
+ peers: [initialAsPeer],
241
241
  crypto: Crypto,
242
242
  asActiveAccount: true,
243
243
  });
@@ -51,7 +51,7 @@ describe("createContext methods", () => {
51
51
 
52
52
  const context = await createJazzContextFromExistingCredentials({
53
53
  credentials,
54
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
54
+ peers: [getPeerConnectedToTestSyncServer()],
55
55
  crypto: Crypto,
56
56
  sessionProvider: randomSessionProvider,
57
57
  asActiveAccount: true,
@@ -83,7 +83,7 @@ describe("createContext methods", () => {
83
83
 
84
84
  const context = await createJazzContextFromExistingCredentials({
85
85
  credentials,
86
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
86
+ peers: [getPeerConnectedToTestSyncServer()],
87
87
  crypto: Crypto,
88
88
  AccountSchema: CustomAccount,
89
89
  sessionProvider: randomSessionProvider,
@@ -107,7 +107,7 @@ describe("createContext methods", () => {
107
107
  accountID: account.$jazz.id,
108
108
  secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
109
109
  },
110
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
110
+ peers: [getPeerConnectedToTestSyncServer()],
111
111
  crypto: Crypto,
112
112
  sessionProvider: randomSessionProvider,
113
113
  onLogOut,
@@ -131,7 +131,7 @@ describe("createContext methods", () => {
131
131
  accountID: account.$jazz.id,
132
132
  secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
133
133
  },
134
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
134
+ peers: [getPeerConnectedToTestSyncServer()],
135
135
  crypto: Crypto,
136
136
  sessionProvider: randomSessionProvider,
137
137
  asActiveAccount: true,
@@ -152,7 +152,7 @@ describe("createContext methods", () => {
152
152
  accountID: account.$jazz.id,
153
153
  secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
154
154
  },
155
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
155
+ peers: [getPeerConnectedToTestSyncServer()],
156
156
  crypto: Crypto,
157
157
  sessionProvider: randomSessionProvider,
158
158
  asActiveAccount: true,
@@ -171,7 +171,7 @@ describe("createContext methods", () => {
171
171
  accountID: account.$jazz.id,
172
172
  secret: account.$jazz.localNode.getCurrentAgent().agentSecret,
173
173
  },
174
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
174
+ peers: [getPeerConnectedToTestSyncServer()],
175
175
  crypto: Crypto,
176
176
  sessionProvider: randomSessionProvider,
177
177
  asActiveAccount: false,
@@ -185,7 +185,7 @@ describe("createContext methods", () => {
185
185
  test("creates new account with provided props", async () => {
186
186
  const context = await createJazzContextForNewAccount({
187
187
  creationProps: { name: "New User" },
188
- peersToLoadFrom: [],
188
+ peers: [],
189
189
  crypto: Crypto,
190
190
  });
191
191
 
@@ -199,7 +199,7 @@ describe("createContext methods", () => {
199
199
  const context = await createJazzContextForNewAccount({
200
200
  creationProps: { name: "New User" },
201
201
  initialAgentSecret: initialSecret,
202
- peersToLoadFrom: [],
202
+ peers: [],
203
203
  crypto: Crypto,
204
204
  });
205
205
 
@@ -216,7 +216,7 @@ describe("createContext methods", () => {
216
216
 
217
217
  const context = await createJazzContextForNewAccount({
218
218
  creationProps: { name: "New User" },
219
- peersToLoadFrom: [],
219
+ peers: [],
220
220
  crypto: Crypto,
221
221
  AccountSchema: CustomAccount,
222
222
  });
@@ -229,7 +229,7 @@ describe("createContext methods", () => {
229
229
  test("sets the active account to the new account", async () => {
230
230
  const context = await createJazzContextForNewAccount({
231
231
  creationProps: { name: "New User" },
232
- peersToLoadFrom: [],
232
+ peers: [],
233
233
  crypto: Crypto,
234
234
  });
235
235
  expect(activeAccountContext.get()).toBe(context.account);
@@ -239,7 +239,7 @@ describe("createContext methods", () => {
239
239
  describe("createAnonymousJazzContext", () => {
240
240
  test("creates anonymous context", async () => {
241
241
  const context = await createAnonymousJazzContext({
242
- peersToLoadFrom: [],
242
+ peers: [],
243
243
  crypto: Crypto,
244
244
  });
245
245
 
@@ -257,7 +257,7 @@ describe("createContext methods", () => {
257
257
  coMap.set("test", "test", "trusting");
258
258
 
259
259
  const context = await createAnonymousJazzContext({
260
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
260
+ peers: [getPeerConnectedToTestSyncServer()],
261
261
  crypto: Crypto,
262
262
  });
263
263
 
@@ -268,7 +268,7 @@ describe("createContext methods", () => {
268
268
 
269
269
  test("sets the guest mode", async () => {
270
270
  await createAnonymousJazzContext({
271
- peersToLoadFrom: [],
271
+ peers: [],
272
272
  crypto: Crypto,
273
273
  });
274
274
 
@@ -281,7 +281,7 @@ describe("createContext methods", () => {
281
281
  describe("createJazzContext", () => {
282
282
  test("creates new account when no credentials exist", async () => {
283
283
  const context = await createJazzContext({
284
- peersToLoadFrom: [],
284
+ peers: [],
285
285
  crypto: Crypto,
286
286
  authSecretStorage,
287
287
  sessionProvider: randomSessionProvider,
@@ -294,7 +294,7 @@ describe("createContext methods", () => {
294
294
  test("uses existing credentials when available", async () => {
295
295
  // First create an account and store credentials
296
296
  const initialContext = await createJazzContext({
297
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
297
+ peers: [getPeerConnectedToTestSyncServer()],
298
298
  crypto: Crypto,
299
299
  authSecretStorage,
300
300
  sessionProvider: randomSessionProvider,
@@ -302,7 +302,7 @@ describe("createContext methods", () => {
302
302
 
303
303
  // Create new context with same storage
304
304
  const newContext = await createJazzContext({
305
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
305
+ peers: [getPeerConnectedToTestSyncServer()],
306
306
  crypto: Crypto,
307
307
  authSecretStorage,
308
308
  sessionProvider: randomSessionProvider,
@@ -316,7 +316,7 @@ describe("createContext methods", () => {
316
316
  newAccountProps: {
317
317
  creationProps: { name: "Custom User" },
318
318
  },
319
- peersToLoadFrom: [],
319
+ peers: [],
320
320
  crypto: Crypto,
321
321
  authSecretStorage,
322
322
  sessionProvider: randomSessionProvider,
@@ -341,7 +341,7 @@ describe("createContext methods", () => {
341
341
  newAccountProps: {
342
342
  secret: initialSecret,
343
343
  },
344
- peersToLoadFrom: [],
344
+ peers: [],
345
345
  crypto: Crypto,
346
346
  authSecretStorage,
347
347
  sessionProvider: randomSessionProvider,
@@ -365,7 +365,7 @@ describe("createContext methods", () => {
365
365
  .withMigration(async () => {});
366
366
 
367
367
  const context = await createJazzContext({
368
- peersToLoadFrom: [],
368
+ peers: [],
369
369
  crypto: Crypto,
370
370
  authSecretStorage,
371
371
  sessionProvider: randomSessionProvider,
@@ -55,7 +55,7 @@ describe("Deep loading with depth arg", async () => {
55
55
  secret: me.$jazz.localNode.getCurrentAgent().agentSecret,
56
56
  },
57
57
  sessionProvider: randomSessionProvider,
58
- peersToLoadFrom: [initialAsPeer],
58
+ peers: [initialAsPeer],
59
59
  crypto: Crypto,
60
60
  asActiveAccount: true,
61
61
  });
@@ -286,7 +286,7 @@ test("Deep loading a record-like coMap", async () => {
286
286
  secret: me.$jazz.localNode.getCurrentAgent().agentSecret,
287
287
  },
288
288
  sessionProvider: randomSessionProvider,
289
- peersToLoadFrom: [initialAsPeer],
289
+ peers: [initialAsPeer],
290
290
  crypto: Crypto,
291
291
  asActiveAccount: true,
292
292
  });
@@ -30,6 +30,65 @@ describe("Group", () => {
30
30
  expect(group.getRoleOf("everyone")).toBe("reader");
31
31
  });
32
32
 
33
+ describe("Invitations", () => {
34
+ it("should create invitations as an instance method", () => {
35
+ const group = co.group().create();
36
+ const invite = group.$jazz.createInvite();
37
+ expect(invite.startsWith("inviteSecret_")).toBeTruthy();
38
+ });
39
+
40
+ it("should create invitations as an static method", async () => {
41
+ const group = co.group().create();
42
+ const groupId = group.$jazz.id;
43
+ const invite = await Group.createInvite(groupId);
44
+ expect(invite.startsWith("inviteSecret_")).toBeTruthy();
45
+ });
46
+
47
+ it("should correctly create invitations for users of different roles", async () => {
48
+ const currentUser = Account.getMe();
49
+ const group = co.group().create();
50
+ const invites = {
51
+ reader: group.$jazz.createInvite("reader"),
52
+ writeOnly: group.$jazz.createInvite("writeOnly"),
53
+ writer: group.$jazz.createInvite("writer"),
54
+ admin: group.$jazz.createInvite("admin"),
55
+ };
56
+
57
+ expect(group.getRoleOf(currentUser.$jazz.id)).toBe("admin");
58
+
59
+ for (const [role, inviteSecret] of Object.entries(invites)) {
60
+ const newUser = await createJazzTestAccount({
61
+ isCurrentActiveAccount: true,
62
+ });
63
+ expect(group.getRoleOf(newUser.$jazz.id)).toBeUndefined();
64
+ await newUser.acceptInvite(group.$jazz.id, inviteSecret);
65
+ expect(group.getRoleOf(newUser.$jazz.id)).toBe(role);
66
+ }
67
+ });
68
+
69
+ it("should create invitations with loadAs option", async () => {
70
+ const group = co.group().create();
71
+ const groupId = group.$jazz.id;
72
+
73
+ const otherAccount = await createJazzTestAccount();
74
+ group.addMember(otherAccount, "admin");
75
+
76
+ const invite = await Group.createInvite(groupId, {
77
+ role: "writer",
78
+ loadAs: otherAccount,
79
+ });
80
+
81
+ expect(invite.startsWith("inviteSecret_")).toBeTruthy();
82
+ });
83
+
84
+ it("should create invitations via co.group() schema wrapper", async () => {
85
+ const group = co.group().create();
86
+ const groupId = group.$jazz.id;
87
+ const invite = await co.group().createInvite(groupId, { role: "writer" });
88
+ expect(invite.startsWith("inviteSecret_")).toBeTruthy();
89
+ });
90
+ });
91
+
33
92
  describe("TypeScript", () => {
34
93
  it("should correctly type the resolve query", async () => {
35
94
  const group = co.group().create();
@@ -424,7 +424,7 @@ describe("Inbox", () => {
424
424
  const node = await LocalNode.withLoadedAccount({
425
425
  accountID: accountId as any,
426
426
  accountSecret: accountSecret,
427
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
427
+ peers: [getPeerConnectedToTestSyncServer()],
428
428
  crypto: receiver.$jazz.localNode.crypto,
429
429
  sessionID: sessionID,
430
430
  });
@@ -495,7 +495,7 @@ describe("Inbox", () => {
495
495
  const node = await LocalNode.withLoadedAccount({
496
496
  accountID: accountId as any,
497
497
  accountSecret: accountSecret,
498
- peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
498
+ peers: [getPeerConnectedToTestSyncServer()],
499
499
  crypto: receiver.$jazz.localNode.crypto,
500
500
  sessionID: sessionID,
501
501
  });
@@ -38,7 +38,7 @@ export async function setupAccount() {
38
38
  secret: me.$jazz.localNode.getCurrentAgent().agentSecret,
39
39
  },
40
40
  sessionProvider: randomSessionProvider,
41
- peersToLoadFrom: [initialAsPeer],
41
+ peers: [initialAsPeer],
42
42
  crypto: Crypto,
43
43
  asActiveAccount: true,
44
44
  });
@@ -61,7 +61,7 @@ export async function setupTwoNodes(options?: {
61
61
  );
62
62
 
63
63
  const client = await LocalNode.withNewlyCreatedAccount({
64
- peersToLoadFrom: [serverAsPeer],
64
+ peers: [serverAsPeer],
65
65
  crypto: Crypto,
66
66
  creationProps: { name: "Client" },
67
67
  migration: async (rawAccount, _node, creationProps) => {
@@ -74,7 +74,7 @@ export async function setupTwoNodes(options?: {
74
74
  });
75
75
 
76
76
  const server = await LocalNode.withNewlyCreatedAccount({
77
- peersToLoadFrom: [clientAsPeer],
77
+ peers: [clientAsPeer],
78
78
  crypto: Crypto,
79
79
  creationProps: { name: "Server" },
80
80
  migration: async (rawAccount, _node, creationProps) => {
@@ -54,7 +54,7 @@ export async function startWorker<
54
54
 
55
55
  let node: LocalNode | undefined = undefined;
56
56
 
57
- const peersToLoadFrom: Peer[] = [];
57
+ const peers: Peer[] = [];
58
58
 
59
59
  const wsPeer = new WebSocketPeerWithReconnection({
60
60
  peer: syncServer,
@@ -63,7 +63,7 @@ export async function startWorker<
63
63
  if (node) {
64
64
  node.syncManager.addPeer(peer);
65
65
  } else {
66
- peersToLoadFrom.push(peer);
66
+ peers.push(peer);
67
67
  }
68
68
  },
69
69
  removePeer: () => {},
@@ -92,7 +92,7 @@ export async function startWorker<
92
92
  },
93
93
  AccountSchema,
94
94
  sessionProvider: randomSessionProvider,
95
- peersToLoadFrom,
95
+ peers,
96
96
  crypto: options.crypto ?? (await WasmCrypto.create()),
97
97
  asActiveAccount,
98
98
  });
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tools/ssr/ssr.ts"],"sourcesContent":["import { WebSocketPeerWithReconnection } from \"cojson-transport-ws\";\nimport { PureJSCrypto } from \"cojson/dist/crypto/PureJSCrypto\";\nimport { createAnonymousJazzContext } from \"jazz-tools\";\n\nexport function createSSRJazzAgent(opts: { peer: string }) {\n const ssrNode = createAnonymousJazzContext({\n crypto: new PureJSCrypto(),\n peersToLoadFrom: [],\n });\n\n const wsPeer = new WebSocketPeerWithReconnection({\n peer: opts.peer,\n reconnectionTimeout: 100,\n addPeer: (peer) => {\n ssrNode.agent.node.syncManager.addPeer(peer);\n },\n removePeer: () => {},\n });\n\n wsPeer.enable();\n\n return ssrNode.agent;\n}\n"],"mappings":";AAAA,SAAS,qCAAqC;AAC9C,SAAS,oBAAoB;AAC7B,SAAS,kCAAkC;AAEpC,SAAS,mBAAmB,MAAwB;AACzD,QAAM,UAAU,2BAA2B;AAAA,IACzC,QAAQ,IAAI,aAAa;AAAA,IACzB,iBAAiB,CAAC;AAAA,EACpB,CAAC;AAED,QAAM,SAAS,IAAI,8BAA8B;AAAA,IAC/C,MAAM,KAAK;AAAA,IACX,qBAAqB;AAAA,IACrB,SAAS,CAAC,SAAS;AACjB,cAAQ,MAAM,KAAK,YAAY,QAAQ,IAAI;AAAA,IAC7C;AAAA,IACA,YAAY,MAAM;AAAA,IAAC;AAAA,EACrB,CAAC;AAED,SAAO,OAAO;AAEd,SAAO,QAAQ;AACjB;","names":[]}