jazz-tools 0.19.15 → 0.19.17

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 (41) hide show
  1. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +4 -1
  2. package/.turbo/turbo-build.log +60 -60
  3. package/CHANGELOG.md +19 -0
  4. package/dist/{chunk-R3KIZG4P.js → chunk-OH2GW5WP.js} +24 -8
  5. package/dist/{chunk-R3KIZG4P.js.map → chunk-OH2GW5WP.js.map} +1 -1
  6. package/dist/index.js +86 -54
  7. package/dist/index.js.map +1 -1
  8. package/dist/react-native/index.js +18 -17
  9. package/dist/react-native/index.js.map +1 -1
  10. package/dist/react-native-core/ReactNativeSessionProvider.d.ts.map +1 -1
  11. package/dist/react-native-core/index.js +18 -17
  12. package/dist/react-native-core/index.js.map +1 -1
  13. package/dist/svelte/tests/media/image.svelte.test.js +4 -1
  14. package/dist/testing.js +1 -1
  15. package/dist/tools/auth/clerk/getClerkUsername.d.ts +2 -2
  16. package/dist/tools/auth/clerk/getClerkUsername.d.ts.map +1 -1
  17. package/dist/tools/auth/clerk/index.d.ts +5 -4
  18. package/dist/tools/auth/clerk/index.d.ts.map +1 -1
  19. package/dist/tools/auth/clerk/tests/isClerkAuthStateEqual.test.d.ts +2 -0
  20. package/dist/tools/auth/clerk/tests/isClerkAuthStateEqual.test.d.ts.map +1 -0
  21. package/dist/tools/auth/clerk/tests/isClerkCredentials.test.d.ts +2 -0
  22. package/dist/tools/auth/clerk/tests/isClerkCredentials.test.d.ts.map +1 -0
  23. package/dist/tools/auth/clerk/types.d.ts +62 -19
  24. package/dist/tools/auth/clerk/types.d.ts.map +1 -1
  25. package/dist/tools/implementation/ContextManager.d.ts +10 -0
  26. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  27. package/package.json +5 -6
  28. package/src/react/tests/media/image.test.tsx +5 -1
  29. package/src/react-native-core/ReactNativeSessionProvider.ts +24 -24
  30. package/src/svelte/tests/media/image.svelte.test.ts +5 -1
  31. package/src/tools/auth/clerk/getClerkUsername.ts +13 -20
  32. package/src/tools/auth/clerk/index.ts +35 -28
  33. package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +105 -33
  34. package/src/tools/auth/clerk/tests/getClerkUsername.test.ts +25 -45
  35. package/src/tools/auth/clerk/tests/isClerkAuthStateEqual.test.ts +128 -0
  36. package/src/tools/auth/clerk/tests/{types.test.ts → isClerkCredentials.test.ts} +4 -2
  37. package/src/tools/auth/clerk/types.ts +66 -28
  38. package/src/tools/implementation/ContextManager.ts +28 -7
  39. package/src/tools/tests/ContextManager.test.ts +16 -0
  40. package/dist/tools/auth/clerk/tests/types.test.d.ts +0 -2
  41. package/dist/tools/auth/clerk/tests/types.test.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isClerkAuthStateEqual.test.d.ts","sourceRoot":"","sources":["../../../../../src/tools/auth/clerk/tests/isClerkAuthStateEqual.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=isClerkCredentials.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isClerkCredentials.test.d.ts","sourceRoot":"","sources":["../../../../../src/tools/auth/clerk/tests/isClerkCredentials.test.ts"],"names":[],"mappings":""}
