jazz-tools 0.18.23 → 0.18.24

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 (47) hide show
  1. package/.turbo/turbo-build.log +58 -58
  2. package/CHANGELOG.md +11 -0
  3. package/dist/{chunk-D5L6ES2M.js → chunk-W7JT3QUN.js} +1 -1
  4. package/dist/{chunk-D5L6ES2M.js.map → chunk-W7JT3QUN.js.map} +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/react/hooks.d.ts +1 -1
  7. package/dist/react/hooks.d.ts.map +1 -1
  8. package/dist/react/index.d.ts +2 -1
  9. package/dist/react/index.d.ts.map +1 -1
  10. package/dist/react/index.js +13 -1
  11. package/dist/react/index.js.map +1 -1
  12. package/dist/react-core/hooks.d.ts +13 -0
  13. package/dist/react-core/hooks.d.ts.map +1 -1
  14. package/dist/react-core/index.d.ts +2 -0
  15. package/dist/react-core/index.d.ts.map +1 -1
  16. package/dist/react-core/index.js +104 -0
  17. package/dist/react-core/index.js.map +1 -1
  18. package/dist/react-core/subscription-provider.d.ts +27 -0
  19. package/dist/react-core/subscription-provider.d.ts.map +1 -0
  20. package/dist/react-core/tests/subscription.bench.d.ts +2 -0
  21. package/dist/react-core/tests/subscription.bench.d.ts.map +1 -0
  22. package/dist/react-core/tests/useSubscriptionSelector.test.d.ts +2 -0
  23. package/dist/react-core/tests/useSubscriptionSelector.test.d.ts.map +1 -0
  24. package/dist/react-core/types.d.ts +10 -0
  25. package/dist/react-core/types.d.ts.map +1 -0
  26. package/dist/react-native-core/hooks.d.ts +1 -1
  27. package/dist/react-native-core/hooks.d.ts.map +1 -1
  28. package/dist/react-native-core/index.d.ts +1 -0
  29. package/dist/react-native-core/index.d.ts.map +1 -1
  30. package/dist/react-native-core/index.js +13 -1
  31. package/dist/react-native-core/index.js.map +1 -1
  32. package/dist/testing.js +1 -1
  33. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +3 -8
  34. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  35. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  36. package/package.json +5 -4
  37. package/src/react/hooks.tsx +3 -0
  38. package/src/react/index.ts +9 -0
  39. package/src/react-core/hooks.ts +37 -5
  40. package/src/react-core/index.ts +2 -0
  41. package/src/react-core/subscription-provider.tsx +144 -0
  42. package/src/react-core/tests/subscription.bench.tsx +319 -0
  43. package/src/react-core/tests/useSubscriptionSelector.test.ts +250 -0
  44. package/src/react-core/types.ts +19 -0
  45. package/src/react-native-core/hooks.tsx +3 -0
  46. package/src/react-native-core/index.ts +6 -0
  47. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"zodCo.d.ts","sourceRoot":"","sources":["../../../../src/tools/implementation/zodSchema/zodCo.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,eAAe,EAWrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAE5B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,cAAc,EAEf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAC;AACrC,OAAO,EAEL,WAAW,EACZ,MAAM,8BAA8B,CAAC;AAiCtC,eAAO,MAAM,YAAY,GAAI,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc,SACvD,KAAK,KACX,WAAW,CAAC,KAAK,CAInB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,gBAAgB,UACtD,KAAK,KAQX,aAAa,CAAC,KAAK,CAGrB,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,WAGjC,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EACnC,CAAC,SAAS,qBAAqB,YAErB,CAAC,aACA,CAAC,KACX,cAAc,CAAC,CAAC,EAAE,CAAC,CAKrB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,qBAAqB,WAClD,CAAC,KACT,YAAY,CAAC,CAAC,CAGhB,CAAC;AAcF,eAAO,MAAM,gBAAgB,GAC3B,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc;UA/BnC,EAAE,IAAG,CAAC,UAAU;WACjB,EACC,IAAG,CAAC,YACH,CAAC,EAAE,IAAI,CAAC,UACN;iBAAiB,EAAG,IACzB,CAAE,YAAW,CAAC,EAAE,IAAI,CAAC,UAAU;WA4BtB,KAAK,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAC1C,eAAe,CAAC,KAAK,CAQvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,qBAAqB,WAClD,CAAC,KACT,YAAY,CAAC,CAAC,CAGhB,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,gBAGtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,eAGrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO,cAGpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,OAAO,eAAe,CAAC;AAC3D,eAAO,MAAM,cAAc,QAAO,qBAEjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,iBAAiB,UACnD,CAAC,KACR,gBAAgB,CAAC,CAAC,CAEpB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,OAAO,SAAS,2BAA2B,iBAE5B,MAAM,WACZ,OAAO,KACf,0BAA0B,CAAC,OAAO,CAMpC,CAAC"}
