jazz-tools 0.15.7 → 0.15.9

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 (56) hide show
  1. package/.turbo/turbo-build.log +42 -42
  2. package/CHANGELOG.md +21 -0
  3. package/dist/browser/createBrowserContext.d.ts.map +1 -1
  4. package/dist/browser/index.js +9 -7
  5. package/dist/browser/index.js.map +1 -1
  6. package/dist/{chunk-AV3MKD64.js → chunk-5PFEKHX5.js} +30 -5
  7. package/dist/chunk-5PFEKHX5.js.map +1 -0
  8. package/dist/index.js +1 -1
  9. package/dist/inspector/{custom-element-I7Q6H5E5.js → custom-element-TUXKXSZU.js} +18791 -18806
  10. package/dist/inspector/custom-element-TUXKXSZU.js.map +1 -0
  11. package/dist/inspector/register-custom-element.js +1 -1
  12. package/dist/react/index.js +1 -1
  13. package/dist/react/index.js.map +1 -1
  14. package/dist/react/testing.js +1 -1
  15. package/dist/react/testing.js.map +1 -1
  16. package/dist/react-native-core/index.d.ts +1 -1
  17. package/dist/react-native-core/index.d.ts.map +1 -1
  18. package/dist/react-native-core/index.js +15 -31
  19. package/dist/react-native-core/index.js.map +1 -1
  20. package/dist/react-native-core/platform.d.ts +1 -1
  21. package/dist/react-native-core/platform.d.ts.map +1 -1
  22. package/dist/testing.js +22 -3
  23. package/dist/testing.js.map +1 -1
  24. package/dist/tools/exports.d.ts +1 -1
  25. package/dist/tools/exports.d.ts.map +1 -1
  26. package/dist/tools/implementation/createContext.d.ts +8 -4
  27. package/dist/tools/implementation/createContext.d.ts.map +1 -1
  28. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +12 -13
  29. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  30. package/dist/tools/implementation/zodSchema/zodCo.d.ts +39 -9
  31. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  32. package/dist/tools/subscribe/SubscriptionScope.d.ts +2 -0
  33. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  34. package/dist/tools/testing.d.ts +3 -1
  35. package/dist/tools/testing.d.ts.map +1 -1
  36. package/package.json +7 -7
  37. package/src/browser/createBrowserContext.ts +8 -6
  38. package/src/react-core/tests/useCoState.test.ts +0 -12
  39. package/src/react-native-core/index.ts +1 -1
  40. package/src/react-native-core/platform.ts +13 -12
  41. package/src/tools/exports.ts +2 -0
  42. package/src/tools/implementation/createContext.ts +16 -0
  43. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +17 -15
  44. package/src/tools/implementation/zodSchema/zodCo.ts +54 -32
  45. package/src/tools/subscribe/SubscriptionScope.ts +20 -0
  46. package/src/tools/testing.ts +25 -2
  47. package/src/tools/tests/coFeed.test.ts +190 -239
  48. package/src/tools/tests/coMap.test.ts +0 -8
  49. package/src/tools/tests/coPlainText.test.ts +2 -1
  50. package/src/tools/tests/load.test.ts +65 -30
  51. package/src/tools/tests/subscribe.test.ts +92 -0
  52. package/dist/chunk-AV3MKD64.js.map +0 -1
  53. package/dist/inspector/custom-element-I7Q6H5E5.js.map +0 -1
  54. package/dist/react-native-core/storage/sqlite-react-native.d.ts +0 -9
  55. package/dist/react-native-core/storage/sqlite-react-native.d.ts.map +0 -1
  56. package/src/react-native-core/storage/sqlite-react-native.ts +0 -19
@@ -8,6 +8,7 @@ import {
8
8
  RawAccount,
9
9
  RawAccountID,
10
10
  SessionID,
11
+ StorageAPI,
11
12
  } from "cojson";
12
13
  import { AuthSecretStorage } from "../auth/AuthSecretStorage.js";
13
14
  import { type Account, type AccountClass } from "../coValues/account.js";
@@ -93,6 +94,7 @@ export async function createJazzContextFromExistingCredentials<
93
94
  credentials,
94
95
  peersToLoadFrom,
95
96
  crypto,
97
+ storage,
96
98
  AccountSchema: PropsAccountSchema,
97
99
  sessionProvider,
98
100
  onLogOut,
@@ -103,6 +105,7 @@ export async function createJazzContextFromExistingCredentials<
103
105
  AccountSchema?: S;