@@ -1,25 +1,66 @@
1
- import { AgentSecret } from "cojson";
2
- import { Account, ID } from "jazz-tools";
1
+ import { type AgentSecret } from "cojson";
2
+ import { z } from "zod/v4";
3
+ declare const ClerkUserSchema: z.ZodObject<{
4
+ fullName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
5
+ username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6
+ firstName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7
+ lastName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8
+ id: z.ZodOptional<z.ZodString>;
9
+ primaryEmailAddress: z.ZodOptional<z.ZodNullable<z.ZodObject<{
10
+ emailAddress: z.ZodNullable<z.ZodString>;
11
+ }, z.core.$strip>>>;
12
+ unsafeMetadata: z.ZodUnion<readonly [z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
13
+ jazzAccountID: z.ZodString;
14
+ jazzAccountSecret: z.ZodString;
15
+ jazzAccountSeed: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
16
+ }, z.core.$strip>]>;
17
+ update: z.ZodFunction<z.ZodTuple<readonly [z.ZodObject<{
18
+ unsafeMetadata: z.ZodObject<{
19
+ jazzAccountID: z.ZodString;
20
+ jazzAccountSecret: z.ZodString;
21
+ jazzAccountSeed: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
22
+ }, z.core.$strip>;
23
+ }, z.core.$strip>], null>, z.ZodPromise<z.ZodUnknown>>;
24
+ }, z.core.$strip>;
25
+ export declare const ClerkEventSchema: z.ZodObject<{
26
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
27
+ fullName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
28
+ username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
29
+ firstName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
30
+ lastName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
31
+ id: z.ZodOptional<z.ZodString>;
32
+ primaryEmailAddress: z.ZodOptional<z.ZodNullable<z.ZodObject<{
33
+ emailAddress: z.ZodNullable<z.ZodString>;
34
+ }, z.core.$strip>>>;
35
+ unsafeMetadata: z.ZodUnion<readonly [z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
36
+ jazzAccountID: z.ZodString;
37
+ jazzAccountSecret: z.ZodString;
38
+ jazzAccountSeed: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
39
+ }, z.core.$strip>]>;
40
+ update: z.ZodFunction<z.ZodTuple<readonly [z.ZodObject<{
41
+ unsafeMetadata: z.ZodObject<{
42
+ jazzAccountID: z.ZodString;
43
+ jazzAccountSecret: z.ZodString;
44
+ jazzAccountSeed: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
45
+ }, z.core.$strip>;
46
+ }, z.core.$strip>], null>, z.ZodPromise<z.ZodUnknown>>;
47
+ }, z.core.$strip>>>;
48
+ }, z.core.$strip>;
49
+ export type ClerkEventSchema = z.infer<typeof ClerkEventSchema>;
50
+ export type ClerkUser = z.infer<typeof ClerkUserSchema>;
51
+ type PermissiveClerkUser = Omit<ClerkUser, "unsafeMetadata" | "update"> & {
52
+ unsafeMetadata: Record<string, unknown>;
53
+ update: (args: {
54
+ unsafeMetadata: Record<string, unknown>;
55
+ }) => Promise<unknown>;
56
+ };
3
57
  export type MinimalClerkClient = {
4
- user: {
5
- unsafeMetadata: Record<string, any>;
6
- fullName: string | null;
7
- username: string | null;
8
- firstName: string | null;
9
- lastName: string | null;
10
- id: string;
11
- primaryEmailAddress: {
12
- emailAddress: string | null;
13
- } | null;
14
- update: (args: {
15
- unsafeMetadata: Record<string, any>;
16
- }) => Promise<unknown>;
17
- } | null | undefined;
58
+ user: PermissiveClerkUser | null | undefined;
18
59
  signOut: () => Promise<void>;
19
60
  addListener: (listener: (data: unknown) => void) => void;
20
61
  };
21
62
  export type ClerkCredentials = {
22
- jazzAccountID: ID<Account>;
63
+ jazzAccountID: string;
23
64
  jazzAccountSecret: AgentSecret;
24
65
  jazzAccountSeed?: number[];
25
66
  };