1
+ {"version":3,"file":"zodCo.d.ts","sourceRoot":"","sources":["../../../../src/tools/implementation/zodSchema/zodCo.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,eAAe,EAWrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAE5B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,cAAc,EAEf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAC;AACrC,OAAO,EAEL,WAAW,EACZ,MAAM,8BAA8B,CAAC;AAiCtC,eAAO,MAAM,YAAY,GAAI,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc,SACvD,KAAK,KACX,WAAW,CAAC,KAAK,CAInB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,gBAAgB,UACtD,KAAK,KAQX,aAAa,CAAC,KAAK,CAGrB,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,WAGjC,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EACnC,CAAC,SAAS,qBAAqB,YAErB,CAAC,aACA,CAAC,KACX,cAAc,CAAC,CAAC,EAAE,CAAC,CAKrB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,qBAAqB,WAClD,CAAC,KACT,YAAY,CAAC,CAAC,CAGhB,CAAC;AAcF,eAAO,MAAM,gBAAgB,GAC3B,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc;UAhCpB,EAAG,IAAI,CAAC,UAAU;WACrB,EAAG,IAAI,CAAC,YAAY,CAClC,EACE,IAAC,CAAC,UAAU;iBAEd,EAAG,IAAI,CAAC,YAAY,CAAC,EAAG,IAAG,CACzB,UAAO;WA4BA,KAAK,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAC1C,eAAe,CAAC,KAAK,CAQvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,qBAAqB,WAClD,CAAC,KACT,YAAY,CAAC,CAAC,CAGhB,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,gBAGtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,eAGrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO,cAGpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,OAAO,eAAe,CAAC;AAC3D,eAAO,MAAM,cAAc,QAAO,qBAEjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,iBAAiB,UACnD,CAAC,KACR,gBAAgB,CAAC,CAAC,CAEpB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,OAAO,SAAS,2BAA2B,iBAE5B,MAAM,WACZ,OAAO,KACf,0BAA0B,CAAC,OAAO,CAMpC,CAAC"}
package/package.json CHANGED
@@ -187,7 +187,7 @@
187
187
  },
188
188
  "type": "module",
189
189
  "license": "MIT",
190
- "version": "0.18.23",
190
+ "version": "0.18.24",
191
191
  "dependencies": {
192
192
  "@manuscripts/prosemirror-recreate-steps": "^0.1.4",
193
193
  "@scure/base": "1.2.1",
@@ -204,9 +204,9 @@
204
204
  "prosemirror-transform": "^1.9.0",
205
205
  "use-sync-external-store": "^1.5.0",
206
206
  "zod": "4.1.11",
207
- "cojson": "0.18.23",
208
- "cojson-storage-indexeddb": "0.18.23",
209
- "cojson-transport-ws": "0.18.23"
207
+ "cojson-storage-indexeddb": "0.18.24",
208
+ "cojson": "0.18.24",
209
+ "cojson-transport-ws": "0.18.24"
210
210
  },