104
106
  sessionProvider: SessionProvider;
105
107
  onLogOut?: () => void;
108
+ storage?: StorageAPI;
106
109
  }): Promise<JazzContextWithAccount<InstanceOfSchema<S>>> {
107
110
  const { sessionID, sessionDone } = await sessionProvider(
108
111
  credentials.accountID,
@@ -120,6 +123,7 @@ export async function createJazzContextFromExistingCredentials<
120
123
  sessionID: sessionID,
121
124
  peersToLoadFrom: peersToLoadFrom,
122
125
  crypto: crypto,
126
+ storage,
123
127
  migration: async (rawAccount, _node, creationProps) => {
124
128
  const account = AccountClass.fromRaw(rawAccount) as InstanceOfSchema<S>;
125
129
  activeAccountContext.set(account);
@@ -157,6 +161,7 @@ export async function createJazzContextForNewAccount<
157
161
  crypto,
158
162
  AccountSchema: PropsAccountSchema,
159
163
  onLogOut,
164
+ storage,
160
165
  }: {
161
166
  creationProps: { name: string };
162
167
  initialAgentSecret?: AgentSecret;
@@ -164,6 +169,7 @@ export async function createJazzContextForNewAccount<
164
169
  crypto: CryptoProvider;
165
170
  AccountSchema?: S;
166
171
  onLogOut?: () => Promise<void>;
172
+ storage?: StorageAPI;
167
173
  }): Promise<JazzContextWithAccount<InstanceOfSchema<S>>> {
168
174
  const CurrentAccountSchema =
169
175
  PropsAccountSchema ?? (RegisteredSchemas["Account"] as unknown as S);
@@ -175,6 +181,7 @@ export async function createJazzContextForNewAccount<
175
181
  peersToLoadFrom,
176
182
  crypto,
177
183
  initialAgentSecret,
184
+ storage,
178
185
  migration: async (rawAccount, _node, creationProps) => {
179
186
  const account = AccountClass.fromRaw(rawAccount) as InstanceOfSchema<S>;
180
187
  activeAccountContext.set(account);
@@ -212,6 +219,7 @@ export async function createJazzContext<
212
219
  AccountSchema?: S;
213
220
  sessionProvider: SessionProvider;
214
221
  authSecretStorage: AuthSecretStorage;
222
+ storage?: StorageAPI;
215
223
  }) {
216
224
  const crypto = options.crypto;
217
225
 
@@ -236,6 +244,7 @@ export async function createJazzContext<
236
244
  onLogOut: () => {
237
245
  authSecretStorage.clearWithoutNotify();
238
246
  },
247
+ storage: options.storage,
239
248
  });
240
249
  } else {
241
250
  const secretSeed = options.crypto.newRandomSecretSeed();
@@ -257,6 +266,7 @@ export async function createJazzContext<
257
266
  onLogOut: async () => {
258
267
  await authSecretStorage.clearWithoutNotify();
259
268
  },
269
+ storage: options.storage,
260
270
  });
261
271
 
