From 415f2839238ebca4f941a74174b2c297b6eb85a1 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:08:15 -0500 Subject: [PATCH 01/13] feat(clerk-js,react,types): Introduce state signals --- packages/clerk-js/package.json | 1 + packages/clerk-js/src/core/clerk.ts | 2 + packages/clerk-js/src/core/events.ts | 5 ++ .../clerk-js/src/core/resources/SignIn.ts | 3 + packages/clerk-js/src/core/signals.ts | 5 ++ packages/clerk-js/src/core/state.ts | 20 +++++++ packages/react/src/experimental.ts | 1 + packages/react/src/hooks/useClerkSignal.ts | 55 +++++++++++++++++++ packages/react/src/isomorphicClerk.ts | 5 ++ packages/types/src/clerk.ts | 3 + packages/types/src/index.ts | 1 + packages/types/src/state.ts | 12 ++++ pnpm-lock.yaml | 39 +++---------- 13 files changed, 122 insertions(+), 30 deletions(-) create mode 100644 packages/clerk-js/src/core/signals.ts create mode 100644 packages/clerk-js/src/core/state.ts create mode 100644 packages/react/src/hooks/useClerkSignal.ts create mode 100644 packages/types/src/state.ts diff --git a/packages/clerk-js/package.json b/packages/clerk-js/package.json index c992873fee3..894121d8f5b 100644 --- a/packages/clerk-js/package.json +++ b/packages/clerk-js/package.json @@ -75,6 +75,7 @@ "@swc/helpers": "^0.5.17", "@zxcvbn-ts/core": "3.0.4", "@zxcvbn-ts/language-common": "3.0.4", + "alien-signals": "^2.0.5", "browser-tabs-lock": "1.3.0", "copy-to-clipboard": "3.3.3", "core-js": "3.41.0", diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index d4f48ae67b1..ad5c6883164 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -154,6 +154,7 @@ import { Waitlist, } from './resources/internal'; import { navigateToTask } from './sessionTasks'; +import { State } from './state'; import { warnings } from './warnings'; type SetActiveHook = (intent?: 'sign-out') => void | Promise; @@ -211,6 +212,7 @@ export class Clerk implements ClerkInterface { public user: UserResource | null | undefined; public __internal_country?: string | null; public telemetry: TelemetryCollector | undefined; + public __internal_state: State = new State(); protected internal_last_error: ClerkAPIError | null = null; // converted to protected environment to support `updateEnvironment` type assertion diff --git a/packages/clerk-js/src/core/events.ts b/packages/clerk-js/src/core/events.ts index 55f1d8996ab..7fad9c9af80 100644 --- a/packages/clerk-js/src/core/events.ts +++ b/packages/clerk-js/src/core/events.ts @@ -1,20 +1,25 @@ import { createEventBus } from '@clerk/shared/eventBus'; import type { TokenResource } from '@clerk/types'; +import type { SignIn } from './resources'; + export const events = { TokenUpdate: 'token:update', UserSignOut: 'user:signOut', EnvironmentUpdate: 'environment:update', SessionTokenResolved: 'session:tokenResolved', + SignInUpdate: 'signin:update', } as const; type TokenUpdatePayload = { token: TokenResource | null }; +export type SignInUpdatePayload = { resource: SignIn }; type InternalEvents = { [events.TokenUpdate]: TokenUpdatePayload; [events.UserSignOut]: null; [events.EnvironmentUpdate]: null; [events.SessionTokenResolved]: null; + [events.SignInUpdate]: SignInUpdatePayload; }; export const eventBus = createEventBus(); diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index fe4cb5c045c..b57e6846d54 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -65,6 +65,7 @@ import { clerkVerifyPasskeyCalledBeforeCreate, clerkVerifyWeb3WalletCalledBeforeCreate, } from '../errors'; +import { eventBus } from '../events'; import { BaseResource, UserData, Verification } from './internal'; export class SignIn extends BaseResource implements SignInResource { @@ -447,6 +448,8 @@ export class SignIn extends BaseResource implements SignInResource { this.createdSessionId = data.created_session_id; this.userData = new UserData(data.user_data); } + + eventBus.emit('signin:update', { resource: this }); return this; } diff --git a/packages/clerk-js/src/core/signals.ts b/packages/clerk-js/src/core/signals.ts new file mode 100644 index 00000000000..9c49086bb54 --- /dev/null +++ b/packages/clerk-js/src/core/signals.ts @@ -0,0 +1,5 @@ +import { signal } from 'alien-signals'; + +import type { SignIn } from './resources/SignIn'; + +export const signInSignal = signal<{ resource: SignIn | null }>({ resource: null }); diff --git a/packages/clerk-js/src/core/state.ts b/packages/clerk-js/src/core/state.ts new file mode 100644 index 00000000000..cb08adb1a98 --- /dev/null +++ b/packages/clerk-js/src/core/state.ts @@ -0,0 +1,20 @@ +import type { State as StateInterface } from '@clerk/types'; +import { computed, effect } from 'alien-signals'; + +import { eventBus, type SignInUpdatePayload } from './events'; +import { signInSignal } from './signals'; + +export class State implements StateInterface { + signInSignal = signInSignal; + + __internal_effect = effect; + __internal_computed = computed; + + constructor() { + eventBus.on('signin:update', this.onSignInUpdated); + } + + private onSignInUpdated = (payload: SignInUpdatePayload) => { + this.signInSignal({ resource: payload.resource }); + }; +} diff --git a/packages/react/src/experimental.ts b/packages/react/src/experimental.ts index a0378d0fb80..73b6ff81985 100644 --- a/packages/react/src/experimental.ts +++ b/packages/react/src/experimental.ts @@ -1,6 +1,7 @@ export { CheckoutButton } from './components/CheckoutButton'; export { PlanDetailsButton } from './components/PlanDetailsButton'; export { SubscriptionDetailsButton } from './components/SubscriptionDetailsButton'; +export { useSignInSignal } from './hooks/useClerkSignal'; export type { __experimental_CheckoutButtonProps as CheckoutButtonProps, diff --git a/packages/react/src/hooks/useClerkSignal.ts b/packages/react/src/hooks/useClerkSignal.ts new file mode 100644 index 00000000000..84976498da9 --- /dev/null +++ b/packages/react/src/hooks/useClerkSignal.ts @@ -0,0 +1,55 @@ +import type { SignInResource } from '@clerk/types'; +import { useCallback, useSyncExternalStore } from 'react'; + +import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; +import { useAssertWrappedByClerkProvider } from './useAssertWrappedByClerkProvider'; + +function useClerkSignal(signal: 'signIn'): { isLoaded: boolean; signIn: SignInResource | null } { + useAssertWrappedByClerkProvider('useSignInSignal'); + + const clerk = useIsomorphicClerkContext(); + + const subscribe = useCallback( + (callback: () => void) => { + if (!clerk.loaded || !clerk.__internal_state) { + return () => {}; + } + + return clerk.__internal_state.__internal_effect(() => { + switch (signal) { + case 'signIn': + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know that the state is defined + clerk.__internal_state!.signInSignal(); + break; + default: + throw new Error(`Unknown signal: ${signal}`); + } + callback(); + }); + }, + [clerk, clerk.loaded, clerk.__internal_state], + ); + const getSnapshot = useCallback(() => { + if (!clerk.__internal_state) { + return null; + } + + switch (signal) { + case 'signIn': + return clerk.__internal_state.signInSignal().resource; + default: + throw new Error(`Unknown signal: ${signal}`); + } + }, [clerk.__internal_state]); + + const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot); + + return { + isLoaded: clerk.loaded, + [signal]: value, + }; +} + +export function useSignInSignal() { + return useClerkSignal('signIn'); +} diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index 8e7deb0ce02..4462ae00fe8 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -44,6 +44,7 @@ import type { SignUpProps, SignUpRedirectOptions, SignUpResource, + State, TaskSelectOrganizationProps, UnsubscribeCallback, UserButtonProps, @@ -714,6 +715,10 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk { return this.clerkjs?.billing; } + get __internal_state(): State | undefined { + return this.clerkjs?.__internal_state; + } + get apiKeys(): APIKeysNamespace | undefined { return this.clerkjs?.apiKeys; } diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index af12ec8df19..368dde42881 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -54,6 +54,7 @@ import type { SessionVerificationLevel } from './sessionVerification'; import type { SignInResource } from './signIn'; import type { SignUpResource } from './signUp'; import type { ClientJSONSnapshot, EnvironmentJSONSnapshot } from './snapshots'; +import type { State } from './state'; import type { Web3Strategy } from './strategies'; import type { TelemetryCollector } from './telemetry'; import type { UserResource } from './user'; @@ -227,6 +228,8 @@ export interface Clerk { /** Current User. */ user: UserResource | null | undefined; + __internal_state: State | undefined; + /** * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. * @see https://clerk.com/docs/billing/overview diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 854394dbeba..0e1f312dc2e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -49,6 +49,7 @@ export * from './sessionVerification'; export * from './signIn'; export * from './signUp'; export * from './ssr'; +export * from './state'; export * from './strategies'; export * from './theme'; export * from './token'; diff --git a/packages/types/src/state.ts b/packages/types/src/state.ts new file mode 100644 index 00000000000..f0de660f3bd --- /dev/null +++ b/packages/types/src/state.ts @@ -0,0 +1,12 @@ +import type { SignInResource } from './signIn'; + +export interface State { + signInSignal: { + (): { + resource: SignInResource | null; + }; + (value: { resource: SignInResource | null }): void; + }; + __internal_effect: (callback: () => void) => () => void; + __internal_computed: (getter: (previousValue?: T) => T) => () => T; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e00def2f529..bc8596eee1b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,39 +5,10 @@ settings: excludeLinksFromLockfile: false catalogs: - peer-react: - react: - specifier: ^18.0.0 || ^19.0.0 || ^19.0.0-0 - version: 18.3.1 - react-dom: - specifier: ^18.0.0 || ^19.0.0 || ^19.0.0-0 - version: 18.3.1 - react: - '@types/react': - specifier: 18.3.23 - version: 18.3.23 - '@types/react-dom': - specifier: 18.3.7 - version: 18.3.7 - react: - specifier: 18.3.1 - version: 18.3.1 - react-dom: - specifier: 18.3.1 - version: 18.3.1 repo: tslib: specifier: 2.8.1 version: 2.8.1 - tsup: - specifier: 8.5.0 - version: 8.5.0 - typescript: - specifier: 5.8.3 - version: 5.8.3 - zx: - specifier: 8.7.1 - version: 8.7.1 overrides: jest: 29.7.0 @@ -473,6 +444,9 @@ importers: '@zxcvbn-ts/language-common': specifier: 3.0.4 version: 3.0.4 + alien-signals: + specifier: ^2.0.5 + version: 2.0.5 browser-tabs-lock: specifier: 1.3.0 version: 1.3.0 @@ -5869,6 +5843,9 @@ packages: alien-signals@1.0.9: resolution: {integrity: sha512-2dQYgGZHrW4pOYv0BWiw4cH/ElhwmLnQDcj/fdnRRF2OO3YBqgJXSleI1EbbXdQsuC5oCvr6+VKAOEElsmcx4Q==} + alien-signals@2.0.5: + resolution: {integrity: sha512-PdJB6+06nUNAClInE3Dweq7/2xVAYM64vvvS1IHVHSJmgeOtEdrAGyp7Z2oJtYm0B342/Exd2NT0uMJaThcjLQ==} + anser@1.4.10: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} @@ -13302,7 +13279,7 @@ packages: superagent@8.1.2: resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==} engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net superjson@1.13.3: resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} @@ -21109,6 +21086,8 @@ snapshots: alien-signals@1.0.9: {} + alien-signals@2.0.5: {} + anser@1.4.10: {} ansi-align@3.0.1: From 2d00936e60a3ed368663955920496f87c1679c85 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:40:11 -0500 Subject: [PATCH 02/13] fix(clerk-js): Mark state property as readonly --- packages/clerk-js/src/core/clerk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 673ce5f875b..2b012bffe9f 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -212,7 +212,7 @@ export class Clerk implements ClerkInterface { public user: UserResource | null | undefined; public __internal_country?: string | null; public telemetry: TelemetryCollector | undefined; - public __internal_state: State = new State(); + public readonly __internal_state: State = new State(); protected internal_last_error: ClerkAPIError | null = null; // converted to protected environment to support `updateEnvironment` type assertion From 66f9a55386bec2b66186c5c7329bdc75f7384f15 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:09:09 -0500 Subject: [PATCH 03/13] feat(clerk-js): Add SignInBeta class --- packages/clerk-js/src/core/events.ts | 2 ++ .../clerk-js/src/core/resources/SignIn.ts | 29 +++++++++++++++++++ packages/clerk-js/src/core/signals.ts | 14 ++++++++- packages/clerk-js/src/core/state.ts | 13 +++++++-- packages/react/src/hooks/useClerkSignal.ts | 11 +++---- packages/types/src/signIn.ts | 5 ++++ packages/types/src/state.ts | 7 +++-- 7 files changed, 67 insertions(+), 14 deletions(-) diff --git a/packages/clerk-js/src/core/events.ts b/packages/clerk-js/src/core/events.ts index 7fad9c9af80..3fe58fe0178 100644 --- a/packages/clerk-js/src/core/events.ts +++ b/packages/clerk-js/src/core/events.ts @@ -9,6 +9,7 @@ export const events = { EnvironmentUpdate: 'environment:update', SessionTokenResolved: 'session:tokenResolved', SignInUpdate: 'signin:update', + SignInError: 'signin:error', } as const; type TokenUpdatePayload = { token: TokenResource | null }; @@ -20,6 +21,7 @@ type InternalEvents = { [events.EnvironmentUpdate]: null; [events.SessionTokenResolved]: null; [events.SignInUpdate]: SignInUpdatePayload; + [events.SignInError]: any; }; export const eventBus = createEventBus(); diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 3b9e32c7c08..6f21627a46b 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -30,6 +30,7 @@ import type { SignInIdentifier, SignInJSON, SignInJSONSnapshot, + SignInBetaResource, SignInResource, SignInSecondFactor, SignInStartEmailLinkFlowParams, @@ -83,9 +84,14 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); + __internal_beta: SignInBeta | null = new SignInBeta(this); + __internal_basePost; + constructor(data: SignInJSON | SignInJSONSnapshot | null = null) { super(); this.fromJSON(data); + + this.__internal_basePost = this._basePost; } create = (params: SignInCreateParams): Promise => { @@ -473,3 +479,26 @@ export class SignIn extends BaseResource implements SignInResource { }; } } + +class SignInBeta implements SignInBetaResource { + constructor(readonly resource: SignIn) {} + + get status() { + return this.resource.status; + } + + async password({ identifier, password }: { identifier: string; password: string }): Promise<{ error: unknown }> { + eventBus.emit('signin:error', null); + try { + await this.resource.__internal_basePost({ + path: this.resource.pathRoot, + body: { identifier, password }, + }); + } catch (err) { + eventBus.emit('signin:error', err); + return { error: err }; + } + + return { error: null }; + } +} diff --git a/packages/clerk-js/src/core/signals.ts b/packages/clerk-js/src/core/signals.ts index 9c49086bb54..11d5f3baf40 100644 --- a/packages/clerk-js/src/core/signals.ts +++ b/packages/clerk-js/src/core/signals.ts @@ -1,5 +1,17 @@ -import { signal } from 'alien-signals'; +import { signal, computed } from 'alien-signals'; import type { SignIn } from './resources/SignIn'; export const signInSignal = signal<{ resource: SignIn | null }>({ resource: null }); +export const signInErrorSignal = signal<{ errors: unknown }>({ errors: null }); + +export const signInComputedSignal = computed(() => { + const signIn = signInSignal().resource; + const errors = signInErrorSignal().errors; + + if (!signIn) { + return { errors: null, signIn: null }; + } + + return { errors, signIn: signIn.__internal_beta }; +}); diff --git a/packages/clerk-js/src/core/state.ts b/packages/clerk-js/src/core/state.ts index cb08adb1a98..16f0337a085 100644 --- a/packages/clerk-js/src/core/state.ts +++ b/packages/clerk-js/src/core/state.ts @@ -2,19 +2,26 @@ import type { State as StateInterface } from '@clerk/types'; import { computed, effect } from 'alien-signals'; import { eventBus, type SignInUpdatePayload } from './events'; -import { signInSignal } from './signals'; +import { signInComputedSignal, signInErrorSignal, signInSignal } from './signals'; export class State implements StateInterface { - signInSignal = signInSignal; + signInResourceSignal = signInSignal; + signInErrorSignal = signInErrorSignal; + signInSignal = signInComputedSignal; __internal_effect = effect; __internal_computed = computed; constructor() { eventBus.on('signin:update', this.onSignInUpdated); + eventBus.on('signin:error', this.onSignInError); } private onSignInUpdated = (payload: SignInUpdatePayload) => { - this.signInSignal({ resource: payload.resource }); + this.signInResourceSignal({ resource: payload.resource }); + }; + + private onSignInError = (error: unknown) => { + this.signInErrorSignal({ errors: error }); }; } diff --git a/packages/react/src/hooks/useClerkSignal.ts b/packages/react/src/hooks/useClerkSignal.ts index 84976498da9..99effd91542 100644 --- a/packages/react/src/hooks/useClerkSignal.ts +++ b/packages/react/src/hooks/useClerkSignal.ts @@ -1,10 +1,10 @@ -import type { SignInResource } from '@clerk/types'; +import type { SignInBetaResource } from '@clerk/types'; import { useCallback, useSyncExternalStore } from 'react'; import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; import { useAssertWrappedByClerkProvider } from './useAssertWrappedByClerkProvider'; -function useClerkSignal(signal: 'signIn'): { isLoaded: boolean; signIn: SignInResource | null } { +function useClerkSignal(signal: 'signIn'): { errors: unknown; signIn: SignInBetaResource | null } | null { useAssertWrappedByClerkProvider('useSignInSignal'); const clerk = useIsomorphicClerkContext(); @@ -36,7 +36,7 @@ function useClerkSignal(signal: 'signIn'): { isLoaded: boolean; signIn: SignInRe switch (signal) { case 'signIn': - return clerk.__internal_state.signInSignal().resource; + return clerk.__internal_state.signInSignal(); default: throw new Error(`Unknown signal: ${signal}`); } @@ -44,10 +44,7 @@ function useClerkSignal(signal: 'signIn'): { isLoaded: boolean; signIn: SignInRe const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot); - return { - isLoaded: clerk.loaded, - [signal]: value, - }; + return value; } export function useSignInSignal() { diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts index 0f8ccdbde66..a54ada5f642 100644 --- a/packages/types/src/signIn.ts +++ b/packages/types/src/signIn.ts @@ -125,6 +125,11 @@ export interface SignInResource extends ClerkResource { __internal_toSnapshot: () => SignInJSONSnapshot; } +export interface SignInBetaResource { + status: SignInStatus | null; + password: (params: { identifier: string; password: string }) => Promise<{ error: unknown }>; +} + export type SignInStatus = | 'needs_identifier' | 'needs_first_factor' diff --git a/packages/types/src/state.ts b/packages/types/src/state.ts index f0de660f3bd..a5a908a249b 100644 --- a/packages/types/src/state.ts +++ b/packages/types/src/state.ts @@ -1,11 +1,12 @@ -import type { SignInResource } from './signIn'; +import type { SignInBetaResource } from './signIn'; export interface State { signInSignal: { (): { - resource: SignInResource | null; + errors: unknown; + signIn: SignInBetaResource | null; }; - (value: { resource: SignInResource | null }): void; + (value: { errors: unknown; signIn: SignInBetaResource | null }): void; }; __internal_effect: (callback: () => void) => () => void; __internal_computed: (getter: (previousValue?: T) => T) => () => T; From 57ef049d6c08987fcb4aaa36f6c371f4e36c0a05 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Tue, 5 Aug 2025 16:05:41 -0500 Subject: [PATCH 04/13] feat(clerk-js,types): Rename to SignInFuture, use resource-agnostic events --- packages/clerk-js/src/core/events.ts | 13 +- .../clerk-js/src/core/resources/SignIn.ts | 119 +++++++++++++++++- packages/clerk-js/src/core/state.ts | 20 +-- packages/react/src/hooks/useClerkSignal.ts | 4 +- packages/types/src/signIn.ts | 13 +- packages/types/src/state.ts | 6 +- 6 files changed, 150 insertions(+), 25 deletions(-) diff --git a/packages/clerk-js/src/core/events.ts b/packages/clerk-js/src/core/events.ts index 3fe58fe0178..0e4f54d433e 100644 --- a/packages/clerk-js/src/core/events.ts +++ b/packages/clerk-js/src/core/events.ts @@ -1,27 +1,28 @@ import { createEventBus } from '@clerk/shared/eventBus'; import type { TokenResource } from '@clerk/types'; -import type { SignIn } from './resources'; +import { BaseResource } from './resources/Base'; export const events = { TokenUpdate: 'token:update', UserSignOut: 'user:signOut', EnvironmentUpdate: 'environment:update', SessionTokenResolved: 'session:tokenResolved', - SignInUpdate: 'signin:update', - SignInError: 'signin:error', + ResourceUpdate: 'resource:update', + ResourceError: 'resource:error', } as const; type TokenUpdatePayload = { token: TokenResource | null }; -export type SignInUpdatePayload = { resource: SignIn }; +export type ResourceUpdatePayload = { resource: BaseResource }; +export type ResourceErrorPayload = { resource: BaseResource; error: unknown }; type InternalEvents = { [events.TokenUpdate]: TokenUpdatePayload; [events.UserSignOut]: null; [events.EnvironmentUpdate]: null; [events.SessionTokenResolved]: null; - [events.SignInUpdate]: SignInUpdatePayload; - [events.SignInError]: any; + [events.ResourceUpdate]: ResourceUpdatePayload; + [events.ResourceError]: ResourceErrorPayload; }; export const eventBus = createEventBus(); diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 6f21627a46b..f21483b9e95 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -30,7 +30,7 @@ import type { SignInIdentifier, SignInJSON, SignInJSONSnapshot, - SignInBetaResource, + SignInFutureResource, SignInResource, SignInSecondFactor, SignInStartEmailLinkFlowParams, @@ -39,6 +39,7 @@ import type { Web3Provider, Web3SignatureConfig, Web3SignatureFactor, + OAuthStrategy, } from '@clerk/types'; import { @@ -84,7 +85,7 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); - __internal_beta: SignInBeta | null = new SignInBeta(this); + __internal_beta: SignInFuture | null = new SignInFuture(this); __internal_basePost; constructor(data: SignInJSON | SignInJSONSnapshot | null = null) { @@ -459,7 +460,7 @@ export class SignIn extends BaseResource implements SignInResource { this.userData = new UserData(data.user_data); } - eventBus.emit('signin:update', { resource: this }); + eventBus.emit('resource:update', { resource: this }); return this; } @@ -480,22 +481,128 @@ export class SignIn extends BaseResource implements SignInResource { } } -class SignInBeta implements SignInBetaResource { +class SignInFuture implements SignInFutureResource { + emailCode = { + sendCode: this.sendEmailCode.bind(this), + verifyCode: this.verifyEmailCode.bind(this), + }; + constructor(readonly resource: SignIn) {} get status() { return this.resource.status; } + async create(params: { + identifier?: string; + strategy?: OAuthStrategy | 'saml' | 'enterprise_sso'; + redirectUrl?: string; + actionCompleteRedirectUrl?: string; + }): Promise<{ error: unknown }> { + eventBus.emit('resource:error', { resource: this.resource, error: null }); + try { + await this.resource.__internal_basePost({ + path: this.resource.pathRoot, + body: params, + }); + + return { error: null }; + } catch (err) { + eventBus.emit('resource:error', { resource: this.resource, error: err }); + return { error: err }; + } + } + async password({ identifier, password }: { identifier: string; password: string }): Promise<{ error: unknown }> { - eventBus.emit('signin:error', null); + eventBus.emit('resource:error', { resource: this.resource, error: null }); try { await this.resource.__internal_basePost({ path: this.resource.pathRoot, body: { identifier, password }, }); } catch (err) { - eventBus.emit('signin:error', err); + eventBus.emit('resource:error', { resource: this.resource, error: err }); + return { error: err }; + } + + return { error: null }; + } + + async sendEmailCode({ email }: { email: string }): Promise<{ error: unknown }> { + eventBus.emit('resource:error', { resource: this.resource, error: null }); + try { + if (!this.resource.id) { + await this.create({ identifier: email }); + } + + const emailCodeFactor = this.resource.supportedFirstFactors?.find(f => f.strategy === 'email_code'); + + if (!emailCodeFactor) { + throw new Error('Email code factor not found'); + } + + const { emailAddressId } = emailCodeFactor; + await this.resource.__internal_basePost({ + body: { emailAddressId, strategy: 'email_code' }, + action: 'prepare_first_factor', + }); + } catch (err: unknown) { + eventBus.emit('resource:error', { resource: this.resource, error: err }); + return { error: err }; + } + + return { error: null }; + } + + async verifyEmailCode({ code }: { code: string }): Promise<{ error: unknown }> { + eventBus.emit('resource:error', { resource: this.resource, error: null }); + try { + await this.resource.__internal_basePost({ + body: { code, strategy: 'email_code' }, + action: 'attempt_first_factor', + }); + } catch (err: unknown) { + eventBus.emit('resource:error', { resource: this.resource, error: err }); + return { error: err }; + } + + return { error: null }; + } + + async sso({ + flow = 'auto', + strategy, + redirectUrl, + redirectUrlComplete, + }: { + flow?: 'auto' | 'modal'; + strategy: OAuthStrategy | 'saml' | 'enterprise_sso'; + redirectUrl: string; + redirectUrlComplete: string; + }): Promise<{ error: unknown }> { + eventBus.emit('resource:error', { resource: this.resource, error: null }); + try { + if (flow !== 'auto') { + throw new Error('modal flow is not supported yet'); + } + + const redirectUrlWithAuthToken = SignIn.clerk.buildUrlWithAuth(redirectUrl); + + if (!this.resource.id) { + await this.create({ + strategy, + redirectUrl: redirectUrlWithAuthToken, + actionCompleteRedirectUrl: redirectUrlComplete, + }); + } + + const { status, externalVerificationRedirectURL } = this.resource.firstFactorVerification; + + if (status === 'unverified' && externalVerificationRedirectURL) { + windowNavigate(externalVerificationRedirectURL); + } + } catch (err: unknown) { + eventBus.emit('resource:error', { resource: this.resource, error: err }); return { error: err }; } diff --git a/packages/clerk-js/src/core/state.ts b/packages/clerk-js/src/core/state.ts index 16f0337a085..785b5806bbe 100644 --- a/packages/clerk-js/src/core/state.ts +++ b/packages/clerk-js/src/core/state.ts @@ -1,8 +1,10 @@ import type { State as StateInterface } from '@clerk/types'; import { computed, effect } from 'alien-signals'; -import { eventBus, type SignInUpdatePayload } from './events'; +import { eventBus } from './events'; import { signInComputedSignal, signInErrorSignal, signInSignal } from './signals'; +import { BaseResource } from './resources/Base'; +import { SignIn } from './resources/SignIn'; export class State implements StateInterface { signInResourceSignal = signInSignal; @@ -13,15 +15,19 @@ export class State implements StateInterface { __internal_computed = computed; constructor() { - eventBus.on('signin:update', this.onSignInUpdated); - eventBus.on('signin:error', this.onSignInError); + eventBus.on('resource:update', this.onResourceUpdated); + eventBus.on('resource:error', this.onResourceError); } - private onSignInUpdated = (payload: SignInUpdatePayload) => { - this.signInResourceSignal({ resource: payload.resource }); + private onResourceError = (payload: { resource: BaseResource; error: unknown }) => { + if (payload.resource instanceof SignIn) { + this.signInErrorSignal({ errors: payload.error }); + } }; - private onSignInError = (error: unknown) => { - this.signInErrorSignal({ errors: error }); + private onResourceUpdated = (payload: { resource: BaseResource }) => { + if (payload.resource instanceof SignIn) { + this.signInResourceSignal({ resource: payload.resource }); + } }; } diff --git a/packages/react/src/hooks/useClerkSignal.ts b/packages/react/src/hooks/useClerkSignal.ts index 99effd91542..37e9851ec6b 100644 --- a/packages/react/src/hooks/useClerkSignal.ts +++ b/packages/react/src/hooks/useClerkSignal.ts @@ -1,10 +1,10 @@ -import type { SignInBetaResource } from '@clerk/types'; +import type { SignInFutureResource } from '@clerk/types'; import { useCallback, useSyncExternalStore } from 'react'; import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; import { useAssertWrappedByClerkProvider } from './useAssertWrappedByClerkProvider'; -function useClerkSignal(signal: 'signIn'): { errors: unknown; signIn: SignInBetaResource | null } | null { +function useClerkSignal(signal: 'signIn'): { errors: unknown; signIn: SignInFutureResource | null } | null { useAssertWrappedByClerkProvider('useSignInSignal'); const clerk = useIsomorphicClerkContext(); diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts index a54ada5f642..43d7a5fc5e4 100644 --- a/packages/types/src/signIn.ts +++ b/packages/types/src/signIn.ts @@ -125,9 +125,20 @@ export interface SignInResource extends ClerkResource { __internal_toSnapshot: () => SignInJSONSnapshot; } -export interface SignInBetaResource { +export interface SignInFutureResource { status: SignInStatus | null; + create: (params: { identifier: string }) => Promise<{ error: unknown }>; password: (params: { identifier: string; password: string }) => Promise<{ error: unknown }>; + emailCode: { + sendCode: (params: { email: string }) => Promise<{ error: unknown }>; + verifyCode: (params: { code: string }) => Promise<{ error: unknown }>; + }; + sso: (params: { + flow?: 'auto' | 'modal'; + strategy: OAuthStrategy | 'saml' | 'enterprise_sso'; + redirectUrl: string; + redirectUrlComplete: string; + }) => Promise<{ error: unknown }>; } export type SignInStatus = diff --git a/packages/types/src/state.ts b/packages/types/src/state.ts index a5a908a249b..f24811d17ee 100644 --- a/packages/types/src/state.ts +++ b/packages/types/src/state.ts @@ -1,12 +1,12 @@ -import type { SignInBetaResource } from './signIn'; +import type { SignInFutureResource } from './signIn'; export interface State { signInSignal: { (): { errors: unknown; - signIn: SignInBetaResource | null; + signIn: SignInFutureResource | null; }; - (value: { errors: unknown; signIn: SignInBetaResource | null }): void; + (value: { errors: unknown; signIn: SignInFutureResource | null }): void; }; __internal_effect: (callback: () => void) => () => void; __internal_computed: (getter: (previousValue?: T) => T) => () => T; From a3614d73c731c06583327d10d00b32ac1eac5b43 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 10:35:19 -0500 Subject: [PATCH 05/13] fix(clerk-js): Rename internal_beta to internal_future --- packages/clerk-js/src/core/resources/SignIn.ts | 2 +- packages/clerk-js/src/core/signals.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index f21483b9e95..e23d323431e 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -85,7 +85,7 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); - __internal_beta: SignInFuture | null = new SignInFuture(this); + __internal_future: SignInFuture | null = new SignInFuture(this); __internal_basePost; constructor(data: SignInJSON | SignInJSONSnapshot | null = null) { diff --git a/packages/clerk-js/src/core/signals.ts b/packages/clerk-js/src/core/signals.ts index 11d5f3baf40..eb271e90634 100644 --- a/packages/clerk-js/src/core/signals.ts +++ b/packages/clerk-js/src/core/signals.ts @@ -13,5 +13,5 @@ export const signInComputedSignal = computed(() => { return { errors: null, signIn: null }; } - return { errors, signIn: signIn.__internal_beta }; + return { errors, signIn: signIn.__internal_future }; }); From 0ed14b616c48eb800525d29ffe7868abbd633a8f Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:15:28 -0500 Subject: [PATCH 06/13] chore(clerk-js): Narrow range for alien-signals --- packages/clerk-js/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/clerk-js/package.json b/packages/clerk-js/package.json index 6f2cb410986..3596f90864a 100644 --- a/packages/clerk-js/package.json +++ b/packages/clerk-js/package.json @@ -75,7 +75,7 @@ "@swc/helpers": "^0.5.17", "@zxcvbn-ts/core": "3.0.4", "@zxcvbn-ts/language-common": "3.0.4", - "alien-signals": "^2.0.5", + "alien-signals": "2.0.6", "browser-tabs-lock": "1.3.0", "copy-to-clipboard": "3.3.3", "core-js": "3.41.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9dc4f9ad7a4..2f1b19345eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -474,8 +474,8 @@ importers: specifier: 3.0.4 version: 3.0.4 alien-signals: - specifier: ^2.0.5 - version: 2.0.5 + specifier: 2.0.6 + version: 2.0.6 browser-tabs-lock: specifier: 1.3.0 version: 1.3.0 @@ -5882,8 +5882,8 @@ packages: alien-signals@1.0.9: resolution: {integrity: sha512-2dQYgGZHrW4pOYv0BWiw4cH/ElhwmLnQDcj/fdnRRF2OO3YBqgJXSleI1EbbXdQsuC5oCvr6+VKAOEElsmcx4Q==} - alien-signals@2.0.5: - resolution: {integrity: sha512-PdJB6+06nUNAClInE3Dweq7/2xVAYM64vvvS1IHVHSJmgeOtEdrAGyp7Z2oJtYm0B342/Exd2NT0uMJaThcjLQ==} + alien-signals@2.0.6: + resolution: {integrity: sha512-P3TxJSe31bUHBiblg59oU1PpaWPtmxF9GhJ/cB7OkgJ0qN/ifFSKUI25/v8ZhsT+lIG6ac8DpTOplXxORX6F3Q==} anser@1.4.10: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} @@ -21139,7 +21139,7 @@ snapshots: alien-signals@1.0.9: {} - alien-signals@2.0.5: {} + alien-signals@2.0.6: {} anser@1.4.10: {} From d82111cb83dd8081841088843ed840274ce7c165 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:18:19 -0500 Subject: [PATCH 07/13] fix(clerk-js): Lint --- packages/clerk-js/src/core/events.ts | 2 +- packages/clerk-js/src/core/resources/SignIn.ts | 8 +++----- packages/clerk-js/src/core/signals.ts | 2 +- packages/clerk-js/src/core/state.ts | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/clerk-js/src/core/events.ts b/packages/clerk-js/src/core/events.ts index 0e4f54d433e..858aa6d10ee 100644 --- a/packages/clerk-js/src/core/events.ts +++ b/packages/clerk-js/src/core/events.ts @@ -1,7 +1,7 @@ import { createEventBus } from '@clerk/shared/eventBus'; import type { TokenResource } from '@clerk/types'; -import { BaseResource } from './resources/Base'; +import type { BaseResource } from './resources/Base'; export const events = { TokenUpdate: 'token:update', diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index e23d323431e..d30713ff41c 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -16,6 +16,7 @@ import type { EmailCodeConfig, EmailLinkConfig, EnterpriseSSOConfig, + OAuthStrategy, PassKeyConfig, PasskeyFactor, PhoneCodeConfig, @@ -27,10 +28,10 @@ import type { SamlConfig, SignInCreateParams, SignInFirstFactor, + SignInFutureResource, SignInIdentifier, SignInJSON, SignInJSONSnapshot, - SignInFutureResource, SignInResource, SignInSecondFactor, SignInStartEmailLinkFlowParams, @@ -39,7 +40,6 @@ import type { Web3Provider, Web3SignatureConfig, Web3SignatureFactor, - OAuthStrategy, } from '@clerk/types'; import { @@ -86,13 +86,11 @@ export class SignIn extends BaseResource implements SignInResource { userData: UserData = new UserData(null); __internal_future: SignInFuture | null = new SignInFuture(this); - __internal_basePost; + __internal_basePost = this._basePost.bind(this); constructor(data: SignInJSON | SignInJSONSnapshot | null = null) { super(); this.fromJSON(data); - - this.__internal_basePost = this._basePost; } create = (params: SignInCreateParams): Promise => { diff --git a/packages/clerk-js/src/core/signals.ts b/packages/clerk-js/src/core/signals.ts index eb271e90634..781b082822a 100644 --- a/packages/clerk-js/src/core/signals.ts +++ b/packages/clerk-js/src/core/signals.ts @@ -1,4 +1,4 @@ -import { signal, computed } from 'alien-signals'; +import { computed, signal } from 'alien-signals'; import type { SignIn } from './resources/SignIn'; diff --git a/packages/clerk-js/src/core/state.ts b/packages/clerk-js/src/core/state.ts index 785b5806bbe..b18c07ca78b 100644 --- a/packages/clerk-js/src/core/state.ts +++ b/packages/clerk-js/src/core/state.ts @@ -2,9 +2,9 @@ import type { State as StateInterface } from '@clerk/types'; import { computed, effect } from 'alien-signals'; import { eventBus } from './events'; -import { signInComputedSignal, signInErrorSignal, signInSignal } from './signals'; -import { BaseResource } from './resources/Base'; +import type { BaseResource } from './resources/Base'; import { SignIn } from './resources/SignIn'; +import { signInComputedSignal, signInErrorSignal, signInSignal } from './signals'; export class State implements StateInterface { signInResourceSignal = signInSignal; From 253bd9c55650ea91f6b28899009fbe90d3b6bd68 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:07:02 -0500 Subject: [PATCH 08/13] chore(clerk-js): Add JSDoc comments --- packages/clerk-js/src/core/resources/SignIn.ts | 12 ++++++++++++ packages/types/src/clerk.ts | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index d30713ff41c..1585c731f79 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -85,7 +85,19 @@ export class SignIn extends BaseResource implements SignInResource { createdSessionId: string | null = null; userData: UserData = new UserData(null); + /** + * @experimental This experimental API is subject to change. + * + * An instance of `SignInFuture`, which has a different API than `SignIn`, intended to be used in custom flows. + */ __internal_future: SignInFuture | null = new SignInFuture(this); + + /** + * @internal Only used for internal purposes, and is not intended to be used directly. + * + * This property is used to provide access to underlying Client methods to `SignInFuture`, which wraps an instance + * of `SignIn`. + */ __internal_basePost = this._basePost.bind(this); constructor(data: SignInJSON | SignInJSONSnapshot | null = null) { diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index d395063a403..c571eb5ef5d 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -228,6 +228,12 @@ export interface Clerk { /** Current User. */ user: UserResource | null | undefined; + /** + * @experimental This experimental API is subject to change. + * + * Entrypoint for Clerk's Signal API containing resource signals along with accessible versions of `computed()` and + * `effect()` that can be used to subscribe to changes from Signals. + */ __internal_state: State | undefined; /** From 18d4b576598eb7e23f99cadafbb0a4db61a1ae9d Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:19:14 -0500 Subject: [PATCH 09/13] chore(repo): Add empty changeset --- .changeset/early-toys-greet.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/early-toys-greet.md diff --git a/.changeset/early-toys-greet.md b/.changeset/early-toys-greet.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/early-toys-greet.md @@ -0,0 +1,2 @@ +--- +--- From 63c4a45f57640a328428f5d07de4cfb0821c22af Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:26:22 -0500 Subject: [PATCH 10/13] chore(clerk-js): Add JSDoc comments --- packages/types/src/state.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/types/src/state.ts b/packages/types/src/state.ts index f24811d17ee..8f91dde4412 100644 --- a/packages/types/src/state.ts +++ b/packages/types/src/state.ts @@ -1,6 +1,9 @@ import type { SignInFutureResource } from './signIn'; export interface State { + /** + * A Signal that updates when the underlying `SignIn` resource changes, including errors. + */ signInSignal: { (): { errors: unknown; @@ -8,6 +11,23 @@ export interface State { }; (value: { errors: unknown; signIn: SignInFutureResource | null }): void; }; + + /** + * @experimental This experimental API is subject to change. + * + * An alias for `effect()` from `alien-signals`, which can be used to subscribe to changes from Signals. + * + * @see https://github.com/stackblitz/alien-signals#usage + */ __internal_effect: (callback: () => void) => () => void; + + /** + * @experimental This experimental API is subject to change. + * + * An alias for `computed()` from `alien-signals`, which can be used to create a computed Signal that updates when + * its dependencies change. + * + * @see https://github.com/stackblitz/alien-signals#usage + */ __internal_computed: (getter: (previousValue?: T) => T) => () => T; } From 1bd1005075299e12ea10afcaa0c5a871b2eb644f Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:31:50 -0500 Subject: [PATCH 11/13] chore(clerk-js): Bump bundle limits --- packages/clerk-js/bundlewatch.config.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index dc2341dcfb5..133d55eec24 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -1,9 +1,9 @@ { "files": [ - { "path": "./dist/clerk.js", "maxSize": "618KB" }, - { "path": "./dist/clerk.browser.js", "maxSize": "74KB" }, - { "path": "./dist/clerk.legacy.browser.js", "maxSize": "115.08KB" }, - { "path": "./dist/clerk.headless*.js", "maxSize": "55.2KB" }, + { "path": "./dist/clerk.js", "maxSize": "619KB" }, + { "path": "./dist/clerk.browser.js", "maxSize": "75KB" }, + { "path": "./dist/clerk.legacy.browser.js", "maxSize": "117KB" }, + { "path": "./dist/clerk.headless*.js", "maxSize": "57KB" }, { "path": "./dist/ui-common*.js", "maxSize": "113KB" }, { "path": "./dist/ui-common*.legacy.*.js", "maxSize": "118KB" }, { "path": "./dist/vendors*.js", "maxSize": "40.2KB" }, From e08b6aab80c17163a07411fa259372746fd2b695 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Thu, 7 Aug 2025 12:34:54 -0500 Subject: [PATCH 12/13] chore(repo): Add changeset --- .changeset/dull-cups-accept.md | 7 +++++++ .changeset/early-toys-greet.md | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/dull-cups-accept.md delete mode 100644 .changeset/early-toys-greet.md diff --git a/.changeset/dull-cups-accept.md b/.changeset/dull-cups-accept.md new file mode 100644 index 00000000000..e9c91de2f7e --- /dev/null +++ b/.changeset/dull-cups-accept.md @@ -0,0 +1,7 @@ +--- +'@clerk/clerk-js': patch +'@clerk/clerk-react': patch +'@clerk/types': patch +--- + +[Experimental] Signals diff --git a/.changeset/early-toys-greet.md b/.changeset/early-toys-greet.md deleted file mode 100644 index a845151cc84..00000000000 --- a/.changeset/early-toys-greet.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- From 37f2eca0f22ce36c78612ec5fda0251859d01ac0 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Thu, 7 Aug 2025 12:44:28 -0500 Subject: [PATCH 13/13] chore(clerk-js): Bump bundle limit --- packages/clerk-js/bundlewatch.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index cbd451b11e1..55893738a3c 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -1,6 +1,6 @@ { "files": [ - { "path": "./dist/clerk.js", "maxSize": "620KB" }, + { "path": "./dist/clerk.js", "maxSize": "621KB" }, { "path": "./dist/clerk.browser.js", "maxSize": "75KB" }, { "path": "./dist/clerk.legacy.browser.js", "maxSize": "117KB" }, { "path": "./dist/clerk.headless*.js", "maxSize": "57KB" },