jazz-tools 0.18.23 → 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 (116) 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 +65 -65
  4. package/CHANGELOG.md +25 -0
  5. package/dist/browser/index.js +9 -9
  6. package/dist/browser/index.js.map +1 -1
  7. package/dist/{chunk-D5L6ES2M.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/hooks.d.ts +1 -1
  20. package/dist/react/hooks.d.ts.map +1 -1
  21. package/dist/react/index.d.ts +2 -1
  22. package/dist/react/index.d.ts.map +1 -1
  23. package/dist/react/index.js +17 -3
  24. package/dist/react/index.js.map +1 -1
  25. package/dist/react/provider.d.ts +2 -1
  26. package/dist/react/provider.d.ts.map +1 -1
  27. package/dist/react/ssr.js +1 -1
  28. package/dist/react/ssr.js.map +1 -1
  29. package/dist/react-core/hooks.d.ts +13 -0
  30. package/dist/react-core/hooks.d.ts.map +1 -1
  31. package/dist/react-core/index.d.ts +2 -0
  32. package/dist/react-core/index.d.ts.map +1 -1
  33. package/dist/react-core/index.js +104 -0
  34. package/dist/react-core/index.js.map +1 -1
  35. package/dist/react-core/subscription-provider.d.ts +27 -0
  36. package/dist/react-core/subscription-provider.d.ts.map +1 -0
  37. package/dist/react-core/tests/subscription.bench.d.ts +2 -0
  38. package/dist/react-core/tests/subscription.bench.d.ts.map +1 -0
  39. package/dist/react-core/tests/useSubscriptionSelector.test.d.ts +2 -0
  40. package/dist/react-core/tests/useSubscriptionSelector.test.d.ts.map +1 -0
  41. package/dist/react-core/types.d.ts +10 -0
  42. package/dist/react-core/types.d.ts.map +1 -0
  43. package/dist/react-native-core/hooks.d.ts +1 -1
  44. package/dist/react-native-core/hooks.d.ts.map +1 -1
  45. package/dist/react-native-core/index.d.ts +1 -0
  46. package/dist/react-native-core/index.d.ts.map +1 -1
  47. package/dist/react-native-core/index.js +25 -12
  48. package/dist/react-native-core/index.js.map +1 -1
  49. package/dist/react-native-core/provider.d.ts +2 -1
  50. package/dist/react-native-core/provider.d.ts.map +1 -1
  51. package/dist/svelte/Provider.svelte +2 -0
  52. package/dist/svelte/Provider.svelte.d.ts.map +1 -1
  53. package/dist/testing.js +4 -4
  54. package/dist/testing.js.map +1 -1
  55. package/dist/tools/auth/AuthSecretStorage.d.ts +3 -1
  56. package/dist/tools/auth/AuthSecretStorage.d.ts.map +1 -1
  57. package/dist/tools/coValues/account.d.ts +3 -3
  58. package/dist/tools/coValues/account.d.ts.map +1 -1
  59. package/dist/tools/coValues/group.d.ts +20 -1
  60. package/dist/tools/coValues/group.d.ts.map +1 -1
  61. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  62. package/dist/tools/implementation/ContextManager.d.ts +1 -0
  63. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  64. package/dist/tools/implementation/createContext.d.ts +7 -7
  65. package/dist/tools/implementation/createContext.d.ts.map +1 -1
  66. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +3 -8
  67. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  68. package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts +5 -0
  69. package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts.map +1 -1
  70. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  71. package/dist/tools/ssr.js +1 -1
  72. package/dist/tools/testing.d.ts.map +1 -1
  73. package/dist/worker/index.js +3 -3
  74. package/dist/worker/index.js.map +1 -1
  75. package/package.json +5 -4
  76. package/src/better-auth/database-adapter/tests/sync-utils.ts +1 -1
  77. package/src/browser/createBrowserContext.ts +9 -9
  78. package/src/browser/tests/utils.ts +2 -2
  79. package/src/inspector/viewer/use-open-inspector.ts +1 -0
  80. package/src/inspector/viewer/use-page-path.ts +1 -0
  81. package/src/react/hooks.tsx +3 -0
  82. package/src/react/index.ts +9 -0
  83. package/src/react/provider.tsx +3 -0
  84. package/src/react-core/hooks.ts +37 -5
  85. package/src/react-core/index.ts +2 -0
  86. package/src/react-core/subscription-provider.tsx +144 -0
  87. package/src/react-core/tests/subscription.bench.tsx +319 -0
  88. package/src/react-core/tests/useSubscriptionSelector.test.ts +250 -0
  89. package/src/react-core/types.ts +19 -0
  90. package/src/react-native-core/hooks.tsx +3 -0
  91. package/src/react-native-core/index.ts +6 -0
  92. package/src/react-native-core/platform.ts +9 -9
  93. package/src/react-native-core/provider.tsx +3 -1
  94. package/src/svelte/Provider.svelte +2 -0
  95. package/src/tools/auth/AuthSecretStorage.ts +16 -9
  96. package/src/tools/coValues/account.ts +5 -5
  97. package/src/tools/coValues/group.ts +33 -0
  98. package/src/tools/coValues/interfaces.ts +4 -1
  99. package/src/tools/implementation/ContextManager.ts +7 -3
  100. package/src/tools/implementation/createContext.ts +12 -12
  101. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +5 -5
  102. package/src/tools/implementation/zodSchema/schemaTypes/GroupSchema.ts +7 -1
  103. package/src/tools/ssr/ssr.ts +1 -1
  104. package/src/tools/testing.ts +3 -3
  105. package/src/tools/tests/AuthSecretStorage.test.ts +59 -1
  106. package/src/tools/tests/ContextManager.test.ts +11 -1
  107. package/src/tools/tests/account.test.ts +16 -0
  108. package/src/tools/tests/coPlainText.test.ts +2 -2
  109. package/src/tools/tests/createContext.test.ts +19 -19
  110. package/src/tools/tests/deepLoading.test.ts +2 -2
  111. package/src/tools/tests/group.test.ts +59 -0
  112. package/src/tools/tests/inbox.test.ts +2 -2
  113. package/src/tools/tests/utils.ts +3 -3
  114. package/src/worker/index.ts +3 -3
  115. package/dist/chunk-BOMSRY5H.js.map +0 -1
  116. package/dist/chunk-D5L6ES2M.js.map +0 -1
@@ -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
+ });
@@ -0,0 +1,250 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { cojsonInternals } from "cojson";
4
+ import { co, z } from "jazz-tools";
5
+ import { beforeEach, describe, expect, expectTypeOf, it } from "vitest";
6
+ import {
7
+ useCoValueSubscription,
8
+ useAccountSubscription,
9
+ useSubscriptionSelector,
10
+ } from "../index.js";
11
+ import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
12
+ import { act, renderHook, waitFor } from "./testUtils.js";
13
+ import { useRef } from "react";
14
+
15
+ beforeEach(async () => {
16
+ await setupJazzTestSync();
17
+
18
+ await createJazzTestAccount({
19
+ isCurrentActiveAccount: true,
20
+ });
21
+ });
22
+
23
+ cojsonInternals.setCoValueLoadingRetryDelay(300);
24
+
25
+ const useRenderCount = <T>(hook: () => T) => {
26
+ const renderCountRef = useRef(0);
27
+ const result = hook();
28
+ renderCountRef.current = renderCountRef.current + 1;
29
+ return {
30
+ renderCount: renderCountRef.current,
31
+ result,
32
+ };
33
+ };
34
+
35
+ describe("useSubscriptionSelector", () => {
36
+ it("should return coValue", () => {
37
+ const TestMap = co.map({
38
+ value: z.string(),
39
+ });
40
+
41
+ const map = TestMap.create({
42
+ value: "123",
43
+ });
44
+
45
+ const { result } = renderHook(() => {
46
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
47
+ return useSubscriptionSelector(subscription);
48
+ });
49
+
50
+ expect(result.current?.value).toBe("123");
51
+ });
52
+
53
+ it("should resolve nested coValues", () => {
54
+ const TestNestedMap = co.map({
55
+ content: z.string(),
56
+ });
57
+
58
+ const TestMap = co.map({
59
+ content: z.string(),
60
+ nested: TestNestedMap,
61
+ });
62
+
63
+ const map = TestMap.create({
64
+ content: "123",
65
+ nested: {
66
+ content: "456",
67
+ },
68
+ });
69
+
70
+ const { result } = renderHook(() => {
71
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
72
+ return useSubscriptionSelector(subscription);
73
+ });
74
+
75
+ expect(result.current?.nested?.content).toBe("456");
76
+ });
77
+
78
+ it("should return null on invalid coValue id", async () => {
79
+ const TestMap = co.map({
80
+ value: z.string(),
81
+ });
82
+
83
+ const { result } = renderHook(() => {
84
+ const subscription = useCoValueSubscription(TestMap, "123");
85
+ return useSubscriptionSelector(subscription);
86
+ });
87
+
88
+ expect(result.current).toBeUndefined();
89
+
90
+ await waitFor(() => {
91
+ expect(result.current).toBeNull();
92
+ });
93
+ });
94
+
95
+ it("should return coAccount", async () => {
96
+ const account = await createJazzTestAccount();
97
+
98
+ const { result } = renderHook(
99
+ () => {
100
+ const subscription = useAccountSubscription(co.account());
101
+ return useSubscriptionSelector(subscription);
102
+ },
103
+ {
104
+ account,
105
+ },
106
+ );
107
+
108
+ expect(result.current?.$jazz.id).toBe(account.$jazz.id);
109
+ });
110
+
111
+ it("should return value from coValue with selector", () => {
112
+ const TestMap = co.map({
113
+ value: z.string(),
114
+ });
115
+
116
+ const map = TestMap.create({
117
+ value: "123",
118
+ });
119
+
120
+ const { result } = renderHook(() => {
121
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
122
+ return useSubscriptionSelector(subscription, {
123
+ select: (v) => v?.value,
124
+ });
125
+ });
126
+
127
+ expect(result.current).toBe("123");
128
+ });
129
+
130
+ it("should return value from coAccount with selector", async () => {
131
+ const account = await createJazzTestAccount({
132
+ creationProps: { name: "test" },
133
+ });
134
+
135
+ const { result } = renderHook(
136
+ () => {
137
+ const subscription = useAccountSubscription(co.account());
138
+ return useSubscriptionSelector(subscription, {
139
+ select: (v) => v?.profile?.name,
140
+ });
141
+ },
142
+ {
143
+ account,
144
+ },
145
+ );
146
+
147
+ expect(result.current).toBe("test");
148
+ });
149
+
150
+ it("should update value from coValue with selected value changes", () => {
151
+ const TestMap = co.map({
152
+ value: z.string(),
153
+ });
154
+
155
+ const map = TestMap.create({
156
+ value: "123",
157
+ });
158
+
159
+ const { result } = renderHook(() => {
160
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
161
+ return useSubscriptionSelector(subscription, {
162
+ select: (v) => v?.value,
163
+ });
164
+ });
165
+
166
+ expect(result.current).toBe("123");
167
+
168
+ act(() => {
169
+ map.$jazz.set("value", "456");
170
+ });
171
+
172
+ expect(result.current).toBe("456");
173
+ });
174
+
175
+ it("should not re-render when a non-selected field is updated and not selected", () => {
176
+ const TestMap = co.map({
177
+ value: z.string(),
178
+ other: z.string(),
179
+ });
180
+
181
+ const map = TestMap.create({
182
+ value: "1",
183
+ other: "1",
184
+ });
185
+
186
+ const { result } = renderHook(() =>
187
+ useRenderCount(() => {
188
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
189
+ return useSubscriptionSelector(subscription, {
190
+ select: (v) => v?.value,
191
+ });
192
+ }),
193
+ );
194
+
195
+ expect(result.current.result).toBe("1");
196
+ expect(result.current.renderCount).toBe(1);
197
+
198
+ act(() => {
199
+ map.$jazz.set("other", "2");
200
+ });
201
+
202
+ expect(result.current.result).toBe("1");
203
+ expect(result.current.renderCount).toBe(1);
204
+ });
205
+
206
+ it("should only re-render or load new value when equalityFn returns true", () => {
207
+ const TestMap = co.map({
208
+ value: z.number(),
209
+ other: z.number(),
210
+ });
211
+
212
+ const map = TestMap.create({
213
+ value: 1,
214
+ other: 2,
215
+ });
216
+
217
+ const { result } = renderHook(() =>
218
+ useRenderCount(() => {
219
+ const subscription = useCoValueSubscription(TestMap, map.$jazz.id);
220
+ return useSubscriptionSelector(subscription, {
221
+ select: (v) =>
222
+ v
223
+ ? [Math.floor(v.value / 5), Math.floor(v.other / 5)].toSorted()
224
+ : [],
225
+ equalityFn: (a, b) => a.every((v, i) => v === b[i]),
226
+ });
227
+ }),
228
+ );
229
+
230
+ expect(result.current.result).toEqual([0, 0]);
231
+ expect(result.current.renderCount).toBe(1);
232
+
233
+ act(() => {
234
+ map.$jazz.applyDiff({
235
+ value: 3,
236
+ other: 4,
237
+ });
238
+ });
239
+
240
+ expect(result.current.result).toEqual([0, 0]);
241
+ expect(result.current.renderCount).toBe(1);
242
+
243
+ act(() => {
244
+ map.$jazz.set("value", 5);
245
+ });
246
+
247
+ expect(result.current.result).toEqual([0, 1]);
248
+ expect(result.current.renderCount).toBe(2);
249
+ });
250
+ });
@@ -0,0 +1,19 @@
1
+ import {
2
+ CoValueClassOrSchema,
3
+ ResolveQuery,
4
+ SubscriptionScope,
5
+ } from "jazz-tools";
6
+
7
+ declare const subscriptionTag: unique symbol;
8
+
9
+ export type CoValueSubscription<
10
+ S extends CoValueClassOrSchema,
11
+ R extends ResolveQuery<S>,
12
+ > =
13
+ | (SubscriptionScope<any> & {
14
+ [subscriptionTag]: {
15
+ schema: S;
16
+ resolve: R;
17
+ };
18
+ })
19
+ | null;
@@ -16,6 +16,9 @@ export {
16
16
  useCoStateWithSelector,
17
17
  useAccountWithSelector,
18
18
  useSyncConnectionStatus,
19
+ useCoValueSubscription,
20
+ useAccountSubscription,
21
+ useSubscriptionSelector,
19
22
  } from "jazz-tools/react-core";