@@ -27,6 +68,8 @@ export type ClerkCredentials = {
27
68
  * Checks if the Clerk user metadata contains the necessary credentials for Jazz auth.
28
69
  * **Note**: It does not validate the credentials, only checks if the necessary fields are present in the metadata object.
29
70
  */
30
- export declare function isClerkCredentials(data: NonNullable<MinimalClerkClient["user"]>["unsafeMetadata"] | undefined): data is ClerkCredentials;
31
- export declare function isClerkAuthStateEqual(previousUser: MinimalClerkClient["user"] | null | undefined, newUser: MinimalClerkClient["user"] | null | undefined): boolean;
71
+ export declare function isClerkCredentials(data: Record<string, unknown> | undefined): data is ClerkCredentials;
72
+ type ClerkUserWithUnsafeMetadata = Pick<ClerkUser, "unsafeMetadata"> | null | undefined;
73
+ export declare function isClerkAuthStateEqual(previousUser: ClerkUserWithUnsafeMetadata, newUser: ClerkUserWithUnsafeMetadata): boolean;
74
+ export {};
32
75
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/tools/auth/clerk/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EACA;QAEE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,mBAAmB,EAAE;YACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;SAC7B,GAAG,IAAI,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE;YAEb,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;SACrC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KACxB,GACD,IAAI,GACJ,SAAS,CAAC;IACd,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IAC3B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,SAAS,GAC1E,IAAI,IAAI,gBAAgB,CAE1B;AAED,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3D,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,WAUvD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/tools/auth/clerk/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAQ3B,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;iBAoBnB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;iBAE3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAGxD,KAAK,mBAAmB,GAAG,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,QAAQ,CAAC,GAAG;IACxE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,IAAI,EAAE;QACb,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACzC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,WAAW,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACxC,IAAI,IAAI,gBAAgB,CAE1B;AAED,KAAK,2BAA2B,GAC5B,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,GACjC,IAAI,GACJ,SAAS,CAAC;AAEd,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,2BAA2B,EACzC,OAAO,EAAE,2BAA2B,WAkBrC"}
@@ -60,6 +60,16 @@ export declare class JazzContextManager<Acc extends Account, P extends JazzConte
60
60
  getAuthSecretStorage(): AuthSecretStorage;
61
61
  getAuthenticatingAccountID(): string | null;
62
62
  getSubscriptionScopeCache(): SubscriptionCache;
63
+ /**
64
+ * Flag to indicate if a logout operation is currently in progress.
65
+ * Used to prevent concurrent logout attempts or double-logout issues.
66
+ * Set to true when logout starts, reset to false once all logout logic runs.
67
+ */
68
+ loggingOut: boolean;
69
+ /**
70
+ * Handles the logout process.
71
+ * Uses the loggingOut flag to ensure only one logout can happen at a time.
72
+ */
63
73
  logOut: () => Promise<void>;
64
74
  done: () => void;
65
75
  shouldMigrateAnonymousAccount: () => Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"ContextManager.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/ContextManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ContextManager.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/ContextManager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -205,7 +205,7 @@
205
205
  },
206
206
  "type": "module",
207
207
  "license": "MIT",
208
- "version": "0.19.15",
208
+ "version": "0.19.17",
209
209
  "dependencies": {
210
210
  "@manuscripts/prosemirror-recreate-steps": "^0.1.4",
211
211
  "@scure/base": "1.2.1",
@@ -222,9 +222,9 @@
222
222
  "prosemirror-transform": "^1.9.0",
223
223
  "use-sync-external-store": "^1.5.0",
224
224
  "zod": "4.1.11",
225
- "cojson": "0.19.15",
226
- "cojson-storage-indexeddb": "0.19.15",
227
- "cojson-transport-ws": "0.19.15"
225
+ "cojson": "0.19.17",
226
+ "cojson-storage-indexeddb": "0.19.17",
227
+ "cojson-transport-ws": "0.19.17"
228
228
  },
229
229
  "devDependencies": {
230
230
  "@scure/bip39": "^1.3.0",
@@ -237,7 +237,6 @@
237
237
  "@types/react": "19.1.0",
238
238
  "@types/react-dom": "19.1.0",
239
239
  "@types/use-sync-external-store": "^1.5.0",
240
- "@vitest/browser": "^3.2.4",
241
240
  "libsql": "^0.5.13",
242
241
  "msw": "^2.10.3",
243
242
  "oauth2-mock-server": "^8.1.0",
@@ -246,7 +245,7 @@
246
245
  "react-error-boundary": "^6.0.0",
247
246
  "tsup": "8.5.0",
248
247
  "typescript": "5.6.2",
249
- "vitest": "3.2.4",
248
+ "vitest": "4.0.16",
250
249
  "ws": "^8.14.2"
251
250
  },
