jazz-tools 0.17.14 → 0.18.1

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 (250) hide show
  1. package/.svelte-kit/__package__/jazz.class.svelte.js +1 -1
  2. package/.svelte-kit/__package__/media/image.svelte +3 -9
  3. package/.svelte-kit/__package__/media/image.svelte.d.ts +1 -6
  4. package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
  5. package/.svelte-kit/__package__/media/image.types.d.ts +7 -0
  6. package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -0
  7. package/.svelte-kit/__package__/media/image.types.js +1 -0
  8. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +31 -31
  9. package/.turbo/turbo-build.log +60 -46
  10. package/CHANGELOG.md +41 -0
  11. package/dist/better-auth/auth/client.d.ts +29 -0
  12. package/dist/better-auth/auth/client.d.ts.map +1 -0
  13. package/dist/better-auth/auth/client.js +127 -0
  14. package/dist/better-auth/auth/client.js.map +1 -0
  15. package/dist/better-auth/auth/react.d.ts +2170 -0
  16. package/dist/better-auth/auth/react.d.ts.map +1 -0
  17. package/dist/better-auth/auth/react.js +40 -0
  18. package/dist/better-auth/auth/react.js.map +1 -0
  19. package/dist/better-auth/auth/server.d.ts +14 -0
  20. package/dist/better-auth/auth/server.d.ts.map +1 -0
  21. package/dist/better-auth/auth/server.js +198 -0
  22. package/dist/better-auth/auth/server.js.map +1 -0
  23. package/dist/better-auth/auth/tests/client.test.d.ts +2 -0
  24. package/dist/better-auth/auth/tests/client.test.d.ts.map +1 -0
  25. package/dist/better-auth/auth/tests/server.test.d.ts +2 -0
  26. package/dist/better-auth/auth/tests/server.test.d.ts.map +1 -0
  27. package/dist/browser/index.js +2 -2
  28. package/dist/browser/index.js.map +1 -1
  29. package/dist/{chunk-LZOF6WP5.js → chunk-IERUTUXB.js} +1336 -1017
  30. package/dist/chunk-IERUTUXB.js.map +1 -0
  31. package/dist/index.js +18 -18
  32. package/dist/index.js.map +1 -1
  33. package/dist/inspector/{custom-element-ZSNTCECD.js → custom-element-WCY6D3QJ.js} +3 -3
  34. package/dist/inspector/{custom-element-ZSNTCECD.js.map → custom-element-WCY6D3QJ.js.map} +1 -1
  35. package/dist/inspector/index.js +1 -1
  36. package/dist/inspector/index.js.map +1 -1
  37. package/dist/inspector/register-custom-element.js +1 -1
  38. package/dist/media/{chunk-E5J3WLQW.js → chunk-KR2V6X2N.js} +14 -9
  39. package/dist/media/chunk-KR2V6X2N.js.map +1 -0
  40. package/dist/media/create-image.d.ts +6 -6
  41. package/dist/media/index.browser.d.ts +6 -6
  42. package/dist/media/index.browser.js +1 -1
  43. package/dist/media/index.d.ts +1 -1
  44. package/dist/media/index.js +1 -1
  45. package/dist/media/index.native.d.ts +6 -6
  46. package/dist/media/index.native.js +1 -1
  47. package/dist/media/utils.d.ts.map +1 -1
  48. package/dist/prosemirror/index.js +2 -2
  49. package/dist/prosemirror/index.js.map +1 -1
  50. package/dist/react/index.js +7 -5
  51. package/dist/react/index.js.map +1 -1
  52. package/dist/react-core/hooks.d.ts.map +1 -1
  53. package/dist/react-core/index.js +4675 -23
  54. package/dist/react-core/index.js.map +1 -1
  55. package/dist/react-native-core/index.js +1 -1
  56. package/dist/react-native-core/index.js.map +1 -1
  57. package/dist/svelte/jazz.class.svelte.js +1 -1
  58. package/dist/svelte/media/image.svelte +3 -9
  59. package/dist/svelte/media/image.svelte.d.ts +1 -6
  60. package/dist/svelte/media/image.svelte.d.ts.map +1 -1
  61. package/dist/svelte/media/image.types.d.ts +7 -0
  62. package/dist/svelte/media/image.types.d.ts.map +1 -0
  63. package/dist/svelte/media/image.types.js +1 -0
  64. package/dist/svelte/tests/media/image.svelte.test.js +31 -31
  65. package/dist/testing.js +18 -14
  66. package/dist/testing.js.map +1 -1
  67. package/dist/tools/coValues/CoFieldInit.d.ts +13 -0
  68. package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -0
  69. package/dist/tools/coValues/CoValueBase.d.ts +18 -15
  70. package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
  71. package/dist/tools/coValues/account.d.ts +101 -46
  72. package/dist/tools/coValues/account.d.ts.map +1 -1
  73. package/dist/tools/coValues/coFeed.d.ts +78 -62
  74. package/dist/tools/coValues/coFeed.d.ts.map +1 -1
  75. package/dist/tools/coValues/coList.d.ts +212 -99
  76. package/dist/tools/coValues/coList.d.ts.map +1 -1
  77. package/dist/tools/coValues/coMap.d.ts +210 -192
  78. package/dist/tools/coValues/coMap.d.ts.map +1 -1
  79. package/dist/tools/coValues/coPlainText.d.ts +30 -22
  80. package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
  81. package/dist/tools/coValues/deepLoading.d.ts +13 -13
  82. package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
  83. package/dist/tools/coValues/extensions/imageDef.d.ts +1 -1
  84. package/dist/tools/coValues/group.d.ts +32 -32
  85. package/dist/tools/coValues/group.d.ts.map +1 -1
  86. package/dist/tools/coValues/inbox.d.ts.map +1 -1
  87. package/dist/tools/coValues/interfaces.d.ts +18 -17
  88. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  89. package/dist/tools/coValues/profile.d.ts +6 -5
  90. package/dist/tools/coValues/profile.d.ts.map +1 -1
  91. package/dist/tools/coValues/schemaUnion.d.ts +3 -3
  92. package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
  93. package/dist/tools/exports.d.ts +1 -1
  94. package/dist/tools/exports.d.ts.map +1 -1
  95. package/dist/tools/implementation/anonymousJazzAgent.d.ts +2 -1
  96. package/dist/tools/implementation/anonymousJazzAgent.d.ts.map +1 -1
  97. package/dist/tools/implementation/schema.d.ts +5 -5
  98. package/dist/tools/implementation/schema.d.ts.map +1 -1
  99. package/dist/tools/implementation/symbols.d.ts +2 -0
  100. package/dist/tools/implementation/symbols.d.ts.map +1 -1
  101. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +2 -2
  102. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  103. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +6 -2
  104. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  105. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +8 -3
  106. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  107. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +12 -7
  108. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  109. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +13 -7
  110. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
  111. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +11 -2
  112. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
  113. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +4 -0
  114. package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
  115. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +4 -0
  116. package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
  117. package/dist/tools/implementation/zodSchema/typeConverters/{CoFieldInit.d.ts → CoFieldSchemaInit.d.ts} +7 -7
  118. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -0
  119. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +4 -4
  120. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
  121. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +4 -4
  122. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
  123. package/dist/tools/implementation/zodSchema/zodCo.d.ts +3 -3
  124. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  125. package/dist/tools/internal.d.ts +2 -1
  126. package/dist/tools/internal.d.ts.map +1 -1
  127. package/dist/tools/lib/migration.d.ts +1 -1
  128. package/dist/tools/lib/migration.d.ts.map +1 -1
  129. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  130. package/dist/tools/subscribe/index.d.ts +1 -1
  131. package/dist/tools/subscribe/index.d.ts.map +1 -1
  132. package/dist/tools/subscribe/utils.d.ts +2 -2
  133. package/dist/tools/subscribe/utils.d.ts.map +1 -1
  134. package/dist/tools/testing.d.ts.map +1 -1
  135. package/dist/tools/tests/utils.d.ts +2 -6
  136. package/dist/tools/tests/utils.d.ts.map +1 -1
  137. package/dist/worker/index.js +3 -3
  138. package/dist/worker/index.js.map +1 -1
  139. package/package.json +23 -4
  140. package/src/better-auth/auth/client.ts +169 -0
  141. package/src/better-auth/auth/react.tsx +105 -0
  142. package/src/better-auth/auth/server.ts +250 -0
  143. package/src/better-auth/auth/tests/client.test.ts +249 -0
  144. package/src/better-auth/auth/tests/server.test.ts +226 -0
  145. package/src/browser/auth/PasskeyAuth.ts +2 -2
  146. package/src/browser/createBrowserContext.ts +2 -2
  147. package/src/browser/tests/PasskeyAuth.test.ts +2 -2
  148. package/src/inspector/custom-element.tsx +2 -2
  149. package/src/inspector/viewer/new-app.tsx +1 -1
  150. package/src/media/create-image.test.ts +7 -7
  151. package/src/media/create-image.ts +5 -3
  152. package/src/media/index.ts +1 -1
  153. package/src/media/utils.test.ts +72 -66
  154. package/src/media/utils.ts +9 -6
  155. package/src/prosemirror/lib/plugin.ts +1 -1
  156. package/src/prosemirror/lib/sync.ts +1 -1
  157. package/src/prosemirror/tests/plugin.test.ts +4 -4
  158. package/src/react/media/image.tsx +2 -2
  159. package/src/react/tests/media/image.test.tsx +52 -32
  160. package/src/react-core/hooks.ts +11 -5
  161. package/src/react-core/tests/useAccount.test.ts +16 -22
  162. package/src/react-core/tests/useCoState.test.ts +19 -19
  163. package/src/react-core/tests/useInboxSender.test.ts +5 -2
  164. package/src/react-core/tests/usePassPhraseAuth.test.ts +6 -6
  165. package/src/react-native-core/media/image.tsx +1 -1
  166. package/src/svelte/jazz.class.svelte.ts +1 -1
  167. package/src/svelte/media/image.svelte +3 -9
  168. package/src/svelte/media/image.types.ts +7 -0
  169. package/src/svelte/tests/media/image.svelte.test.ts +34 -32
  170. package/src/tools/auth/DemoAuth.ts +2 -2
  171. package/src/tools/auth/PassphraseAuth.ts +2 -2
  172. package/src/tools/auth/clerk/index.ts +2 -2
  173. package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +1 -1
  174. package/src/tools/coValues/CoFieldInit.ts +20 -0
  175. package/src/tools/coValues/CoValueBase.ts +40 -60
  176. package/src/tools/coValues/account.ts +311 -232
  177. package/src/tools/coValues/coFeed.ts +185 -153
  178. package/src/tools/coValues/coList.ts +507 -334
  179. package/src/tools/coValues/coMap.ts +434 -286
  180. package/src/tools/coValues/coPlainText.ts +94 -110
  181. package/src/tools/coValues/deepLoading.ts +13 -13
  182. package/src/tools/coValues/group.ts +100 -114
  183. package/src/tools/coValues/inbox.ts +16 -14
  184. package/src/tools/coValues/interfaces.ts +49 -31
  185. package/src/tools/coValues/profile.ts +8 -6
  186. package/src/tools/coValues/request.ts +9 -9
  187. package/src/tools/coValues/schemaUnion.ts +11 -5
  188. package/src/tools/exports.ts +1 -1
  189. package/src/tools/implementation/ContextManager.ts +4 -4
  190. package/src/tools/implementation/anonymousJazzAgent.ts +2 -1
  191. package/src/tools/implementation/createContext.ts +1 -1
  192. package/src/tools/implementation/devtoolsFormatters.ts +9 -9
  193. package/src/tools/implementation/invites.ts +2 -2
  194. package/src/tools/implementation/schema.ts +7 -7
  195. package/src/tools/implementation/symbols.ts +3 -0
  196. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -2
  197. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +11 -2
  198. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +18 -7
  199. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +17 -7
  200. package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +20 -11
  201. package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +19 -2
  202. package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +6 -0
  203. package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +6 -0
  204. package/src/tools/implementation/zodSchema/typeConverters/{CoFieldInit.ts → CoFieldSchemaInit.ts} +11 -11
  205. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +4 -4
  206. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +4 -4
  207. package/src/tools/implementation/zodSchema/zodCo.ts +3 -3
  208. package/src/tools/internal.ts +2 -1
  209. package/src/tools/lib/migration.ts +5 -5
  210. package/src/tools/subscribe/SubscriptionScope.ts +32 -24
  211. package/src/tools/subscribe/index.ts +4 -4
  212. package/src/tools/subscribe/utils.ts +11 -11
  213. package/src/tools/testing.ts +17 -13
  214. package/src/tools/tests/ContextManager.test.ts +70 -59
  215. package/src/tools/tests/PassphraseAuth.test.ts +2 -2
  216. package/src/tools/tests/account.test.ts +188 -67
  217. package/src/tools/tests/coDiscriminatedUnion.test-d.ts +12 -6
  218. package/src/tools/tests/coDiscriminatedUnion.test.ts +26 -17
  219. package/src/tools/tests/coFeed.test-d.ts +18 -17
  220. package/src/tools/tests/coFeed.test.ts +108 -97
  221. package/src/tools/tests/coList.test-d.ts +18 -23
  222. package/src/tools/tests/coList.test.ts +350 -165
  223. package/src/tools/tests/coMap.record.test-d.ts +9 -13
  224. package/src/tools/tests/coMap.record.test.ts +37 -23
  225. package/src/tools/tests/coMap.test-d.ts +43 -21
  226. package/src/tools/tests/coMap.test.ts +459 -182
  227. package/src/tools/tests/coOptional.test.ts +28 -13
  228. package/src/tools/tests/coPlainText.test.ts +15 -15
  229. package/src/tools/tests/createContext.test.ts +14 -14
  230. package/src/tools/tests/deepLoading.test.ts +95 -94
  231. package/src/tools/tests/exportImport.test.ts +61 -41
  232. package/src/tools/tests/groupsAndAccounts.test.ts +333 -116
  233. package/src/tools/tests/inbox.test.ts +22 -17
  234. package/src/tools/tests/interfaces.test.ts +12 -11
  235. package/src/tools/tests/invites.test.ts +6 -4
  236. package/src/tools/tests/load.test.ts +20 -18
  237. package/src/tools/tests/patterns/notifications.test.ts +7 -7
  238. package/src/tools/tests/patterns/quest.test.ts +3 -3
  239. package/src/tools/tests/patterns/requestToJoin.test.ts +22 -22
  240. package/src/tools/tests/request.test.ts +38 -39
  241. package/src/tools/tests/schemaUnion.test.ts +64 -10
  242. package/src/tools/tests/subscribe.test.ts +64 -64
  243. package/src/tools/tests/testing.test.ts +7 -11
  244. package/src/tools/tests/utils.ts +3 -3
  245. package/src/tools/tests/zod.test.ts +3 -3
  246. package/src/worker/index.ts +3 -3
  247. package/tsup.config.ts +9 -0
  248. package/dist/chunk-LZOF6WP5.js.map +0 -1
  249. package/dist/media/chunk-E5J3WLQW.js.map +0 -1
  250. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts.map +0 -1
