jazz-tools 0.19.16 → 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 (39) hide show
  1. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +4 -1
  2. package/.turbo/turbo-build.log +55 -55
  3. package/CHANGELOG.md +9 -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 +72 -48
  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 +4 -4
  18. package/dist/tools/auth/clerk/index.d.ts.map +1 -1
  19. package/dist/tools/auth/clerk/tests/isClerkCredentials.test.d.ts +2 -0
  20. package/dist/tools/auth/clerk/tests/isClerkCredentials.test.d.ts.map +1 -0
  21. package/dist/tools/auth/clerk/types.d.ts +62 -19
  22. package/dist/tools/auth/clerk/types.d.ts.map +1 -1
  23. package/dist/tools/implementation/ContextManager.d.ts +10 -0
  24. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  25. package/package.json +5 -6
  26. package/src/react/tests/media/image.test.tsx +5 -1
  27. package/src/react-native-core/ReactNativeSessionProvider.ts +24 -24
  28. package/src/svelte/tests/media/image.svelte.test.ts +5 -1
  29. package/src/tools/auth/clerk/getClerkUsername.ts +13 -20
  30. package/src/tools/auth/clerk/index.ts +25 -28
  31. package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +29 -34
  32. package/src/tools/auth/clerk/tests/getClerkUsername.test.ts +25 -45
  33. package/src/tools/auth/clerk/tests/isClerkAuthStateEqual.test.ts +7 -3
  34. package/src/tools/auth/clerk/tests/{types.test.ts → isClerkCredentials.test.ts} +4 -2
  35. package/src/tools/auth/clerk/types.ts +55 -34
  36. package/src/tools/implementation/ContextManager.ts +28 -7
  37. package/src/tools/tests/ContextManager.test.ts +16 -0
  38. package/dist/tools/auth/clerk/tests/types.test.d.ts +0 -2
  39. package/dist/tools/auth/clerk/tests/types.test.d.ts.map +0 -1