262
272
  if (!options.newAccountProps) {
@@ -278,9 +288,11 @@ export async function createJazzContext<
278
288
  export function createAnonymousJazzContext({
279
289
  peersToLoadFrom,
280
290
  crypto,
291
+ storage,
281
292
  }: {
282
293
  peersToLoadFrom: Peer[];
283
294
  crypto: CryptoProvider;
295
+ storage?: StorageAPI;
284
296
  }): JazzContextWithAgent {
285
297
  const agentSecret = crypto.newRandomAgentSecret();
286
298
 
@@ -294,6 +306,10 @@ export function createAnonymousJazzContext({
294
306
  node.syncManager.addPeer(peer);
295
307
  }
296
308
 
309
+ if (storage) {
310
+ node.setStorage(storage);
311
+ }
312
+
297
313
  activeAccountContext.setGuestMode();
298
314
 
299
315
  return {
@@ -7,22 +7,24 @@ import { z } from "../zodReExport.js";
7
7
  import { Loaded, ResolveQuery } from "../zodSchema.js";
8
8
  import { AnyCoMapSchema, CoMapSchema } from "./CoMapSchema.js";
9
9
 
10
+ export type BaseProfileShape = {
11
+ name: z.core.$ZodString<string>;
12
+ inbox?: z.core.$ZodOptional<z.core.$ZodString>;
13
+ inboxInvite?: z.core.$ZodOptional<z.core.$ZodString>;
14
+ };
15
+
16
+ export type BaseAccountShape = {
17
+ profile: AnyCoMapSchema<BaseProfileShape>;
18
+ root: AnyCoMapSchema;
19
+ };
20
+
21
+ export type DefaultAccountShape = {
22
+ profile: CoMapSchema<BaseProfileShape>;
23
+ root: CoMapSchema<{}>;
24
+ };
25
+
10
26
  export type AccountSchema<
11
- Shape extends {
12
- profile: AnyCoMapSchema<{
13
- name: z.core.$ZodString<string>;
14
- inbox?: z.core.$ZodOptional<z.core.$ZodString>;
15
- inboxInvite?: z.core.$ZodOptional<z.core.$ZodString>;
16
- }>;
17
- root: AnyCoMapSchema;
18
- } = {
19
- profile: CoMapSchema<{
20
- name: z.core.$ZodString<string>;
21
- inbox?: z.core.$ZodOptional<z.core.$ZodString>;
22
- inboxInvite?: z.core.$ZodOptional<z.core.$ZodString>;
23
- }>;
24
- root: CoMapSchema<{}>;
25
- },
27
+ Shape extends BaseAccountShape = DefaultAccountShape,
26
28
  > = Omit<CoMapSchema<Shape>, "create" | "load" | "withMigration"> & {
27
29
  builtin: "Account";
28
30
 
@@ -1,22 +1,23 @@
1
1
  import {
2
2
  type Account,
3
- AccountCreationProps,
4
- AccountSchema,
5
- AnyCoMapSchema,
3
+ type AccountCreationProps,
4
+ type AccountSchema,
5
+ type AnyCoMapSchema,
6
+ BaseAccountShape,
6
7
  CoFeed,
7
- CoFeedSchema,
8
- CoListSchema,
9
- CoMapSchema,
8
+ type CoFeedSchema,
9
+ type CoListSchema,
10
+ type CoMapSchema,
10
11
  CoPlainText,
11
- CoProfileSchema,
12
- CoRecordSchema,
12
+ type CoProfileSchema,
13
+ type CoRecordSchema,
13
14
  CoRichText,
14
- DefaultProfileShape,
15
+ type DefaultProfileShape,
15
16
  FileStream,
16
- FileStreamSchema,
17
+ type FileStreamSchema,
17
18
  ImageDefinition,
18
- PlainTextSchema,
19
- Simplify,
19
+ type PlainTextSchema,
20
+ type Simplify,
20
21
  zodSchemaToCoSchema,
21
22
  } from "../../internal.js";
22
23
  import { RichTextSchema } from "./schemaTypes/RichTextSchema.js";
@@ -82,16 +83,9 @@ export const coMapDefiner = <Shape extends z.core.$ZodLooseShape>(
82
83
  return enrichCoMapSchema(objectSchema);
83
84
  };
84
85
 
85
- function enrichAccountSchema<
86
- Shape extends {
87
- profile: AnyCoMapSchema<{
88
- name: z.core.$ZodString<string>;
89
- inbox?: z.core.$ZodOptional<z.core.$ZodString>;
90
- inboxInvite?: z.core.$ZodOptional<z.core.$ZodString>;
91
- }>;
92
- root: AnyCoMapSchema;
93
- },
94
- >(schema: z.ZodObject<Shape, z.core.$strip>) {
86
+ function enrichAccountSchema<Shape extends BaseAccountShape>(
87
+ schema: z.ZodObject<Shape, z.core.$strip>,
88
+ ) {
95
89
  const enrichedSchema = Object.assign(schema, {
96
90
  collaborative: true,
97
91
  builtin: "Account",
@@ -142,16 +136,44 @@ function enrichAccountSchema<
142
136
  return enrichedSchema;
143
137
  }
144
138
 
145
- export const coAccountDefiner = <
146
- Shape extends {
147
- profile: AnyCoMapSchema<{
148
- name: z.core.$ZodString<string>;
149
- inbox?: z.core.$ZodOptional<z.core.$ZodString>;
150
- inboxInvite?: z.core.$ZodOptional<z.core.$ZodString>;
151
- }>;
152
- root: AnyCoMapSchema;
153
- },
154
- >(
139
+ /**
140
+ * Defines a collaborative account schema for Jazz applications.
141
+ *
142
+ * Creates an account schema that represents a user account with profile and root data.
143
+ * Accounts are the primary way to identify and manage users in Jazz applications.
144
+ *
145
+ * @template Shape - The shape of the account schema extending BaseAccountShape
146
+ * @param shape - The account schema shape. Defaults to a basic profile with name, inbox, and inboxInvite fields, plus an empty root object.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * // Basic account with default profile
151
+ * const BasicAccount = co.account();
152
+ *
153
+ * // Custom account with specific profile and root structure
154
+ * const JazzAccount = co.account({
155
+ * profile: co.profile({
156
+ * name: z.string(),
157
+ * avatar: z.optional(z.string()),
158
+ * }),
159
+ * root: co.map({
160
+ * organizations: co.list(Organization),
161
+ * draftOrganization: DraftOrganization,
162
+ * }),
163
+ * }).withMigration(async (account) => {
164
+ * // Migration logic for existing accounts
165
+ * if (account.profile === undefined) {
166
+ * const group = Group.create();
167
+ * account.profile = co.profile().create(
168
+ * { name: getRandomUsername() },
169
+ * group
170
+ * );
171
+ * group.addMember("everyone", "reader");
172
+ * }
173
+ * });
174
+ * ```
175
+ */
176
+ export const coAccountDefiner = <Shape extends BaseAccountShape>(
155
177
  shape: Shape = {
156
178
  profile: coMapDefiner({
157
179
  name: z.string(),
@@ -249,6 +249,10 @@ export class SubscriptionScope<D extends CoValue> {
249
249
  // If the value is in error, we send the update regardless of the children statuses
250
250
  if (this.value.type !== "loaded") return true;
251
251
 
252
+ if (this.isStreaming() && !this.isFileStream()) {
253
+ return false;
254
+ }
255
+
252
256
  for (const value of this.childValues.values()) {
253
257
  // We don't wait for autoloaded values to be loaded, in order to stream updates
254
258
  // on autoloaded lists or records
@@ -285,6 +289,22 @@ export class SubscriptionScope<D extends CoValue> {
285
289
  return undefined;
286
290
  }
287
291
 
292
+ isStreaming() {
293
+ if (this.value.type !== "loaded") {
294
+ return false;
295
+ }
296
+
297
+ return this.value.value._raw.core.verified.isStreaming();
298
+ }
299
+
300
+ isFileStream() {
301
+ if (this.value.type !== "loaded") {
302
+ return false;
303
+ }
304
+
305
+ return this.value.value._raw.core.verified.header.meta?.type === "binary";
306
+ }
307
+
288
308
  triggerUpdate() {
289
309
  if (!this.shouldSendUpdates()) return;
290
310
  if (!this.dirty) return;
@@ -19,7 +19,10 @@ import {
19
19
  randomSessionProvider,
20
20
  } from "./internal.js";
21
21
 
22
- const syncServer: { current: LocalNode | null } = { current: null };
22
+ const syncServer: { current: LocalNode | null; asyncPeers: boolean } = {
23
+ current: null,
24
+ asyncPeers: false,
25
+ };
23
26
 
24
27
  export class TestJSCrypto extends PureJSCrypto {
25
28
  static async create() {
@@ -57,6 +60,23 @@ export function getPeerConnectedToTestSyncServer() {
57
60
  peer2role: "server",
58
61
  },
59
62
  );
63
+
64
+ if (syncServer.asyncPeers) {
65
+ const push = aPeer.outgoing.push;
66
+
67
+ aPeer.outgoing.push = (message) => {
68
+ setTimeout(() => {
69
+ push.call(aPeer.outgoing, message);
70
+ });
71
+ };
72
+
73
+ bPeer.outgoing.push = (message) => {
74
+ setTimeout(() => {
75
+ push.call(bPeer.outgoing, message);
76
+ });
77
+ };
78
+ }
79
+
60
80
  syncServer.current.syncManager.addPeer(aPeer);
61
81
 
62
82
  return bPeer;
@@ -283,7 +303,9 @@ export async function linkAccounts(
283
303
  await b.waitForAllCoValuesSync();
284
304
  }
285
305
 
286
- export async function setupJazzTestSync() {
306
+ export async function setupJazzTestSync({
307
+ asyncPeers = false,
308
+ }: { asyncPeers?: boolean } = {}) {
287
309
  if (syncServer.current) {
288
310
  syncServer.current.gracefulShutdown();
289
311
  }
@@ -296,6 +318,7 @@ export async function setupJazzTestSync() {
296
318
  });
297
319
 
298
320
  syncServer.current = account._raw.core.node;
321
+ syncServer.asyncPeers = asyncPeers;
299
322
 
300
323
  return account;
301
324
  }