@@ -0,0 +1,249 @@
1
+ import { createAuthClient } from "better-auth/client";
2
+ import type { Account, AuthSecretStorage } from "jazz-tools";
3
+ import {
4
+ TestJazzContextManager,
5
+ setActiveAccount,
6
+ setupJazzTestSync,
7
+ } from "jazz-tools/testing";
8
+ import { assert, beforeEach, describe, expect, it, vi } from "vitest";
9
+ import { jazzPluginClient } from "../client.js";
10
+
11
+ describe("auth client", () => {
12
+ let account: Account;
13
+ let jazzContextManager: TestJazzContextManager<Account>;
14
+ let authSecretStorage: AuthSecretStorage;
15
+ let authClient: ReturnType<
16
+ typeof createAuthClient<{
17
+ plugins: ReturnType<typeof jazzPluginClient>[];
18
+ }>
19
+ >;
20
+ let customFetchImpl = vi.fn();
21
+
22
+ beforeEach(async () => {
23
+ account = await setupJazzTestSync();
24
+ setActiveAccount(account);
25
+
26
+ jazzContextManager = TestJazzContextManager.fromAccountOrGuest(account);
27
+ authSecretStorage = jazzContextManager.getAuthSecretStorage();
28
+
29
+ // start a new context
30
+ await jazzContextManager.createContext({});
31
+
32
+ authClient = createAuthClient({
33
+ baseURL: "http://localhost:3000",
34
+ plugins: [jazzPluginClient()],
35
+ fetchOptions: {
36
+ customFetchImpl,
37
+ },
38
+ });
39
+
40
+ const context = jazzContextManager.getCurrentValue();
41
+ assert(context, "Jazz context is not available");
42
+ authClient.jazz.setJazzContext(context);
43
+ authClient.jazz.setAuthSecretStorage(authSecretStorage);
44
+
45
+ customFetchImpl.mockReset();
46
+ });
47
+
48
+ it("should send Jazz credentials over signup", async () => {
49
+ const credentials = await authSecretStorage.get();
50
+ expect(authSecretStorage.isAuthenticated).toBe(false);
51
+ assert(credentials, "Jazz credentials are not available");
52
+
53
+ customFetchImpl.mockResolvedValue(
54
+ new Response(
55
+ JSON.stringify({
56
+ token: "6diDScDDcLJLl3sxAEestZz63mrw9Azy",
57
+ user: {
58
+ id: "S6SDKApdnh746gUnP3zujzsEY53tjuTm",
59
+ email: "test@jazz.dev",
60
+ name: "Matteo",
61
+ image: null,
62
+ emailVerified: false,
63
+ createdAt: new Date(),
64
+ updatedAt: new Date(),
65
+ },
66
+ jazzAuth: {
67
+ accountID: credentials.accountID,
68
+ secretSeed: credentials.secretSeed,
69
+ accountSecret: credentials.accountSecret,
70
+ },
71
+ }),
72
+ ),
73
+ );
74
+
75
+ // Sign up
76
+ await authClient.signUp.email({
77
+ email: "test@jazz.dev",
78
+ password: "12345678",
79
+ name: "Matteo",
80
+ });
81
+
82
+ expect(customFetchImpl).toHaveBeenCalledTimes(1);
83
+ expect(customFetchImpl.mock.calls[0]![0].toString()).toBe(
84
+ "http://localhost:3000/api/auth/sign-up/email",
85
+ );
86
+
87
+ // Verify the credentials have been injected in the request body
88
+ expect(
89
+ customFetchImpl.mock.calls[0]![1].headers.get("x-jazz-auth")!,
90
+ ).toEqual(
91
+ JSON.stringify({
92
+ accountID: credentials!.accountID,
93
+ secretSeed: credentials!.secretSeed,
94
+ accountSecret: credentials!.accountSecret,
95
+ }),
96
+ );
97
+
98
+ expect(authSecretStorage.isAuthenticated).toBe(true);
99
+
100
+ // Verify the profile name has been updated
101
+ const context = jazzContextManager.getCurrentValue();
102
+ assert(context && "me" in context);
103
+ expect(context.me.$jazz.id).toBe(credentials!.accountID);
104
+ });
105
+
106
+ it("should become logged in Jazz credentials after sign-in", async () => {
107
+ const credentials = await jazzContextManager.getAuthSecretStorage().get();
108
+
109
+ // Log out from initial context
110
+ await jazzContextManager.logOut();
111
+ expect(authSecretStorage.isAuthenticated).toBe(false);
112
+
113
+ customFetchImpl.mockResolvedValue(
114
+ new Response(
115
+ JSON.stringify({
116
+ user: {
117
+ id: "123",
118
+ email: "test@jazz.dev",
119
+ name: "Matteo",
120
+ },
121
+ jazzAuth: {
122
+ accountID: credentials!.accountID,
123
+ secretSeed: credentials!.secretSeed,
124
+ accountSecret: credentials!.accountSecret,
125
+ provider: "better-auth",
126
+ },
127
+ }),
128
+ ),
129
+ );
130
+
131
+ // Retrieve the BetterAuth session and trigger the authentication
132
+ await authClient.signIn.email({
133
+ email: "test@jazz.dev",
134
+ password: "12345678",
135
+ });
136
+
137
+ expect(customFetchImpl).toHaveBeenCalledTimes(1);
138
+ expect(customFetchImpl.mock.calls[0]![0].toString()).toBe(
139
+ "http://localhost:3000/api/auth/sign-in/email",
140
+ );
141
+
142
+ expect(authSecretStorage.isAuthenticated).toBe(true);
143
+
144
+ const newContext = jazzContextManager.getCurrentValue()!;
145
+ expect("me" in newContext).toBe(true);
146
+ expect(await authSecretStorage.get()).toMatchObject({
147
+ accountID: credentials!.accountID,
148
+ provider: "better-auth",
149
+ });
150
+ });
151
+
152
+ it("should logout from Jazz after BetterAuth sign-out", async () => {
153
+ const credentials = await authSecretStorage.get();
154
+ expect(authSecretStorage.isAuthenticated).toBe(false);
155
+ customFetchImpl.mockResolvedValueOnce(
156
+ new Response(
157
+ JSON.stringify({
158
+ token: "6diDScDDcLJLl3sxAEestZz63mrw9Azy",
159
+ user: {
160
+ id: "S6SDKApdnh746gUnP3zujzsEY53tjuTm",
161
+ email: "test@jazz.dev",
162
+ name: "Matteo",
163
+ image: null,
164
+ emailVerified: false,
165
+ createdAt: new Date(),
166
+ updatedAt: new Date(),
167
+ },
168
+ jazzAuth: {
169
+ accountID: credentials!.accountID,
170
+ secretSeed: credentials!.secretSeed,
171
+ accountSecret: credentials!.accountSecret,
172
+ provider: "better-auth",
173
+ },
174
+ }),
175
+ ),
176
+ );
177
+
178
+ // 1. Sign up
179
+ await authClient.signUp.email({
180
+ email: "test@jazz.dev",
181
+ password: "12345678",
182
+ name: "Matteo",
183
+ });
184
+
185
+ expect(authSecretStorage.isAuthenticated).toBe(true);
186
+
187
+ // 2. Sign out
188
+ customFetchImpl.mockResolvedValueOnce(
189
+ new Response(JSON.stringify({ success: true })),
190
+ );
191
+
192
+ await authClient.signOut();
193
+
194
+ expect(authSecretStorage.isAuthenticated).toBe(false);
195
+
196
+ const anonymousCredentials = await authSecretStorage.get();
197
+ expect(anonymousCredentials).not.toMatchObject(credentials!);
198
+ });
199
+
200
+ it("should logout from Jazz after BetterAuth user deletion", async () => {
201
+ const credentials = await authSecretStorage.get();
202
+ expect(authSecretStorage.isAuthenticated).toBe(false);
203
+ customFetchImpl.mockResolvedValueOnce(
204
+ new Response(
205
+ JSON.stringify({
206
+ token: "6diDScDDcLJLl3sxAEestZz63mrw9Azy",
207
+ user: {
208
+ id: "S6SDKApdnh746gUnP3zujzsEY53tjuTm",
209
+ email: "test@jazz.dev",
210
+ name: "Matteo",
211
+ image: null,
212
+ emailVerified: false,
213
+ createdAt: new Date(),
214
+ updatedAt: new Date(),
215
+ },
216
+ jazzAuth: {
217
+ accountID: credentials!.accountID,
218
+ secretSeed: credentials!.secretSeed,
219
+ accountSecret: credentials!.accountSecret,
220
+ provider: "better-auth",
221
+ },
222
+ }),
223
+ ),
224
+ );
225
+
226
+ // 1. Sign up
227
+ await authClient.signUp.email({
228
+ email: "test@jazz.dev",
229
+ password: "12345678",
230
+ name: "Matteo",
231
+ });
232
+
233
+ expect(authSecretStorage.isAuthenticated).toBe(true);
234
+
235
+ // 2. Delete user
236
+ customFetchImpl.mockResolvedValueOnce(
237
+ new Response(JSON.stringify({ success: true })),
238
+ );
239
+
240
+ await authClient.deleteUser();
241
+
242
+ expect(authSecretStorage.isAuthenticated).toBe(false);
243
+
244
+ const anonymousCredentials = await authSecretStorage.get();
245
+ expect(anonymousCredentials).not.toMatchObject(credentials!);
246
+ });
247
+
248
+ it.todo("should logout from Better Auth after Jazz's log-out");
249
+ });
@@ -0,0 +1,226 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { memoryAdapter } from "better-auth/adapters/memory";
3
+ import { beforeEach, describe, expect, it, vi, type Mock } from "vitest";
4
+ import { jazzPlugin } from "../server.js";
5
+
6
+ describe("Better Auth - Signup and Login Tests", () => {
7
+ let auth: ReturnType<typeof betterAuth>;
8
+ let accountCreationSpy: Mock;
9
+ let verificationCreationSpy: Mock;
10
+
11
+ beforeEach(() => {
12
+ accountCreationSpy = vi.fn();
13
+ verificationCreationSpy = vi.fn();
14
+
15
+ // Create auth instance with in-memory database
16
+ auth = betterAuth({
17
+ database: memoryAdapter({
18
+ user: [],
19
+ session: [],
20
+ verification: [],
21
+ account: [],
22
+ }),
23
+ plugins: [jazzPlugin()],
24
+ emailAndPassword: {
25
+ enabled: true,
26
+ requireEmailVerification: false, // Disable for testing
27
+ },
28
+ socialProviders: {
29
+ github: {
30
+ clientId: "123",
31
+ clientSecret: "123",
32
+ },
33
+ },
34
+ databaseHooks: {
35
+ user: {
36
+ create: {
37
+ after: accountCreationSpy,
38
+ },
39
+ },
40
+ verification: {
41
+ create: {
42
+ after: verificationCreationSpy,
43
+ },
44
+ },
45
+ },
46
+ session: {
47
+ expiresIn: 60 * 60 * 24 * 7, // 7 days
48
+ },
49
+ });
50
+ });
51
+
52
+ describe("User Registration (Signup)", () => {
53
+ it("should successfully register a new user with email and password", async () => {
54
+ const userData = {
55
+ name: "test",
56
+ email: "test@example.com",
57
+ password: "securePassword123",
58
+ };
59
+
60
+ const jazzAuth = {
61
+ accountID: "123",
62
+ secretSeed: [1, 2, 3],
63
+ accountSecret: "123",
64
+ provider: "better-auth",
65
+ };
66
+
67
+ const result = await auth.api.signUpEmail({
68
+ body: userData,
69
+ headers: {
70
+ "x-jazz-auth": JSON.stringify(jazzAuth),
71
+ },
72
+ });
73
+
74
+ expect(result).toBeDefined();
75
+ expect(result).toMatchObject({
76
+ user: {
77
+ id: expect.any(String),
78
+ email: userData.email,
79
+ name: userData.name,
80
+ image: undefined,
81
+ emailVerified: false,
82
+ createdAt: expect.any(Date),
83
+ updatedAt: expect.any(Date),
84
+ },
85
+ jazzAuth: jazzAuth,
86
+ });
87
+
88
+ const res = await (await auth.$context).adapter.findOne({
89
+ model: "user",
90
+ where: [
91
+ {
92
+ field: "id",
93
+ value: result.user.id,
94
+ },
95
+ ],
96
+ });
97
+
98
+ expect(res).toMatchObject({
99
+ id: result.user.id,
100
+ accountID: "123",
101
+ encryptedCredentials: expect.any(String),
102
+ });
103
+ });
104
+
105
+ it("should fail to register user without account ID", async () => {
106
+ const userData = {
107
+ name: "test",
108
+ email: "email@email.it",
109
+ password: "securePassword123",
110
+ };
111
+
112
+ await expect(
113
+ auth.api.signUpEmail({
114
+ body: userData,
115
+ }),
116
+ ).rejects.toThrow("JazzAuth is required");
117
+
118
+ expect(accountCreationSpy).toHaveBeenCalledTimes(0);
119
+ });
120
+
121
+ it("should have AccountID in the registration hook", async () => {
122
+ const userData = {
123
+ name: "test",
124
+ email: "email@email.it",
125
+ password: "securePassword123",
126
+ };
127
+
128
+ const jazzAuth = {
129
+ accountID: "123",
130
+ secretSeed: [1, 2, 3],
131
+ accountSecret: "123",
132
+ provider: "better-auth",
133
+ };
134
+
135
+ await auth.api.signUpEmail({
136
+ body: userData,
137
+ headers: {
138
+ "x-jazz-auth": JSON.stringify(jazzAuth),
139
+ },
140
+ });
141
+
142
+ expect(accountCreationSpy).toHaveBeenCalledTimes(1);
143
+ expect(accountCreationSpy).toHaveBeenCalledWith(
144
+ // user
145
+ expect.objectContaining({ accountID: "123" }),
146
+ // context
147
+ expect.any(Object),
148
+ );
149
+ });
150
+ });
151
+
152
+ describe("User login (Signin)", () => {
153
+ it("should successfully login a new user with email and password", async () => {
154
+ const userData = {
155
+ name: "test",
156
+ email: "test@example.com",
157
+ password: "securePassword123",
158
+ };
159
+
160
+ const jazzAuth = {
161
+ accountID: "123",
162
+ secretSeed: [1, 2, 3],
163
+ accountSecret: "123",
164
+ provider: "better-auth",
165
+ };
166
+
167
+ await auth.api.signUpEmail({
168
+ body: userData,
169
+ headers: {
170
+ "x-jazz-auth": JSON.stringify(jazzAuth),
171
+ },
172
+ });
173
+
174
+ const result = await auth.api.signInEmail({
175
+ body: {
176
+ email: userData.email,
177
+ password: userData.password,
178
+ },
179
+ });
180
+
181
+ expect(result).toBeDefined();
182
+ expect(result).toMatchObject({
183
+ user: {
184
+ id: expect.any(String),
185
+ email: userData.email,
186
+ name: userData.name,
187
+ image: undefined,
188
+ emailVerified: false,
189
+ createdAt: expect.any(Date),
190
+ updatedAt: expect.any(Date),
191
+ },
192
+ jazzAuth: jazzAuth,
193
+ });
194
+ });
195
+ });
196
+
197
+ describe("Social Login", () => {
198
+ it("should store jazzAuth in verification table when using social provider", async () => {
199
+ await auth.api.signInSocial({
200
+ body: {
201
+ provider: "github",
202
+ callbackURL: "http://localhost:3000/api/auth/sign-in/social/callback",
203
+ },
204
+ headers: {
205
+ "x-jazz-auth": JSON.stringify({
206
+ accountID: "123",
207
+ secretSeed: [1, 2, 3],
208
+ accountSecret: "123",
209
+ }),
210
+ },
211
+ });
212
+
213
+ expect(verificationCreationSpy).toHaveBeenCalledTimes(1);
214
+ expect(verificationCreationSpy).toHaveBeenCalledWith(
215
+ expect.objectContaining({
216
+ value: expect.stringContaining('"accountID":"123"'),
217
+ }),
218
+ expect.any(Object),
219
+ );
220
+ });
221
+
222
+ it.todo(
223
+ "should create a new account with jazz auth when using social provider",
224
+ );
225
+ });
226
+ });
@@ -82,14 +82,14 @@ export class BrowserPasskeyAuth {
82
82
  username,
83
83
  });