@@ -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"] | null | undefined): data is ClerkCredentials;
31
- export declare function isClerkAuthStateEqual(previousUser: Pick<NonNullable<MinimalClerkClient["user"]>, "unsafeMetadata"> | null | undefined, newUser: Pick<NonNullable<MinimalClerkClient["user"]>, "unsafeMetadata"> | 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,EACA,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,GACzD,IAAI,GACJ,SAAS,GACZ,IAAI,IAAI,gBAAgB,CAE1B;AAED,wBAAgB,qBAAqB,CACnC,YAAY,EACR,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAC/D,IAAI,GACJ,SAAS,EACb,OAAO,EACH,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAC/D,IAAI,GACJ,SAAS,WAkBd"}
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.16",
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.16",
226
- "cojson-storage-indexeddb": "0.19.16",
227
- "cojson-transport-ws": "0.19.16"
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,32 +55,36 @@ export class JazzClerkAuth {
53
55
  }
54
56
 
55
57
  private isFirstCall = true;
56
- private previousUser: Pick<
57
- NonNullable<MinimalClerkClient["user"]>,
58
- "unsafeMetadata"
59
- > | null = null;
58
+ private previousUser: Pick<ClerkUser, "unsafeMetadata"> | null = null;
60
59
 
61
60
  registerListener(clerkClient: MinimalClerkClient) {
62
- this.previousUser = clerkClient.user ?? null;
61
+ this.previousUser = ClerkEventSchema.parse(clerkClient).user ?? null;
63
62
 
64
63
  // Need to use addListener because the clerk user object is not updated when the user logs in
65
64
  return clerkClient.addListener((event) => {
66
- const user = (event as Pick<MinimalClerkClient, "user">).user ?? null;
65
+ const parsedEvent = ClerkEventSchema.safeParse(event);
66
+
67
+ if (!parsedEvent.success) {
68
+ console.error("Invalid Clerk event", parsedEvent.error);
69
+ return;
70
+ }
71
+
72
+ const user = parsedEvent.data.user ?? null;
67
73
 
68
74
  if (!isClerkAuthStateEqual(this.previousUser, user) || this.isFirstCall) {
69
75
  this.previousUser = user;
70
- this.onClerkUserChange({ user });
76
+ this.onClerkUserChange(user);
71
77
  this.isFirstCall = false;
72
78
  }
73
79
  });
74
80
  }
75
81
 
76
- onClerkUserChange = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
82
+ onClerkUserChange = async (clerkUser: ClerkUser | null | undefined) => {
77
83
  const isAuthenticated = this.authSecretStorage.isAuthenticated;
78
84
 
79
85
  // LogOut is driven by Clerk. The framework adapters will need to pass `logOutReplacement` to the `JazzProvider`
80
86
  // to make the logOut work correctly.
81
- if (!clerkClient.user) {
87
+ if (!clerkUser) {
82
88
  if (isAuthenticated) {
83
89
  this.authSecretStorage.clear();
84
90
  await this.logOut();
@@ -88,22 +94,15 @@ export class JazzClerkAuth {
88
94
 
89
95
  if (isAuthenticated) return;
90
96
 
91
- const clerkCredentials = clerkClient.user
92
- .unsafeMetadata as ClerkCredentials;
93
-
94
- if (!clerkCredentials.jazzAccountID) {
95
- await this.signIn(clerkClient);
97
+ if (!clerkUser.unsafeMetadata.jazzAccountID) {
98
+ await this.signIn(clerkUser);
96
99
  } else {
97
- await this.logIn(clerkClient);
100
+ await this.logIn(clerkUser);
98
101
  }
99
102
  };
100
103
 
101
- logIn = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
102
- if (!clerkClient.user) {
103
- throw new Error("Not signed in on Clerk");
104
- }
105
-
106
- const clerkCredentials = clerkClient.user.unsafeMetadata;
104
+ logIn = async (clerkUser: ClerkUser) => {
105
+ const clerkCredentials = clerkUser.unsafeMetadata;
107
106
  if (!isClerkCredentials(clerkCredentials)) {
108
107
  throw new Error("No credentials found on Clerk");
109
108
  }
@@ -129,7 +128,7 @@ export class JazzClerkAuth {
129
128
  );
130
129
  };
131
130
 
132
- signIn = async (clerkClient: Pick<MinimalClerkClient, "user">) => {
131
+ signIn = async (clerkUser: ClerkUser) => {
133
132
  const credentials = await this.authSecretStorage.get();
134
133
 
135
134
  if (!credentials) {
@@ -149,11 +148,9 @@ export class JazzClerkAuth {
149
148
  // ensures the listener sees the new credentials and does not trigger an unnecessary logIn operation
150
149
  this.previousUser = { unsafeMetadata: clerkCredentials };
151
150
 
152
- if (clerkClient.user) {
153
- await clerkClient.user.update({
154
- unsafeMetadata: clerkCredentials,
155
- });
156
- }
151
+ await clerkUser.update({
152
+ unsafeMetadata: clerkCredentials,
153
+ });
157
154
 
158
155
  const currentAccount = await Account.getMe().$jazz.ensureLoaded({
159
156
  resolve: {
@@ -161,7 +158,7 @@ export class JazzClerkAuth {
161
158
  },
162
159
  });
163
160
 
164
- const username = getClerkUsername(clerkClient);
161
+ const username = getClerkUsername(clerkUser);
165
162
 
166
163
  if (username) {
167
164
  currentAccount.profile.$jazz.set("name", username);
@@ -6,7 +6,7 @@ import { Account, ID, InMemoryKVStore, KvStoreContext } from "jazz-tools";
6
6
  import { createJazzTestAccount } from "jazz-tools/testing";
7
7
  import { beforeEach, describe, expect, it, vi } from "vitest";
8
8
  import { JazzClerkAuth } from "../index";
9
- import type { MinimalClerkClient } from "../types";
9
+ import type { ClerkEventSchema, ClerkUser, MinimalClerkClient } from "../types";
10
10
 
11
11
  KvStoreContext.getInstance().initialize(new InMemoryKVStore());
12
12
  const authSecretStorage = new AuthSecretStorage();
@@ -27,23 +27,16 @@ describe("JazzClerkAuth", () => {
27
27
 
28
28
  describe("onClerkUserChange", () => {
29
29
  it("should do nothing if no clerk user", async () => {
30
- const mockClerk = {
31
- user: null,
32
- } as MinimalClerkClient;
33
-
34
- await auth.onClerkUserChange(mockClerk);
30
+ await auth.onClerkUserChange(null);
35
31
  expect(mockAuthenticate).not.toHaveBeenCalled();
36
32
  });
37
33
 
38
34
  it("should throw if not authenticated locally", async () => {
39
- const mockClerk = {
40
- user: {
41
- unsafeMetadata: {},
42
- },
43
- signOut: vi.fn(),
44
- } as unknown as MinimalClerkClient;
35
+ const user = {
36
+ unsafeMetadata: {},
37
+ } as ClerkUser;
45
38
 
46
- await expect(auth.onClerkUserChange(mockClerk)).rejects.toThrow();
39
+ await expect(auth.onClerkUserChange(user)).rejects.toThrow();
47
40
  expect(mockAuthenticate).not.toHaveBeenCalled();
48
41
  });
49
42
 
@@ -61,11 +54,10 @@ describe("JazzClerkAuth", () => {
61
54
  fullName: "Guido",
62
55
  unsafeMetadata: {},
63
56
  update: vi.fn(),
64
- },
65
- signOut: vi.fn(),
66
- } as unknown as MinimalClerkClient;
57
+ } as ClerkUser,
58
+ };
67
59
 
68
- await auth.onClerkUserChange(mockClerk);
60
+ await auth.onClerkUserChange(mockClerk.user);
69
61
 
70
62
  expect(mockClerk.user?.update).toHaveBeenCalledWith({
71
63
  unsafeMetadata: {
@@ -106,11 +98,11 @@ describe("JazzClerkAuth", () => {
106
98
  jazzAccountSecret: "secret123",
107
99
  jazzAccountSeed: [1, 2, 3],
108
100
  },
109
- },
110
- signOut: vi.fn(),
111
- } as unknown as MinimalClerkClient;
101
+ update: vi.fn(),
102
+ } as ClerkUser,
103
+ };
112
104
 
113
- await auth.onClerkUserChange(mockClerk);
105
+ await auth.onClerkUserChange(mockClerk.user);
114
106
 
115
107
  expect(mockAuthenticate).toHaveBeenCalledWith({
116
108
  accountID: "test123",
@@ -137,13 +129,12 @@ describe("JazzClerkAuth", () => {
137
129
  jazzAccountSecret: "secret123",
138
130
  jazzAccountSeed: [1, 2, 3],
139
131
  },
140
- },
141
- signOut: vi.fn(),
142
- } as unknown as MinimalClerkClient;
143
-
144
- await auth.onClerkUserChange(mockClerk);
132
+ update: vi.fn(),
133
+ } as ClerkUser,
134
+ };
145
135
 
146
- await auth.onClerkUserChange({ user: null });
136
+ await auth.onClerkUserChange(mockClerk.user);
137
+ await auth.onClerkUserChange(null);
147
138
 
148
139
  expect(authSecretStorage.isAuthenticated).toBe(false);
149
140
  expect(mockLogOut).toHaveBeenCalled();
@@ -151,10 +142,8 @@ describe("JazzClerkAuth", () => {
151
142
  });
152
143
 
153
144
  describe("registerListener", () => {
154
- function setupMockClerk(user: MinimalClerkClient["user"]) {
155
- const listners = new Set<
156
- (clerkClient: Pick<MinimalClerkClient, "user">) => void
157
- >();
145
+ function setupMockClerk(user: ClerkUser | null) {
146
+ const listners = new Set<(clerkClient: ClerkEventSchema) => void>();
158
147
 
159
148
  return {
160
149
  client: {
@@ -166,9 +155,9 @@ describe("JazzClerkAuth", () => {
166
155
  };
167
156
  }),
168
157
  } as unknown as MinimalClerkClient,
169
- triggerUserChange: (user: unknown) => {
158
+ triggerUserChange: (user: ClerkUser | null | undefined) => {
170
159
  for (const listener of listners) {
171
- listener({ user } as Pick<MinimalClerkClient, "user">);
160
+ listener({ user });
172
161
  }
173
162
  },
174
163
  };
@@ -211,6 +200,7 @@ describe("JazzClerkAuth", () => {
211
200
  jazzAccountSecret: "secret123",
212
201
  jazzAccountSeed: [1, 2, 3],
213
202
  },
203
+ update: vi.fn(),
214
204
  });
215
205
 
216
206
  expect(onClerkUserChangeSpy).toHaveBeenCalledTimes(2);
@@ -251,6 +241,7 @@ describe("JazzClerkAuth", () => {
251
241
  jazzAccountSecret: "secret123",
252
242
  jazzAccountSeed: [1, 2, 3],
253
243
  },
244
+ update: vi.fn(),
254
245
  });
255
246
 
256
247
  triggerUserChange({
@@ -259,6 +250,7 @@ describe("JazzClerkAuth", () => {
259
250
  jazzAccountSecret: "secret123",
260
251
  jazzAccountSeed: [1, 2, 3],
261
252
  },
253
+ update: vi.fn(),
262
254
  });
263
255
 
264
256
  expect(onClerkUserChangeSpy).toHaveBeenCalledTimes(1);
@@ -308,7 +300,10 @@ describe("JazzClerkAuth", () => {
308
300
 
309
301
  // 3. Trigger event with new Clerk user (no Jazz credentials yet)
310
302
  const mockUserUpdate = vi.fn((data) => {
311
- triggerUserChange(data);
303
+ triggerUserChange({
304
+ ...data,
305
+ update: mockUserUpdate,
306
+ });
312
307
  });
313
308
 
314
309
  const signInSpy = vi.spyOn(auth, "signIn");