252
251
  "peerDependencies": {
@@ -1,10 +1,14 @@
1
1
  // @vitest-environment happy-dom
2
- import { describe, expect, it, vi } from "vitest";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
  import { Account, FileStream, ImageDefinition } from "../../../";
4
4
  import { Image } from "../../media/image";
5
5
  import { createJazzTestAccount } from "../../testing";
6
6
  import { render, screen, waitFor } from "../testUtils";
7
7
 
8
+ beforeEach(() => {
9
+ vi.clearAllMocks();
10
+ });
11
+
8
12
  describe("Image", async () => {
9
13
  const account = await createJazzTestAccount({
10
14
  isCurrentActiveAccount: true,
@@ -16,6 +16,23 @@ export class ReactNativeSessionProvider implements SessionProvider {
16
16
  const kvStore = KvStoreContext.getInstance().getStorage();
17
17
  const existingSession = await kvStore.get(accountID as string);
18
18
 
19
+ if (!existingSession) {
20
+ const newSessionID = crypto.newRandomSessionID(
21
+ accountID as RawAccountID | AgentID,
22
+ );
23
+ await kvStore.set(accountID, newSessionID);
24
+ lockedSessions.add(newSessionID);
25
+
26
+ console.log("Created new session", newSessionID);
27
+
28
+ return Promise.resolve({
29
+ sessionID: newSessionID,
30
+ sessionDone: () => {
31
+ lockedSessions.delete(newSessionID);
32
+ },
33
+ });
34
+ }
35
+
19
36
  // Check if the session is already in use, should happen only if the dev
20
37
  // mounts multiple providers at the same time
21
38
  if (lockedSessions.has(existingSession as SessionID)) {
@@ -31,33 +48,13 @@ export class ReactNativeSessionProvider implements SessionProvider {
31
48
  });
32
49
  }
33
50
 
34
- if (existingSession) {
35
- console.log("Using existing session", existingSession);
36
- lockedSessions.add(existingSession as SessionID);
37
- return Promise.resolve({
38
- sessionID: existingSession as SessionID,
39
- sessionDone: () => {
40
- lockedSessions.delete(existingSession as SessionID);
41
- },
42
- });
43
- }
44
-
45
- // We need to provide this for backwards compatibility with the old session provider
46
- // With the current session provider we should never get here because:
47
- // - New accounts provide their session and go through the persistSession method
48
- // - Existing accounts should already have a session
49
- const newSessionID = crypto.newRandomSessionID(
50
- accountID as RawAccountID | AgentID,
51
- );
52
- await kvStore.set(accountID, newSessionID);
53
- lockedSessions.add(newSessionID);
54
-
55
- console.error("Created new session", newSessionID);
51
+ console.log("Using existing session", existingSession);
52
+ lockedSessions.add(existingSession as SessionID);
56
53
 
57
54
  return Promise.resolve({
58
- sessionID: newSessionID,
55
+ sessionID: existingSession as SessionID,
59
56
  sessionDone: () => {
60
- lockedSessions.delete(newSessionID);
57
+ lockedSessions.delete(existingSession as SessionID);
61
58
  },
62
59
  });
63
60
  }
@@ -69,6 +66,9 @@ export class ReactNativeSessionProvider implements SessionProvider {
69
66
  const kvStore = KvStoreContext.getInstance().getStorage();
70
67
  await kvStore.set(accountID, sessionID);
71
68
  lockedSessions.add(sessionID);
69
+
70
+ console.log("Persisted session", sessionID);
71
+
72
72
  return Promise.resolve({
73
73
  sessionDone: () => {
74
74
  lockedSessions.delete(sessionID);
@@ -1,11 +1,15 @@
1
1
  // @vitest-environment happy-dom
2
2
  import { FileStream, ImageDefinition } from "jazz-tools";
3
3
  import { createJazzTestAccount } from "jazz-tools/testing";
4
- import { describe, expect, it, vi } from "vitest";
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
5
  import Image from "../../media/image.svelte";
6
6
  import type { ImageProps } from "../../media/image.types.js";
7
7
  import { render, screen, waitFor } from "../testUtils";
8
8
 
9
+ beforeEach(() => {
10
+ vi.clearAllMocks();
11
+ });
12
+
9
13
  describe("Image", async () => {
10
14
  const account = await createJazzTestAccount({
11
15
  isCurrentActiveAccount: true,
@@ -1,36 +1,29 @@
1
- import type { MinimalClerkClient } from "./types.js";
1
+ import type { ClerkUser } from "./types.js";
2
2
 
3
- export function getClerkUsername(
4
- clerkClient: Pick<MinimalClerkClient, "user">,
5
- ) {
6
- if (!clerkClient.user) {
7
- return null;
3
+ export function getClerkUsername(user: ClerkUser) {
4
+ if (user.fullName) {
5
+ return user.fullName;
8
6
  }
9
7
 
10
- if (clerkClient.user.fullName) {
11
- return clerkClient.user.fullName;
12
- }
13
-
14
- if (clerkClient.user.firstName) {
15
- if (clerkClient.user.lastName) {
16
- return `${clerkClient.user.firstName} ${clerkClient.user.lastName}`;
8
+ if (user.firstName) {
9
+ if (user.lastName) {
10
+ return `${user.firstName} ${user.lastName}`;
17
11
  }
18
12
 
19
- return clerkClient.user.firstName;
13
+ return user.firstName;
20
14
  }
21
15
 
22
- if (clerkClient.user.username) {
23
- return clerkClient.user.username;
16
+ if (user.username) {
17
+ return user.username;
24
18
  }
25
19
 
26
- if (clerkClient.user.primaryEmailAddress?.emailAddress) {
27
- const emailUsername =
28
- clerkClient.user.primaryEmailAddress.emailAddress.split("@")[0];
20
+ if (user.primaryEmailAddress?.emailAddress) {
21
+ const emailUsername = user.primaryEmailAddress.emailAddress.split("@")[0];
29
22
 
30
23
  if (emailUsername) {
31
24
  return emailUsername;
32
25
  }
33
26
  }
34
27
 
35
- return clerkClient.user.id;
28
+ return user.id;
36
29
  }
@@ -7,6 +7,8 @@ import {
7
7
  import { getClerkUsername } from "./getClerkUsername.js";
8
8
  import {
9
9
  ClerkCredentials,
10
+ ClerkEventSchema,
11
+ ClerkUser,
10
12
  MinimalClerkClient,
11
13
  isClerkAuthStateEqual,
12
14
  isClerkCredentials,
@@ -53,29 +55,36 @@ export class JazzClerkAuth {
53
55
  }
54
56
 
55
57
  private isFirstCall = true;
58
+ private previousUser: Pick<ClerkUser, "unsafeMetadata"> | null = null;
56
59
 
57
60
  registerListener(clerkClient: MinimalClerkClient) {
58
- let previousUser: MinimalClerkClient["user"] | null =
59
- clerkClient.user ?? null;
61
+ this.previousUser = ClerkEventSchema.parse(clerkClient).user ?? null;
60
62
 
61
63
  // Need to use addListener because the clerk user object is not updated when the user logs in
62
64
  return clerkClient.addListener((event) => {
63
- const user = (event as Pick<MinimalClerkClient, "user">).user ?? null;
65
+ const parsedEvent = ClerkEventSchema.safeParse(event);
64
66
 
65
- if (!isClerkAuthStateEqual(previousUser, user) || this.isFirstCall) {
66
- this.onClerkUserChange({ user });
67
- previousUser = user;
67
+ if (!parsedEvent.success) {
68
+ console.error("Invalid Clerk event", parsedEvent.error);
69
+ return;
70
+ }
71
+
72
+ const user = parsedEvent.data.user ?? null;
73
+
74
+ if (!isClerkAuthStateEqual(this.previousUser, user) || this.isFirstCall) {
75
+ this.previousUser = user;
76
+ this.onClerkUserChange(user);
68
77
  this.isFirstCall = false;
69
78
  }
70
79
  });
71
80
  }
72
81
 
73
- onClerkUserChange = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
82
+ onClerkUserChange = async (clerkUser: ClerkUser | null | undefined) => {
74
83
  const isAuthenticated = this.authSecretStorage.isAuthenticated;
75
84
 
76
85
  // LogOut is driven by Clerk. The framework adapters will need to pass `logOutReplacement` to the `JazzProvider`
77
86
  // to make the logOut work correctly.
78
- if (!clerkClient.user) {
87
+ if (!clerkUser) {
79
88
  if (isAuthenticated) {
80
89
  this.authSecretStorage.clear();
81
90
  await this.logOut();
@@ -85,22 +94,15 @@ export class JazzClerkAuth {
85
94
 
86
95
  if (isAuthenticated) return;
87
96
 
88
- const clerkCredentials = clerkClient.user
89
- .unsafeMetadata as ClerkCredentials;
90
-
91
- if (!clerkCredentials.jazzAccountID) {
92
- await this.signIn(clerkClient);
97
+ if (!clerkUser.unsafeMetadata.jazzAccountID) {
98
+ await this.signIn(clerkUser);
93
99
  } else {
94
- await this.logIn(clerkClient);
100
+ await this.logIn(clerkUser);
95
101
  }
96
102
  };
97
103
 
98
- logIn = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
99
- if (!clerkClient.user) {
100
- throw new Error("Not signed in on Clerk");
101
- }
102
-
103
- const clerkCredentials = clerkClient.user.unsafeMetadata;
104
+ logIn = async (clerkUser: ClerkUser) => {
105
+ const clerkCredentials = clerkUser.unsafeMetadata;
104
106
  if (!isClerkCredentials(clerkCredentials)) {
105
107
  throw new Error("No credentials found on Clerk");
106
108
  }
@@ -126,7 +128,7 @@ export class JazzClerkAuth {
126
128
  );
127
129
  };
128
130
 
129
- signIn = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
131
+ signIn = async (clerkUser: ClerkUser) => {
130
132
  const credentials = await this.authSecretStorage.get();
131
133
 
132
134
  if (!credentials) {
@@ -137,12 +139,17 @@ export class JazzClerkAuth {
137
139
  ? Array.from(credentials.secretSeed)
138
140
  : undefined;
139
141
 
140
- await clerkClient.user?.update({
141
- unsafeMetadata: {
142
- jazzAccountID: credentials.accountID,
143
- jazzAccountSecret: credentials.accountSecret,
144
- jazzAccountSeed,
145
- } satisfies ClerkCredentials,
142
+ const clerkCredentials = {
143
+ jazzAccountID: credentials.accountID,
144
+ jazzAccountSecret: credentials.accountSecret,
145
+ jazzAccountSeed,
146
+ };
147
+ // user.update will cause the Clerk user change listener to fire; updating this.previousUser beforehand
148
+ // ensures the listener sees the new credentials and does not trigger an unnecessary logIn operation
149
+ this.previousUser = { unsafeMetadata: clerkCredentials };
150
+
151
+ await clerkUser.update({
152
+ unsafeMetadata: clerkCredentials,
146
153
  });
147
154
 
148
155
  const currentAccount = await Account.getMe().$jazz.ensureLoaded({
@@ -151,7 +158,7 @@ export class JazzClerkAuth {
151
158
  },
152
159
  });
153
160
 
154
- const username = getClerkUsername(clerkClient);
161
+ const username = getClerkUsername(clerkUser);
155
162
 
156
163
  if (username) {
157
164
  currentAccount.profile.$jazz.set("name", username);