84
84
 
85
- const currentAccount = await Account.getMe().ensureLoaded({
85
+ const currentAccount = await Account.getMe().$jazz.ensureLoaded({
86
86
  resolve: {
87
87
  profile: true,
88
88
  },
89
89
  });
90
90
 
91
91
  if (username.trim().length !== 0) {
92
- currentAccount.profile.name = username;
92
+ currentAccount.profile.$jazz.set("name", username);
93
93
  }
94
94
 
95
95
  await this.authSecretStorage.set({
@@ -272,7 +272,7 @@ export function createInviteLink<C extends CoValue>(
272
272
  valueHint,
273
273
  }: { baseURL?: string; valueHint?: string } = {},
274
274
  ): string {
275
- const coValueCore = value._raw.core;
275
+ const coValueCore = value.$jazz.raw.core;
276
276
  let currentCoValue = coValueCore;
277
277
 
278
278
  while (currentCoValue.verified.header.ruleset.type === "ownedByGroup") {
@@ -289,7 +289,7 @@ export function createInviteLink<C extends CoValue>(
289
289
  const inviteSecret = group.createInvite(role);
290
290
 
291
291
  return `${baseURL}#/invite/${valueHint ? valueHint + "/" : ""}${
292
- value.id
292
+ value.$jazz.id
293
293
  }/${inviteSecret}`;
294
294
  }
295
295
 
@@ -198,7 +198,7 @@ describe("BrowserPasskeyAuth", () => {
198
198
 
199
199
  await auth.signUp("");
200
200
 
201
- const currentAccount = await Account.getMe().ensureLoaded({
201
+ const currentAccount = await Account.getMe().$jazz.ensureLoaded({
202
202
  resolve: {
203
203
  profile: true,
204
204
  },
@@ -230,7 +230,7 @@ describe("BrowserPasskeyAuth", () => {
230
230
 
231
231
  await auth.signUp("testuser");
232
232
 
233
- const currentAccount = await Account.getMe().ensureLoaded({
233
+ const currentAccount = await Account.getMe().$jazz.ensureLoaded({
234
234
  resolve: {
235
235
  profile: true,
236
236
  },
@@ -53,8 +53,8 @@ export class JazzInspectorElement extends HTMLElement {
53
53
 
54
54
  this.root?.render(
55
55
  <JazzInspectorInternal
56
- localNode={this.account._raw.core.node}
57
- accountId={this.account._raw.id}
56
+ localNode={this.account.$jazz.localNode}
57
+ accountId={this.account.$jazz.raw.id}
58
58
  />,
59
59
  );
60
60
  }
@@ -72,7 +72,7 @@ export function JazzInspector({ position = "right" }: { position?: Position }) {
72
72
  <JazzInspectorInternal
73
73
  position={position}
74
74
  localNode={localNode}
75
- accountId={me?._raw.id}
75
+ accountId={me?.$jazz.raw.id}
76
76
  />
77
77
  );
78
78
  }
@@ -10,7 +10,7 @@ describe("createImage", async () => {
10
10
  const getPlaceholderBase64 = vi.fn();
11
11
  const createFileStreamFromSource = vi
12
12
  .fn()
13
- .mockResolvedValue(FileStream.create({ owner: account._owner }));
13
+ .mockResolvedValue(FileStream.create({ owner: account }));
14
14
  const resize = vi.fn();
15
15
 
16
16
  const createImage = createImageFactory({
@@ -33,7 +33,7 @@ describe("createImage", async () => {
33
33
  getImageSize.mockResolvedValue({ width: 1, height: 1 });
34
34
 
35
35
  const image = await createImage(imageBlob, {
36
- owner: account._owner,
36
+ owner: account,
37
37
  placeholder: false,
38
38
  progressive: false,
39
39
  });
@@ -60,7 +60,7 @@ describe("createImage", async () => {
60
60
  );
61
61
 
62
62
  const image = await createImage(imageBlob, {
63
- owner: account._owner,
63
+ owner: account,
64
64
  placeholder: "blur",
65
65
  progressive: false,
66
66
  });
@@ -83,7 +83,7 @@ describe("createImage", async () => {
83
83
  resize.mockResolvedValue(new Blob([White1920], { type: "image/png" }));
84
84
 
85
85
  const image = await createImage(imageBlob, {
86
- owner: account._owner,
86
+ owner: account,
87
87
  placeholder: false,
88
88
  progressive: false,
89
89
  maxSize: 256,
@@ -109,7 +109,7 @@ describe("createImage", async () => {
109
109
  getImageSize.mockResolvedValue({ width: 1, height: 1 });
110
110
 
111
111
  const image = await createImage(imageBlob, {
112
- owner: account._owner,
112
+ owner: account,
113
113
  placeholder: false,
114
114
  progressive: false,
115
115
  maxSize: 256,
@@ -136,7 +136,7 @@ describe("createImage", async () => {
136
136
  resize.mockResolvedValue(new Blob([White1920], { type: "image/png" }));
137
137
 
138
138
  const image = await createImage(imageBlob, {
139
- owner: account._owner,
139
+ owner: account,
140
140
  progressive: true,
141
141
  placeholder: false,
142
142
  });
@@ -164,7 +164,7 @@ describe("createImage", async () => {
164
164
  resize.mockResolvedValue(new Blob([White1920], { type: "image/png" }));
165
165
 
166
166
  const image = await createImage(imageBlob, {
167
- owner: account._owner,
167
+ owner: account,
168
168
  maxSize: 256,
169
169
  placeholder: false,
170
170
  progressive: true,
@@ -137,7 +137,7 @@ async function createImage(
137
137
  * On the client side, the image will be loaded progressively, starting from the smallest size and increasing the size until the original size is reached.
138
138
  */
139
139
  if (options?.progressive) {
140
- imageCoValue.progressive = true;
140
+ imageCoValue.$jazz.set("progressive", true);
141
141
 
142
142
  const resizes = ([256, 1024, 2048] as const).filter(
143
143
  (s) =>
@@ -153,8 +153,10 @@ async function createImage(
153
153
  );
154
154
 
155
155
  const blob = await impl.resize(imageBlobOrFile, width, height);
156
- imageCoValue[`${width}x${height}`] =
157
- await impl.createFileStreamFromSource(blob, options?.owner);
156
+ imageCoValue.$jazz.set(
157
+ `${width}x${height}`,
158
+ await impl.createFileStreamFromSource(blob, options?.owner),
159
+ );
158
160
  }
159
161
  }
160
162
 
@@ -27,7 +27,7 @@ export { createImageFactory };
27
27
  * // Creates ImageDefinition with a blurry placeholder, limited to 1024px
28
28
  * // on the longest side, and multiple resolutions automatically
29
29
  * const image = await createImage(file, {
30
- * owner: me._owner,
30
+ * owner: me.$jazz.owner,
31
31
  * maxSize: 1024,
32
32
  * placeholder: "blur",
33
33
  * progressive: true,