211
211
  "devDependencies": {
212
212
  "@scure/bip39": "^1.3.0",
@@ -302,6 +302,7 @@
302
302
  "format-and-lint": "biome check .",
303
303
  "format-and-lint:fix": "biome check . --write",
304
304
  "dev": "tsup --watch --dts",
305
+ "bench": "vitest bench --run --root ../../ --project jazz-tools",
305
306
  "test": "vitest --run --root ../../ --project jazz-tools",
306
307
  "test:watch": "vitest --watch --root ../../ --project jazz-tools",
307
308
  "types": "tsc --outDir dist",
@@ -53,4 +53,7 @@ export {
53
53
  useCoStateWithSelector,
54
54
  useAccountWithSelector,
55
55
  useSyncConnectionStatus,
56
+ useCoValueSubscription,
57
+ useAccountSubscription,
58
+ useSubscriptionSelector,
56
59
  } from "jazz-tools/react-core";
@@ -10,8 +10,17 @@ export {
10
10
  useCoStateWithSelector,
11
11
  useAccountWithSelector,
12
12
  useSyncConnectionStatus,
13
+ useCoValueSubscription,
14
+ useAccountSubscription,
15
+ useSubscriptionSelector,
13
16
  } from "./hooks.js";
14
17
 
18
+ export {
19
+ createCoValueSubscriptionContext,
20
+ createAccountSubscriptionContext,
21
+ type CoValueSubscription,
22
+ } from "jazz-tools/react-core";
23
+
15
24
  export { createInviteLink, parseInviteLink } from "jazz-tools/browser";
16
25
 
17
26
  export * from "./auth/auth.js";
@@ -13,7 +13,6 @@ import {
13
13
  AnyAccountSchema,
14
14
  CoValue,
15
15
  CoValueClassOrSchema,
16
- Group,
17
16
  InboxSender,
18
17
  InstanceOfSchema,
19
18
  JazzContextManager,
@@ -27,6 +26,7 @@ import {
27
26
  } from "jazz-tools";
28
27
  import { JazzContext, JazzContextManagerContext } from "./provider.js";
29
28
  import { getCurrentAccountFromContextManager } from "./utils.js";
29
+ import { CoValueSubscription } from "./types.js";
30
30
 
31
31
  export function useJazzContext<Acc extends Account>() {
32
32
  const value = useContext(JazzContext) as JazzContextType<Acc>;
@@ -82,7 +82,7 @@ export function useIsAuthenticated() {
82
82
  );
83
83
  }
84
84
 
85
- function useCoValueSubscription<
85
+ export function useCoValueSubscription<
86
86
  S extends CoValueClassOrSchema,
87
87
  const R extends ResolveQuery<S>,
88
88
  >(
@@ -161,7 +161,7 @@ function useCoValueSubscription<
161
161
  });
162
162
  }, [Schema, id, contextManager, branchName, branchOwnerId]);
163
163
 
164
- return subscription.subscription;
164
+ return subscription.subscription as CoValueSubscription<S, R>;
165
165
  }
166
166
 