20
23
 
21
24
  export function useAcceptInviteNative<S extends CoValueClassOrSchema>({
@@ -4,6 +4,12 @@ export * from "./provider.js";
4
4
  export * from "./storage/kv-store-context.js";
5
5
  export * from "./media/image.js";
6
6
 
7
+ export {
8
+ createCoValueSubscriptionContext,
9
+ createAccountSubscriptionContext,
10
+ type CoValueSubscription,
11
+ } from "jazz-tools/react-core";
12
+
7
13
  export { SQLiteDatabaseDriverAsync } from "cojson";
8
14
  export { parseInviteLink } from "jazz-tools";
9
15
  export { createInviteLink, setupKvStore } from "./platform.js";
@@ -46,7 +46,7 @@ async function setupPeers(options: BaseReactNativeContextOptions) {
46
46
  const crypto = await CryptoProvider.create();
47
47
  let node: LocalNode | undefined = undefined;
48
48
 
49
- const peersToLoadFrom: Peer[] = [];
49
+ const peers: Peer[] = [];
50
50
 
51
51
  const storage =
52
52
  options.storage && options.storage !== "disabled"
@@ -58,7 +58,7 @@ async function setupPeers(options: BaseReactNativeContextOptions) {
58
58
  toggleNetwork: () => {},
59
59
  addConnectionListener: () => () => {},
60
60
  connected: () => false,
61
- peersToLoadFrom,
61
+ peers,
62
62
  setNode: () => {},
63
63
  crypto,
64
64
  storage,
@@ -72,11 +72,11 @@ async function setupPeers(options: BaseReactNativeContextOptions) {
72
72
  if (node) {
73
73
  node.syncManager.addPeer(peer);
74
74
  } else {
75
- peersToLoadFrom.push(peer);
75
+ peers.push(peer);
76
76
  }
77
77
  },
78
78
  removePeer: (peer) => {
79
- peersToLoadFrom.splice(peersToLoadFrom.indexOf(peer), 1);
79
+ peers.splice(peers.indexOf(peer), 1);
80
80
  },
81
81
  });
82
82
 
@@ -106,7 +106,7 @@ async function setupPeers(options: BaseReactNativeContextOptions) {
106
106
  };
107
107
  },
108
108
  connected: () => wsPeer.connected,
109
- peersToLoadFrom,
109
+ peers,
110
110
  setNode,
111
111
  crypto,
112
112
  storage,
@@ -118,7 +118,7 @@ export async function createJazzReactNativeGuestContext(
118
118
  ) {
119
119
  const {
120
120
  toggleNetwork,
121
- peersToLoadFrom,
121
+ peers,
122
122
  setNode,
123
123
  crypto,
124
124
  storage,
@@ -128,7 +128,7 @@ export async function createJazzReactNativeGuestContext(
128
128
 
129
129
  const context = createAnonymousJazzContext({
130
130
  crypto,
131
- peersToLoadFrom,
131
+ peers,
132
132
  storage,
133
133
  });
134
134
 
@@ -170,7 +170,7 @@ export async function createJazzReactNativeContext<
170
170
  >(options: ReactNativeContextOptions<S>) {
171
171
  const {
172
172
  toggleNetwork,
173
- peersToLoadFrom,
173
+ peers,
174
174
  setNode,
175
175
  crypto,
176
176
  storage,
@@ -202,7 +202,7 @@ export async function createJazzReactNativeContext<
202
202
  const context = await createJazzContext({
203
203
  credentials: options.credentials,
204
204
  newAccountProps: options.newAccountProps,
205
- peersToLoadFrom,
205
+ peers,
206
206
  crypto,
207
207
  defaultProfileName: options.defaultProfileName,
208
208
  AccountSchema: options.AccountSchema,
@@ -20,6 +20,7 @@ export type JazzProviderProps<
20
20
  > = {
21
21
  children: React.ReactNode;
22
22
  kvStore?: KvStore;
23
+ authSecretStorageKey?: string;
23
24
  } & JazzContextManagerProps<S>;
24
25
 
25
26
  /** @category Context & Hooks */
@@ -39,11 +40,12 @@ export function JazzProviderCore<
39
40
  onAnonymousAccountDiscarded,
40
41
  kvStore,
41
42
  CryptoProvider,
43
+ authSecretStorageKey,
42
44
  }: JazzProviderProps<S>) {
43
45
  setupKvStore(kvStore);
44
46
 
45
47
  const [contextManager] = React.useState(
46
- () => new ReactNativeContextManager<S>(),
48
+ () => new ReactNativeContextManager<S>({ authSecretStorageKey }),
47
49
  );
48
50
 
49
51
  const onLogOutRefCallback = useRefCallback(onLogOut);