167
167
  /**
@@ -476,7 +476,39 @@ export function useCoStateWithSelector<
476
476
  );
477
477
  }
478
478
 
479
- function useAccountSubscription<
479
+ export function useSubscriptionSelector<
480
+ S extends CoValueClassOrSchema,
481
+ R extends ResolveQuery<S>,
482
+ TSelectorReturn = Loaded<S, R> | undefined | null,
483
+ >(
484
+ subscription: CoValueSubscription<S, R>,
485
+ options?: {
486
+ select?: (value: Loaded<S, R> | undefined | null) => TSelectorReturn;
487
+ equalityFn?: (a: TSelectorReturn, b: TSelectorReturn) => boolean;
488
+ },
489
+ ) {
490
+ return useSyncExternalStoreWithSelector<
491
+ Loaded<S, R> | undefined | null,
492
+ TSelectorReturn
493
+ >(
494
+ React.useCallback(
495
+ (callback) => {
496
+ if (!subscription) {
497
+ return () => {};
498
+ }
499
+
500
+ return subscription.subscribe(callback);
501
+ },
502
+ [subscription],
503
+ ),
504
+ () => (subscription ? subscription.getCurrentValue() : null),
505
+ () => (subscription ? subscription.getCurrentValue() : null),
506
+ options?.select ?? ((value) => value as TSelectorReturn),
507
+ options?.equalityFn ?? Object.is,
508
+ );
509
+ }
510
+
511
+ export function useAccountSubscription<
480
512
  S extends AccountClass<Account> | AnyAccountSchema,
481
513
  const R extends ResolveQuery<S>,
482
514
  >(
@@ -547,7 +579,7 @@ function useAccountSubscription<
547
579
  });
548
580
  }, [Schema, contextManager, branchName, branchOwnerId]);
549
581
 
550
- return subscription.subscription;
582
+ return subscription.subscription as CoValueSubscription<S, R>;
551
583
  }
552
584
 
553
585
  /**
@@ -1,3 +1,5 @@
1
1
  export * from "./hooks.js";
2
+ export * from "./subscription-provider.js";
2
3
  export * from "./provider.js";
3
4
  export * from "./auth/index.js";
5
+ export type * from "./types.js";
@@ -0,0 +1,144 @@
1
+ import React from "react";
2
+ import {
3
+ Account,
4
+ AccountClass,
5
+ AnyAccountSchema,
6
+ CoValueClassOrSchema,
7
+ Loaded,
8
+ ResolveQuery,
9
+ ResolveQueryStrict,
10
+ } from "jazz-tools";
11
+ import {
12
+ useAccountSubscription,
13
+ useCoValueSubscription,
14
+ useSubscriptionSelector,
15
+ } from "./hooks.js";
16
+ import type { CoValueSubscription } from "./types.js";
17
+
18
+ export function createCoValueSubscriptionContext<
19
+ S extends CoValueClassOrSchema,
20
+ const R extends ResolveQuery<S> = true,
21
+ >(schema: S, resolve?: ResolveQueryStrict<S, R>) {
22
+ const Context = React.createContext<CoValueSubscription<S, R>>(null);
23
+
24
+ return {
25
+ Provider: ({
26
+ id,
27
+ options,
28
+ loadingFallback,
29
+ unavailableFallback,
30
+ children,
31
+ }: React.PropsWithChildren<{
32
+ id: string | undefined | null;
33
+ options?: Omit<
34
+ Parameters<typeof useCoValueSubscription<S, R>>[2],
35
+ "resolve"
36
+ >;
37
+ loadingFallback?: React.ReactNode;
38
+ unavailableFallback?: React.ReactNode;
39
+ }>) => {
40
+ const subscription = useCoValueSubscription(schema, id, {
41
+ ...options,
42
+ resolve: resolve,
43
+ });
44
+
45
+ const loadState = useSubscriptionSelector(subscription, {
46
+ select: (value) => (!value ? value : true),
47
+ });
48
+
49
+ if (loadState === undefined) {
50
+ return loadingFallback ?? null;
51
+ }
52
+
53
+ if (loadState === null) {
54
+ return unavailableFallback ?? null;
55
+ }
56
+
57
+ return (
58
+ <Context.Provider value={subscription}>{children}</Context.Provider>
59
+ );
60
+ },
61
+ useSelector: <TSelectorReturn = Loaded<S, R>>(options?: {
62
+ select?: (value: Loaded<S, R>) => TSelectorReturn;
63
+ equalityFn?: (a: TSelectorReturn, b: TSelectorReturn) => boolean;
64
+ }) => {
65
+ const subscription = React.useContext(Context);
66
+
67
+ if (!subscription) {
68
+ throw new Error(
69
+ "useSelector must be used within a coValue subscription provider",
70
+ );
71
+ }
72
+
73
+ return useSubscriptionSelector<S, R, TSelectorReturn>(
74
+ subscription,
75
+ options as Parameters<
76
+ typeof useSubscriptionSelector<S, R, TSelectorReturn>
77
+ >[1],
78
+ );
79
+ },
80
+ };
81
+ }
82
+
83
+ export function createAccountSubscriptionContext<
84
+ A extends AccountClass<Account> | AnyAccountSchema,
85
+ const R extends ResolveQuery<A> = true,
86
+ >(schema: A, resolve?: ResolveQueryStrict<A, R>) {
87
+ const Context = React.createContext<CoValueSubscription<A, R>>(null);
88
+
89
+ return {
90
+ Provider: ({
91
+ options,
92
+ loadingFallback,
93
+ unavailableFallback,
94
+ children,
95
+ }: React.PropsWithChildren<{
96
+ options?: Omit<
97
+ Parameters<typeof useAccountSubscription<A, R>>[1],
98
+ "resolve"
99
+ >;
100
+ loadingFallback?: React.ReactNode;
101
+ unavailableFallback?: React.ReactNode;
102
+ }>) => {
103
+ const subscription = useAccountSubscription(schema, {
104
+ ...options,
105
+ resolve: resolve,
106
+ });
107
+
108
+ const loadState = useSubscriptionSelector(subscription, {
109
+ select: (value) => (!value ? value : true),
110
+ });
111
+
112
+ if (loadState === undefined) {
113
+ return loadingFallback ?? null;
114
+ }
115
+
116
+ if (loadState === null) {
117
+ return unavailableFallback ?? null;
118
+ }
119
+
120
+ return (
121
+ <Context.Provider value={subscription}>{children}</Context.Provider>
122
+ );
123
+ },
124
+ useSelector: <TSelectorReturn = Loaded<A, R>>(options?: {
125
+ select?: (value: Loaded<A, R>) => TSelectorReturn;
126
+ equalityFn?: (a: TSelectorReturn, b: TSelectorReturn) => boolean;
127
+ }) => {
128
+ const subscription = React.useContext(Context);
129
+
130
+ if (!subscription) {
131
+ throw new Error(
132
+ "useSelector must be used within an account subscription provider",
133
+ );
134
+ }
135
+
136
+ return useSubscriptionSelector<A, R, TSelectorReturn>(
137
+ subscription,
138
+ options as Parameters<
139
+ typeof useSubscriptionSelector<A, R, TSelectorReturn>
140
+ >[1],
141
+ );
142
+ },
143
+ };
144
+ }
@@ -0,0 +1,319 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { cojsonInternals } from "cojson";
4
+ import { co, z } from "jazz-tools";
5
+ import { describe, bench } from "vitest";
6
+ import {
7
+ useAccountSubscription,
8
+ useSubscriptionSelector,
9
+ useAccountWithSelector,
10
+ CoValueSubscription,
11
+ } from "../index.js";
12
+ import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
13
+ import { render } from "./testUtils.js";
14
+
15
+ cojsonInternals.setCoValueLoadingRetryDelay(300);
16
+
17
+ await setupJazzTestSync();
18
+ await createJazzTestAccount({
19
+ isCurrentActiveAccount: true,
20
+ creationProps: { name: "Hermes Puggington" },
21
+ });
22
+
23
+ const AccountSchema = co.account();
24
+
25
+ const AccountName = () => {
26
+ const name = useAccountWithSelector(AccountSchema, {
27
+ resolve: {
28
+ profile: true,
29
+ },
30
+ select: (account) => account?.profile?.name,
31
+ });
32
+
33
+ if (!name) return null;
34
+
35
+ return <span>{name}</span>;
36
+ };
37
+
38
+ const AccountNameFromSubscription = ({
39
+ subscription,
40
+ }: {
41
+ subscription: CoValueSubscription<typeof AccountSchema, { profile: true }>;
42
+ }) => {
43
+ const name = useSubscriptionSelector(subscription, {
44
+ select: (account) => account?.profile?.name,
45
+ });
46
+
47
+ if (!name) return null;
48
+
49
+ return <span>{name}</span>;
50
+ };
51
+
52
+ const UseAccountWithSelector = () => {
53
+ return (
54
+ <div>
55
+ {Array.from({ length: 1000 }).map((_, i) => (
56
+ <AccountName key={i} />
57
+ ))}
58
+ </div>
59
+ );
60
+ };
61
+
62
+ const UseAccountSubscription = () => {
63
+ const subscription = useAccountSubscription(AccountSchema, {
64
+ resolve: {
65
+ profile: true,
66
+ },
67
+ });
68
+
69
+ return (
70
+ <div>
71
+ {Array.from({ length: 1000 }).map((_, i) => (
72
+ <AccountNameFromSubscription key={i} subscription={subscription} />
73
+ ))}
74
+ </div>
75
+ );
76
+ };
77
+
78
+ describe("1000 value loads", () => {
79
+ bench(
80
+ "useAccountSubscription + useSubscriptionSelector",
81
+ () => {
82
+ render(<UseAccountSubscription />);
83
+ },
84
+ { iterations: 50 },
85
+ );
86
+
87
+ bench(
88
+ "useAccountWithSelector",
89
+ () => {
90
+ render(<UseAccountWithSelector />);
91
+ },
92
+ { iterations: 50 },
93
+ );
94
+ });
95
+
96
+ describe("deeply resolved coMaps", async () => {
97
+ const Task = co.map({
98
+ title: z.string(),
99
+ get project() {
100
+ return Project;
101
+ },
102
+ });
103
+
104
+ const TaskList = co.list(Task);
105
+
106
+ const Project = co.map({
107
+ name: z.string(),
108
+ tasks: TaskList,
109
+ draftTasks: TaskList,
110
+ deletedTasks: TaskList,
111
+ });
112
+
113
+ const Organization = co.map({
114
+ name: z.string(),
115
+ projects: co.list(Project),
116
+ });
117
+
118
+ const AccountRoot = co.map({
119
+ organizations: co.list(Organization),
120
+ });
121
+
122
+ const AccountSchema = co
123
+ .account({
124
+ root: AccountRoot,
125
+ profile: co.profile(),
126
+ })
127
+ .withMigration(async (account) => {
128
+ if (!account.$jazz.has("root")) {
129
+ account.$jazz.set("root", {
130
+ organizations: [
131
+ {
132
+ name: "My organization",
133
+ projects: [
134
+ {
135
+ name: "My project",
136
+ tasks: [],
137
+ draftTasks: [],
138
+ deletedTasks: [],
139
+ },
140
+ ],
141
+ },
142
+ ],
143
+ });
144
+ }
145
+ });
146
+
147
+ const account = await createJazzTestAccount({
148
+ AccountSchema,
149
+ isCurrentActiveAccount: true,
150
+ creationProps: { name: "Hermes Puggington" },
151
+ });
152
+
153
+ const root = await account.root.$jazz.ensureLoaded({
154
+ resolve: {
155
+ organizations: {
156
+ $each: {
157
+ projects: {
158
+ $each: true,
159
+ },
160
+ },
161
+ },
162
+ },
163
+ });
164
+
165
+ const project = root.organizations[0]?.projects[0]!;
166
+
167
+ for (let i = 0; i < 250; i++) {
168
+ const taskList = (["tasks", "draftTasks", "deletedTasks"] as const)[i % 3]!;
169
+
170
+ project[taskList].$jazz.push({
171
+ title: `Task ${i}`,
172
+ project,
173
+ });
174
+ }
175
+
176
+ const SingleSubscriptionTasks = ({
177
+ subscription,
178
+ taskListType,
179
+ }: {
180
+ subscription: CoValueSubscription<
181
+ typeof AccountSchema,
182
+ {
183
+ root: {
184
+ organizations: {
185
+ $each: {
186
+ projects: {
187
+ $each: {
188
+ tasks: { $each: { project: true } };
189
+ draftTasks: { $each: { project: true } };
190
+ deletedTasks: { $each: { project: true } };
191
+ };
192
+ };
193
+ };
194
+ };
195
+ };
196
+ }
197
+ >;
198
+ taskListType: "tasks" | "draftTasks" | "deletedTasks";
199
+ }) => {
200
+ const allProjectsTasks = useSubscriptionSelector(subscription, {
201
+ select: (account) => {
202
+ return account?.root.organizations.flatMap((org) =>
203
+ org?.projects.flatMap((project) =>
204
+ project?.[taskListType]?.flatMap((task) => task),
205
+ ),
206
+ );
207
+ },
208
+ });
209
+
210
+ return (
211
+ <div>
212
+ {allProjectsTasks?.map((task) => (
213
+ <div key={task?.$jazz.id}>{task?.title}</div>
214
+ ))}
215
+ </div>
216
+ );
217
+ };
218
+
219
+ const SingleSubscription = () => {
220
+ const subscription = useAccountSubscription(AccountSchema, {
221
+ resolve: {
222
+ root: {
223
+ organizations: {
224
+ $each: {
225
+ projects: {
226
+ $each: {
227
+ tasks: { $each: { project: true } },
228
+ draftTasks: { $each: { project: true } },
229
+ deletedTasks: { $each: { project: true } },
230
+ },
231
+ },
232
+ },
233
+ },
234
+ },
235
+ },
236
+ });
237
+
238
+ return (
239
+ <div>
240
+ <SingleSubscriptionTasks
241
+ subscription={subscription}
242
+ taskListType="tasks"
243
+ />
244
+ <SingleSubscriptionTasks
245
+ subscription={subscription}
246
+ taskListType="draftTasks"
247
+ />
248
+ <SingleSubscriptionTasks
249
+ subscription={subscription}
250
+ taskListType="deletedTasks"
251
+ />
252
+ </div>
253
+ );
254
+ };
255
+
256
+ bench(
257
+ "useAccountSubscription + useSubscriptionSelector",
258
+ () => {
259
+ render(<SingleSubscription />);
260
+ },
261
+ { iterations: 200 },
262
+ );
263
+
264
+ const MultipleSubscriptionTasks = ({
265
+ taskListType,
266
+ }: {
267
+ taskListType: "tasks" | "draftTasks" | "deletedTasks";
268
+ }) => {
269
+ const subscription = useAccountWithSelector(AccountSchema, {
270
+ resolve: {
271
+ root: {
272
+ organizations: {
273
+ $each: {
274
+ projects: {
275
+ $each: {
276
+ tasks: { $each: { project: true } },
277
+ draftTasks: { $each: { project: true } },
278
+ deletedTasks: { $each: { project: true } },
279
+ },
280
+ },
281
+ },
282
+ },
283
+ },
284
+ },
285
+ select: (account) =>
286
+ account?.root.organizations.flatMap((org) =>
287
+ org?.projects.flatMap((project) =>
288
+ project?.[taskListType]?.flatMap((task) => task),
289
+ ),
290
+ ),
291
+ });
292
+
293
+ return (
294
+ <div>
295
+ {subscription?.map((task) => (
296
+ <div key={task?.$jazz.id}>{task?.title}</div>
297
+ ))}
298
+ </div>
299
+ );
300
+ };
301
+
302
+ const MultipleSubscription = () => {
303
+ return (
304
+ <div>
305
+ <MultipleSubscriptionTasks taskListType="tasks" />
306
+ <MultipleSubscriptionTasks taskListType="draftTasks" />
307
+ <MultipleSubscriptionTasks taskListType="deletedTasks" />
308
+ </div>
309
+ );
310
+ };
311
+
312
+ bench(
313
+ "useAccountWithSelector",
314
+ () => {
315
+ render(<MultipleSubscription />);
316
+ },
317
+ { iterations: 200 },
318
+ );
319
+ });