@weirdfingers/boards-auth-supabase 0.9.13 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -184,7 +184,7 @@ var SupabaseAuthProvider = class extends import_boards.BaseAuthProvider {
184
184
  } = await this.supabase.auth.refreshSession();
185
185
  if (error) throw error;
186
186
  return session?.access_token || null;
187
- } catch (_err) {
187
+ } catch {
188
188
  return null;
189
189
  }
190
190
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/SupabaseAuthProvider.ts","../src/types.ts"],"sourcesContent":["/**\n * Supabase authentication provider package for Boards.\n *\n * This package provides a tree-shakable Supabase auth provider\n * that can be used independently of the main boards-frontend package.\n */\n\nexport { SupabaseAuthProvider } from './SupabaseAuthProvider';\nexport type {\n SupabaseConfig,\n SupabaseConfigWithCredentials,\n SupabaseConfigWithClient,\n SupabaseAuthOptions,\n} from './types';\nexport { isCredentialsConfig, isClientConfig } from './types';\n\n// Re-export core types for convenience\nexport type {\n AuthState,\n User,\n AuthProviderConfig,\n AuthContextValue\n} from '@weirdfingers/boards';\n","/**\n * Supabase authentication provider.\n */\n\nimport { BaseAuthProvider, AuthState, User } from \"@weirdfingers/boards\";\nimport type { SupabaseClient, Session, AuthChangeEvent } from \"@supabase/supabase-js\";\nimport type { SupabaseConfig } from \"./types\";\nimport { isClientConfig, isCredentialsConfig } from \"./types\";\n\nexport class SupabaseAuthProvider extends BaseAuthProvider {\n protected config: SupabaseConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private supabase: SupabaseClient | null = null;\n\n constructor(config: SupabaseConfig) {\n super(config);\n this.config = config;\n\n this.currentState = {\n user: null,\n status: \"loading\",\n signIn: this.signIn.bind(this) as AuthState[\"signIn\"],\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n }\n\n async initialize(): Promise<void> {\n try {\n if (isClientConfig(this.config)) {\n // Use the provided client directly\n this.supabase = this.config.client;\n } else if (isCredentialsConfig(this.config)) {\n // Dynamically import Supabase and create a new client\n const { createClient } = await import(\"@supabase/supabase-js\");\n\n this.supabase = createClient(this.config.url, this.config.anonKey, {\n auth: {\n persistSession: this.config.options?.persistSession ?? true,\n detectSessionInUrl: this.config.options?.detectSessionInUrl ?? true,\n ...(this.config.options?.headers && {\n headers: this.config.options.headers,\n }),\n },\n });\n } else {\n throw new Error(\n \"Invalid configuration: provide either { url, anonKey } or { client }\"\n );\n }\n\n // Set up auth state listener\n this.supabase.auth.onAuthStateChange(\n (event: AuthChangeEvent, session: Session | null) => {\n this.handleAuthStateChange(event, session);\n }\n );\n\n // Get initial session\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n this.handleAuthStateChange(\"INITIAL_SESSION\", session);\n } catch (error) {\n console.error(\"Failed to initialize Supabase:\", error);\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(\n opts: {\n email?: string;\n password?: string;\n provider?: \"google\" | \"github\" | \"discord\" | \"twitter\" | \"facebook\";\n type?: \"signup\" | \"signin\" | \"magic_link\";\n options?: {\n data?: Record<string, unknown>;\n redirectTo?: string;\n shouldCreateUser?: boolean;\n };\n } = {}\n ): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n this.updateState({ status: \"loading\" });\n\n try {\n // Social provider login\n if (opts.provider) {\n const tenantId = this.getTenantId();\n const { error } = await this.supabase.auth.signInWithOAuth({\n provider: opts.provider,\n options: {\n redirectTo: opts.options?.redirectTo || window.location.origin,\n ...(tenantId !== \"default\" && {\n queryParams: { tenant: tenantId },\n }),\n },\n });\n\n if (error) throw error;\n return; // OAuth redirects, so we don't update state here\n }\n\n // Magic link\n if (opts.type === \"magic_link\" && opts.email) {\n const { error } = await this.supabase.auth.signInWithOtp({\n email: opts.email,\n options: opts.options,\n });\n\n if (error) throw error;\n this.updateState({ status: \"unauthenticated\" }); // Wait for email click\n return;\n }\n\n // Email/password signup\n if (opts.type === \"signup\" && opts.email && opts.password) {\n const { error } = await this.supabase.auth.signUp({\n email: opts.email,\n password: opts.password,\n options: opts.options,\n });\n\n if (error) throw error;\n return; // May need email confirmation\n }\n\n // Email/password signin (default)\n if (opts.email && opts.password) {\n const { error } = await this.supabase.auth.signInWithPassword({\n email: opts.email,\n password: opts.password,\n });\n\n if (error) throw error;\n return; // State will update via onAuthStateChange\n }\n\n throw new Error(\"Invalid sign in options provided\");\n } catch (error) {\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async signOut(): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.signOut();\n if (error) throw error;\n\n // State will update via onAuthStateChange\n }\n\n async getToken(): Promise<string | null> {\n if (!this.supabase) return null;\n\n try {\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n return session?.access_token || null;\n } catch (error) {\n console.error(\"Failed to get token:\", error);\n return null;\n }\n }\n\n async getUser(): Promise<User | null> {\n return this.currentState.user;\n }\n\n async refreshToken(): Promise<string | null> {\n if (!this.supabase) return null;\n try {\n const {\n data: { session },\n error,\n } = await this.supabase.auth.refreshSession();\n if (error) throw error;\n return session?.access_token || null;\n } catch (_err) {\n return null;\n }\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n // Supabase client cleanup is handled automatically\n }\n\n private handleAuthStateChange(\n _event: AuthChangeEvent | \"INITIAL_SESSION\",\n session: Session | null\n ): void {\n if (session) {\n const user: User = {\n id: session.user.id,\n email: session.user.email ?? \"\",\n name:\n session.user.user_metadata?.display_name ||\n session.user.user_metadata?.full_name ||\n session.user.user_metadata?.name ||\n session.user.email?.split(\"@\")[0],\n avatar:\n session.user.user_metadata?.avatar_url ||\n session.user.user_metadata?.picture,\n metadata: {\n ...session.user.user_metadata,\n provider: \"supabase\",\n subject: session.user.id,\n },\n credits: { balance: 0, reserved: 0 },\n };\n\n this.updateState({ user, status: \"authenticated\" });\n } else {\n this.updateState({ user: null, status: \"unauthenticated\" });\n }\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n\n /**\n * Get the tenant ID from config.\n */\n protected override getTenantId(): string {\n return this.config.tenantId ?? \"default\";\n }\n\n /**\n * Get the underlying Supabase client for advanced operations.\n */\n getSupabaseClient(): SupabaseClient | null {\n return this.supabase;\n }\n\n /**\n * Reset password for email.\n */\n async resetPassword(email: string, redirectTo?: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.resetPasswordForEmail(email, {\n redirectTo: redirectTo || `${window.location.origin}/reset-password`,\n });\n\n if (error) throw error;\n }\n\n /**\n * Update user password.\n */\n async updatePassword(newPassword: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.updateUser({\n password: newPassword,\n });\n\n if (error) throw error;\n }\n}\n","/**\n * Supabase auth provider types.\n */\n\nimport type { AuthProviderConfig } from \"@weirdfingers/boards\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/**\n * Options for Supabase client configuration.\n */\nexport interface SupabaseAuthOptions {\n debug?: boolean;\n persistSession?: boolean;\n detectSessionInUrl?: boolean;\n headers?: Record<string, string>;\n}\n\n/**\n * Base configuration shared by all config variants.\n */\ninterface SupabaseConfigBase extends AuthProviderConfig {\n /**\n * Optional tenant ID for multi-tenant setups.\n */\n tenantId?: string;\n}\n\n/**\n * Configuration for creating a new Supabase client.\n */\nexport interface SupabaseConfigWithCredentials extends SupabaseConfigBase {\n /**\n * Supabase project URL.\n */\n url: string;\n\n /**\n * Supabase anonymous/public key.\n */\n anonKey: string;\n\n /**\n * Additional Supabase client options.\n */\n options?: SupabaseAuthOptions;\n\n /**\n * When using credentials, client should not be provided.\n */\n client?: never;\n}\n\n/**\n * Configuration for using an existing Supabase client.\n */\nexport interface SupabaseConfigWithClient extends SupabaseConfigBase {\n /**\n * Pre-configured Supabase client instance.\n */\n client: SupabaseClient;\n\n /**\n * When using an existing client, credentials should not be provided.\n */\n url?: never;\n anonKey?: never;\n options?: never;\n}\n\n/**\n * Supabase configuration - either provide credentials to create a new client,\n * or provide an existing client instance.\n */\nexport type SupabaseConfig = SupabaseConfigWithCredentials | SupabaseConfigWithClient;\n\n/**\n * Type guard to check if config uses credentials.\n */\nexport function isCredentialsConfig(\n config: SupabaseConfig\n): config is SupabaseConfigWithCredentials {\n return \"url\" in config && \"anonKey\" in config && !(\"client\" in config && config.client);\n}\n\n/**\n * Type guard to check if config uses an existing client.\n */\nexport function isClientConfig(config: SupabaseConfig): config is SupabaseConfigWithClient {\n return \"client\" in config && config.client !== undefined;\n}\n"],"mappings":"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","names":["session"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/SupabaseAuthProvider.ts","../src/types.ts"],"sourcesContent":["/**\n * Supabase authentication provider package for Boards.\n *\n * This package provides a tree-shakable Supabase auth provider\n * that can be used independently of the main boards-frontend package.\n */\n\nexport { SupabaseAuthProvider } from './SupabaseAuthProvider';\nexport type {\n SupabaseConfig,\n SupabaseConfigWithCredentials,\n SupabaseConfigWithClient,\n SupabaseAuthOptions,\n} from './types';\nexport { isCredentialsConfig, isClientConfig } from './types';\n\n// Re-export core types for convenience\nexport type {\n AuthState,\n User,\n AuthProviderConfig,\n AuthContextValue\n} from '@weirdfingers/boards';\n","/**\n * Supabase authentication provider.\n */\n\nimport { BaseAuthProvider, AuthState, User } from \"@weirdfingers/boards\";\nimport type { SupabaseClient, Session, AuthChangeEvent } from \"@supabase/supabase-js\";\nimport type { SupabaseConfig } from \"./types\";\nimport { isClientConfig, isCredentialsConfig } from \"./types\";\n\nexport class SupabaseAuthProvider extends BaseAuthProvider {\n protected config: SupabaseConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private supabase: SupabaseClient | null = null;\n\n constructor(config: SupabaseConfig) {\n super(config);\n this.config = config;\n\n this.currentState = {\n user: null,\n status: \"loading\",\n signIn: this.signIn.bind(this) as AuthState[\"signIn\"],\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n }\n\n async initialize(): Promise<void> {\n try {\n if (isClientConfig(this.config)) {\n // Use the provided client directly\n this.supabase = this.config.client;\n } else if (isCredentialsConfig(this.config)) {\n // Dynamically import Supabase and create a new client\n const { createClient } = await import(\"@supabase/supabase-js\");\n\n this.supabase = createClient(this.config.url, this.config.anonKey, {\n auth: {\n persistSession: this.config.options?.persistSession ?? true,\n detectSessionInUrl: this.config.options?.detectSessionInUrl ?? true,\n ...(this.config.options?.headers && {\n headers: this.config.options.headers,\n }),\n },\n });\n } else {\n throw new Error(\n \"Invalid configuration: provide either { url, anonKey } or { client }\"\n );\n }\n\n // Set up auth state listener\n this.supabase.auth.onAuthStateChange(\n (event: AuthChangeEvent, session: Session | null) => {\n this.handleAuthStateChange(event, session);\n }\n );\n\n // Get initial session\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n this.handleAuthStateChange(\"INITIAL_SESSION\", session);\n } catch (error) {\n console.error(\"Failed to initialize Supabase:\", error);\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(\n opts: {\n email?: string;\n password?: string;\n provider?: \"google\" | \"github\" | \"discord\" | \"twitter\" | \"facebook\";\n type?: \"signup\" | \"signin\" | \"magic_link\";\n options?: {\n data?: Record<string, unknown>;\n redirectTo?: string;\n shouldCreateUser?: boolean;\n };\n } = {}\n ): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n this.updateState({ status: \"loading\" });\n\n try {\n // Social provider login\n if (opts.provider) {\n const tenantId = this.getTenantId();\n const { error } = await this.supabase.auth.signInWithOAuth({\n provider: opts.provider,\n options: {\n redirectTo: opts.options?.redirectTo || window.location.origin,\n ...(tenantId !== \"default\" && {\n queryParams: { tenant: tenantId },\n }),\n },\n });\n\n if (error) throw error;\n return; // OAuth redirects, so we don't update state here\n }\n\n // Magic link\n if (opts.type === \"magic_link\" && opts.email) {\n const { error } = await this.supabase.auth.signInWithOtp({\n email: opts.email,\n options: opts.options,\n });\n\n if (error) throw error;\n this.updateState({ status: \"unauthenticated\" }); // Wait for email click\n return;\n }\n\n // Email/password signup\n if (opts.type === \"signup\" && opts.email && opts.password) {\n const { error } = await this.supabase.auth.signUp({\n email: opts.email,\n password: opts.password,\n options: opts.options,\n });\n\n if (error) throw error;\n return; // May need email confirmation\n }\n\n // Email/password signin (default)\n if (opts.email && opts.password) {\n const { error } = await this.supabase.auth.signInWithPassword({\n email: opts.email,\n password: opts.password,\n });\n\n if (error) throw error;\n return; // State will update via onAuthStateChange\n }\n\n throw new Error(\"Invalid sign in options provided\");\n } catch (error) {\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async signOut(): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.signOut();\n if (error) throw error;\n\n // State will update via onAuthStateChange\n }\n\n async getToken(): Promise<string | null> {\n if (!this.supabase) return null;\n\n try {\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n return session?.access_token || null;\n } catch (error) {\n console.error(\"Failed to get token:\", error);\n return null;\n }\n }\n\n async getUser(): Promise<User | null> {\n return this.currentState.user;\n }\n\n async refreshToken(): Promise<string | null> {\n if (!this.supabase) return null;\n try {\n const {\n data: { session },\n error,\n } = await this.supabase.auth.refreshSession();\n if (error) throw error;\n return session?.access_token || null;\n } catch {\n return null;\n }\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n // Supabase client cleanup is handled automatically\n }\n\n private handleAuthStateChange(\n _event: AuthChangeEvent | \"INITIAL_SESSION\",\n session: Session | null\n ): void {\n if (session) {\n const user: User = {\n id: session.user.id,\n email: session.user.email ?? \"\",\n name:\n session.user.user_metadata?.display_name ||\n session.user.user_metadata?.full_name ||\n session.user.user_metadata?.name ||\n session.user.email?.split(\"@\")[0],\n avatar:\n session.user.user_metadata?.avatar_url ||\n session.user.user_metadata?.picture,\n metadata: {\n ...session.user.user_metadata,\n provider: \"supabase\",\n subject: session.user.id,\n },\n credits: { balance: 0, reserved: 0 },\n };\n\n this.updateState({ user, status: \"authenticated\" });\n } else {\n this.updateState({ user: null, status: \"unauthenticated\" });\n }\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n\n /**\n * Get the tenant ID from config.\n */\n protected override getTenantId(): string {\n return this.config.tenantId ?? \"default\";\n }\n\n /**\n * Get the underlying Supabase client for advanced operations.\n */\n getSupabaseClient(): SupabaseClient | null {\n return this.supabase;\n }\n\n /**\n * Reset password for email.\n */\n async resetPassword(email: string, redirectTo?: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.resetPasswordForEmail(email, {\n redirectTo: redirectTo || `${window.location.origin}/reset-password`,\n });\n\n if (error) throw error;\n }\n\n /**\n * Update user password.\n */\n async updatePassword(newPassword: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.updateUser({\n password: newPassword,\n });\n\n if (error) throw error;\n }\n}\n","/**\n * Supabase auth provider types.\n */\n\nimport type { AuthProviderConfig } from \"@weirdfingers/boards\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/**\n * Options for Supabase client configuration.\n */\nexport interface SupabaseAuthOptions {\n debug?: boolean;\n persistSession?: boolean;\n detectSessionInUrl?: boolean;\n headers?: Record<string, string>;\n}\n\n/**\n * Base configuration shared by all config variants.\n */\ninterface SupabaseConfigBase extends AuthProviderConfig {\n /**\n * Optional tenant ID for multi-tenant setups.\n */\n tenantId?: string;\n}\n\n/**\n * Configuration for creating a new Supabase client.\n */\nexport interface SupabaseConfigWithCredentials extends SupabaseConfigBase {\n /**\n * Supabase project URL.\n */\n url: string;\n\n /**\n * Supabase anonymous/public key.\n */\n anonKey: string;\n\n /**\n * Additional Supabase client options.\n */\n options?: SupabaseAuthOptions;\n\n /**\n * When using credentials, client should not be provided.\n */\n client?: never;\n}\n\n/**\n * Configuration for using an existing Supabase client.\n */\nexport interface SupabaseConfigWithClient extends SupabaseConfigBase {\n /**\n * Pre-configured Supabase client instance.\n */\n client: SupabaseClient;\n\n /**\n * When using an existing client, credentials should not be provided.\n */\n url?: never;\n anonKey?: never;\n options?: never;\n}\n\n/**\n * Supabase configuration - either provide credentials to create a new client,\n * or provide an existing client instance.\n */\nexport type SupabaseConfig = SupabaseConfigWithCredentials | SupabaseConfigWithClient;\n\n/**\n * Type guard to check if config uses credentials.\n */\nexport function isCredentialsConfig(\n config: SupabaseConfig\n): config is SupabaseConfigWithCredentials {\n return \"url\" in config && \"anonKey\" in config && !(\"client\" in config && config.client);\n}\n\n/**\n * Type guard to check if config uses an existing client.\n */\nexport function isClientConfig(config: SupabaseConfig): config is SupabaseConfigWithClient {\n return \"client\" in config && config.client !== undefined;\n}\n"],"mappings":"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","names":["session"]}
package/dist/index.mjs CHANGED
@@ -146,7 +146,7 @@ var SupabaseAuthProvider = class extends BaseAuthProvider {
146
146
  } = await this.supabase.auth.refreshSession();
147
147
  if (error) throw error;
148
148
  return session?.access_token || null;
149
- } catch (_err) {
149
+ } catch {
150
150
  return null;
151
151
  }
152
152
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SupabaseAuthProvider.ts","../src/types.ts"],"sourcesContent":["/**\n * Supabase authentication provider.\n */\n\nimport { BaseAuthProvider, AuthState, User } from \"@weirdfingers/boards\";\nimport type { SupabaseClient, Session, AuthChangeEvent } from \"@supabase/supabase-js\";\nimport type { SupabaseConfig } from \"./types\";\nimport { isClientConfig, isCredentialsConfig } from \"./types\";\n\nexport class SupabaseAuthProvider extends BaseAuthProvider {\n protected config: SupabaseConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private supabase: SupabaseClient | null = null;\n\n constructor(config: SupabaseConfig) {\n super(config);\n this.config = config;\n\n this.currentState = {\n user: null,\n status: \"loading\",\n signIn: this.signIn.bind(this) as AuthState[\"signIn\"],\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n }\n\n async initialize(): Promise<void> {\n try {\n if (isClientConfig(this.config)) {\n // Use the provided client directly\n this.supabase = this.config.client;\n } else if (isCredentialsConfig(this.config)) {\n // Dynamically import Supabase and create a new client\n const { createClient } = await import(\"@supabase/supabase-js\");\n\n this.supabase = createClient(this.config.url, this.config.anonKey, {\n auth: {\n persistSession: this.config.options?.persistSession ?? true,\n detectSessionInUrl: this.config.options?.detectSessionInUrl ?? true,\n ...(this.config.options?.headers && {\n headers: this.config.options.headers,\n }),\n },\n });\n } else {\n throw new Error(\n \"Invalid configuration: provide either { url, anonKey } or { client }\"\n );\n }\n\n // Set up auth state listener\n this.supabase.auth.onAuthStateChange(\n (event: AuthChangeEvent, session: Session | null) => {\n this.handleAuthStateChange(event, session);\n }\n );\n\n // Get initial session\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n this.handleAuthStateChange(\"INITIAL_SESSION\", session);\n } catch (error) {\n console.error(\"Failed to initialize Supabase:\", error);\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(\n opts: {\n email?: string;\n password?: string;\n provider?: \"google\" | \"github\" | \"discord\" | \"twitter\" | \"facebook\";\n type?: \"signup\" | \"signin\" | \"magic_link\";\n options?: {\n data?: Record<string, unknown>;\n redirectTo?: string;\n shouldCreateUser?: boolean;\n };\n } = {}\n ): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n this.updateState({ status: \"loading\" });\n\n try {\n // Social provider login\n if (opts.provider) {\n const tenantId = this.getTenantId();\n const { error } = await this.supabase.auth.signInWithOAuth({\n provider: opts.provider,\n options: {\n redirectTo: opts.options?.redirectTo || window.location.origin,\n ...(tenantId !== \"default\" && {\n queryParams: { tenant: tenantId },\n }),\n },\n });\n\n if (error) throw error;\n return; // OAuth redirects, so we don't update state here\n }\n\n // Magic link\n if (opts.type === \"magic_link\" && opts.email) {\n const { error } = await this.supabase.auth.signInWithOtp({\n email: opts.email,\n options: opts.options,\n });\n\n if (error) throw error;\n this.updateState({ status: \"unauthenticated\" }); // Wait for email click\n return;\n }\n\n // Email/password signup\n if (opts.type === \"signup\" && opts.email && opts.password) {\n const { error } = await this.supabase.auth.signUp({\n email: opts.email,\n password: opts.password,\n options: opts.options,\n });\n\n if (error) throw error;\n return; // May need email confirmation\n }\n\n // Email/password signin (default)\n if (opts.email && opts.password) {\n const { error } = await this.supabase.auth.signInWithPassword({\n email: opts.email,\n password: opts.password,\n });\n\n if (error) throw error;\n return; // State will update via onAuthStateChange\n }\n\n throw new Error(\"Invalid sign in options provided\");\n } catch (error) {\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async signOut(): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.signOut();\n if (error) throw error;\n\n // State will update via onAuthStateChange\n }\n\n async getToken(): Promise<string | null> {\n if (!this.supabase) return null;\n\n try {\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n return session?.access_token || null;\n } catch (error) {\n console.error(\"Failed to get token:\", error);\n return null;\n }\n }\n\n async getUser(): Promise<User | null> {\n return this.currentState.user;\n }\n\n async refreshToken(): Promise<string | null> {\n if (!this.supabase) return null;\n try {\n const {\n data: { session },\n error,\n } = await this.supabase.auth.refreshSession();\n if (error) throw error;\n return session?.access_token || null;\n } catch (_err) {\n return null;\n }\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n // Supabase client cleanup is handled automatically\n }\n\n private handleAuthStateChange(\n _event: AuthChangeEvent | \"INITIAL_SESSION\",\n session: Session | null\n ): void {\n if (session) {\n const user: User = {\n id: session.user.id,\n email: session.user.email ?? \"\",\n name:\n session.user.user_metadata?.display_name ||\n session.user.user_metadata?.full_name ||\n session.user.user_metadata?.name ||\n session.user.email?.split(\"@\")[0],\n avatar:\n session.user.user_metadata?.avatar_url ||\n session.user.user_metadata?.picture,\n metadata: {\n ...session.user.user_metadata,\n provider: \"supabase\",\n subject: session.user.id,\n },\n credits: { balance: 0, reserved: 0 },\n };\n\n this.updateState({ user, status: \"authenticated\" });\n } else {\n this.updateState({ user: null, status: \"unauthenticated\" });\n }\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n\n /**\n * Get the tenant ID from config.\n */\n protected override getTenantId(): string {\n return this.config.tenantId ?? \"default\";\n }\n\n /**\n * Get the underlying Supabase client for advanced operations.\n */\n getSupabaseClient(): SupabaseClient | null {\n return this.supabase;\n }\n\n /**\n * Reset password for email.\n */\n async resetPassword(email: string, redirectTo?: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.resetPasswordForEmail(email, {\n redirectTo: redirectTo || `${window.location.origin}/reset-password`,\n });\n\n if (error) throw error;\n }\n\n /**\n * Update user password.\n */\n async updatePassword(newPassword: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.updateUser({\n password: newPassword,\n });\n\n if (error) throw error;\n }\n}\n","/**\n * Supabase auth provider types.\n */\n\nimport type { AuthProviderConfig } from \"@weirdfingers/boards\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/**\n * Options for Supabase client configuration.\n */\nexport interface SupabaseAuthOptions {\n debug?: boolean;\n persistSession?: boolean;\n detectSessionInUrl?: boolean;\n headers?: Record<string, string>;\n}\n\n/**\n * Base configuration shared by all config variants.\n */\ninterface SupabaseConfigBase extends AuthProviderConfig {\n /**\n * Optional tenant ID for multi-tenant setups.\n */\n tenantId?: string;\n}\n\n/**\n * Configuration for creating a new Supabase client.\n */\nexport interface SupabaseConfigWithCredentials extends SupabaseConfigBase {\n /**\n * Supabase project URL.\n */\n url: string;\n\n /**\n * Supabase anonymous/public key.\n */\n anonKey: string;\n\n /**\n * Additional Supabase client options.\n */\n options?: SupabaseAuthOptions;\n\n /**\n * When using credentials, client should not be provided.\n */\n client?: never;\n}\n\n/**\n * Configuration for using an existing Supabase client.\n */\nexport interface SupabaseConfigWithClient extends SupabaseConfigBase {\n /**\n * Pre-configured Supabase client instance.\n */\n client: SupabaseClient;\n\n /**\n * When using an existing client, credentials should not be provided.\n */\n url?: never;\n anonKey?: never;\n options?: never;\n}\n\n/**\n * Supabase configuration - either provide credentials to create a new client,\n * or provide an existing client instance.\n */\nexport type SupabaseConfig = SupabaseConfigWithCredentials | SupabaseConfigWithClient;\n\n/**\n * Type guard to check if config uses credentials.\n */\nexport function isCredentialsConfig(\n config: SupabaseConfig\n): config is SupabaseConfigWithCredentials {\n return \"url\" in config && \"anonKey\" in config && !(\"client\" in config && config.client);\n}\n\n/**\n * Type guard to check if config uses an existing client.\n */\nexport function isClientConfig(config: SupabaseConfig): config is SupabaseConfigWithClient {\n return \"client\" in config && config.client !== undefined;\n}\n"],"mappings":";AAIA,SAAS,wBAAyC;;;AC0E3C,SAAS,oBACd,QACyC;AACzC,SAAO,SAAS,UAAU,aAAa,UAAU,EAAE,YAAY,UAAU,OAAO;AAClF;AAKO,SAAS,eAAe,QAA4D;AACzF,SAAO,YAAY,UAAU,OAAO,WAAW;AACjD;;;ADhFO,IAAM,uBAAN,cAAmC,iBAAiB;AAAA,EAMzD,YAAY,QAAwB;AAClC,UAAM,MAAM;AALd,SAAQ,YAA4C,CAAC;AAErD,SAAQ,WAAkC;AAIxC,SAAK,SAAS;AAEd,SAAK,eAAe;AAAA,MAClB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ,KAAK,OAAO,KAAK,IAAI;AAAA,MAC7B,SAAS,KAAK,QAAQ,KAAK,IAAI;AAAA,MAC/B,UAAU,KAAK,SAAS,KAAK,IAAI;AAAA,MACjC,cAAc,KAAK,aAAa,KAAK,IAAI;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAChC,QAAI;AACF,UAAI,eAAe,KAAK,MAAM,GAAG;AAE/B,aAAK,WAAW,KAAK,OAAO;AAAA,MAC9B,WAAW,oBAAoB,KAAK,MAAM,GAAG;AAE3C,cAAM,EAAE,aAAa,IAAI,MAAM,OAAO,uBAAuB;AAE7D,aAAK,WAAW,aAAa,KAAK,OAAO,KAAK,KAAK,OAAO,SAAS;AAAA,UACjE,MAAM;AAAA,YACJ,gBAAgB,KAAK,OAAO,SAAS,kBAAkB;AAAA,YACvD,oBAAoB,KAAK,OAAO,SAAS,sBAAsB;AAAA,YAC/D,GAAI,KAAK,OAAO,SAAS,WAAW;AAAA,cAClC,SAAS,KAAK,OAAO,QAAQ;AAAA,YAC/B;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAGA,WAAK,SAAS,KAAK;AAAA,QACjB,CAAC,OAAwBA,aAA4B;AACnD,eAAK,sBAAsB,OAAOA,QAAO;AAAA,QAC3C;AAAA,MACF;AAGA,YAAM;AAAA,QACJ,MAAM,EAAE,QAAQ;AAAA,MAClB,IAAI,MAAM,KAAK,SAAS,KAAK,WAAW;AACxC,WAAK,sBAAsB,mBAAmB,OAAO;AAAA,IACvD,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AACrD,WAAK,YAAY,EAAE,MAAM,MAAM,QAAQ,kBAAkB,CAAC;AAC1D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,eAAmC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OACJ,OAUI,CAAC,GACU;AACf,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,SAAK,YAAY,EAAE,QAAQ,UAAU,CAAC;AAEtC,QAAI;AAEF,UAAI,KAAK,UAAU;AACjB,cAAM,WAAW,KAAK,YAAY;AAClC,cAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,gBAAgB;AAAA,UACzD,UAAU,KAAK;AAAA,UACf,SAAS;AAAA,YACP,YAAY,KAAK,SAAS,cAAc,OAAO,SAAS;AAAA,YACxD,GAAI,aAAa,aAAa;AAAA,cAC5B,aAAa,EAAE,QAAQ,SAAS;AAAA,YAClC;AAAA,UACF;AAAA,QACF,CAAC;AAED,YAAI,MAAO,OAAM;AACjB;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,gBAAgB,KAAK,OAAO;AAC5C,cAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,cAAc;AAAA,UACvD,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK;AAAA,QAChB,CAAC;AAED,YAAI,MAAO,OAAM;AACjB,aAAK,YAAY,EAAE,QAAQ,kBAAkB,CAAC;AAC9C;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,YAAY,KAAK,SAAS,KAAK,UAAU;AACzD,cAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,OAAO;AAAA,UAChD,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf,SAAS,KAAK;AAAA,QAChB,CAAC;AAED,YAAI,MAAO,OAAM;AACjB;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,KAAK,UAAU;AAC/B,cAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,mBAAmB;AAAA,UAC5D,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,QACjB,CAAC;AAED,YAAI,MAAO,OAAM;AACjB;AAAA,MACF;AAEA,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD,SAAS,OAAO;AACd,WAAK,YAAY,EAAE,MAAM,MAAM,QAAQ,kBAAkB,CAAC;AAC1D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,QAAQ;AACnD,QAAI,MAAO,OAAM;AAAA,EAGnB;AAAA,EAEA,MAAM,WAAmC;AACvC,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,QAAI;AACF,YAAM;AAAA,QACJ,MAAM,EAAE,QAAQ;AAAA,MAClB,IAAI,MAAM,KAAK,SAAS,KAAK,WAAW;AACxC,aAAO,SAAS,gBAAgB;AAAA,IAClC,SAAS,OAAO;AACd,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,UAAgC;AACpC,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,MAAM,eAAuC;AAC3C,QAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,QAAI;AACF,YAAM;AAAA,QACJ,MAAM,EAAE,QAAQ;AAAA,QAChB;AAAA,MACF,IAAI,MAAM,KAAK,SAAS,KAAK,eAAe;AAC5C,UAAI,MAAO,OAAM;AACjB,aAAO,SAAS,gBAAgB;AAAA,IAClC,SAAS,MAAM;AACb,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,kBAAkB,UAAkD;AAClE,SAAK,UAAU,KAAK,QAAQ;AAC5B,WAAO,MAAM;AACX,YAAM,QAAQ,KAAK,UAAU,QAAQ,QAAQ;AAC7C,UAAI,QAAQ,IAAI;AACd,aAAK,UAAU,OAAO,OAAO,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,YAAY,CAAC;AAAA,EAEpB;AAAA,EAEQ,sBACN,QACA,SACM;AACN,QAAI,SAAS;AACX,YAAM,OAAa;AAAA,QACjB,IAAI,QAAQ,KAAK;AAAA,QACjB,OAAO,QAAQ,KAAK,SAAS;AAAA,QAC7B,MACE,QAAQ,KAAK,eAAe,gBAC5B,QAAQ,KAAK,eAAe,aAC5B,QAAQ,KAAK,eAAe,QAC5B,QAAQ,KAAK,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA,QAClC,QACE,QAAQ,KAAK,eAAe,cAC5B,QAAQ,KAAK,eAAe;AAAA,QAC9B,UAAU;AAAA,UACR,GAAG,QAAQ,KAAK;AAAA,UAChB,UAAU;AAAA,UACV,SAAS,QAAQ,KAAK;AAAA,QACxB;AAAA,QACA,SAAS,EAAE,SAAS,GAAG,UAAU,EAAE;AAAA,MACrC;AAEA,WAAK,YAAY,EAAE,MAAM,QAAQ,gBAAgB,CAAC;AAAA,IACpD,OAAO;AACL,WAAK,YAAY,EAAE,MAAM,MAAM,QAAQ,kBAAkB,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA,EAEQ,YAAY,SAAmC;AACrD,SAAK,eAAe,EAAE,GAAG,KAAK,cAAc,GAAG,QAAQ;AACvD,SAAK,UAAU,QAAQ,CAAC,aAAa,SAAS,KAAK,YAAY,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKmB,cAAsB;AACvC,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA2C;AACzC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAe,YAAoC;AACrE,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,sBAAsB,OAAO;AAAA,MACtE,YAAY,cAAc,GAAG,OAAO,SAAS,MAAM;AAAA,IACrD,CAAC;AAED,QAAI,MAAO,OAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,aAAoC;AACvD,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,WAAW;AAAA,MACpD,UAAU;AAAA,IACZ,CAAC;AAED,QAAI,MAAO,OAAM;AAAA,EACnB;AACF;","names":["session"]}
1
+ {"version":3,"sources":["../src/SupabaseAuthProvider.ts","../src/types.ts"],"sourcesContent":["/**\n * Supabase authentication provider.\n */\n\nimport { BaseAuthProvider, AuthState, User } from \"@weirdfingers/boards\";\nimport type { SupabaseClient, Session, AuthChangeEvent } from \"@supabase/supabase-js\";\nimport type { SupabaseConfig } from \"./types\";\nimport { isClientConfig, isCredentialsConfig } from \"./types\";\n\nexport class SupabaseAuthProvider extends BaseAuthProvider {\n protected config: SupabaseConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private supabase: SupabaseClient | null = null;\n\n constructor(config: SupabaseConfig) {\n super(config);\n this.config = config;\n\n this.currentState = {\n user: null,\n status: \"loading\",\n signIn: this.signIn.bind(this) as AuthState[\"signIn\"],\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n }\n\n async initialize(): Promise<void> {\n try {\n if (isClientConfig(this.config)) {\n // Use the provided client directly\n this.supabase = this.config.client;\n } else if (isCredentialsConfig(this.config)) {\n // Dynamically import Supabase and create a new client\n const { createClient } = await import(\"@supabase/supabase-js\");\n\n this.supabase = createClient(this.config.url, this.config.anonKey, {\n auth: {\n persistSession: this.config.options?.persistSession ?? true,\n detectSessionInUrl: this.config.options?.detectSessionInUrl ?? true,\n ...(this.config.options?.headers && {\n headers: this.config.options.headers,\n }),\n },\n });\n } else {\n throw new Error(\n \"Invalid configuration: provide either { url, anonKey } or { client }\"\n );\n }\n\n // Set up auth state listener\n this.supabase.auth.onAuthStateChange(\n (event: AuthChangeEvent, session: Session | null) => {\n this.handleAuthStateChange(event, session);\n }\n );\n\n // Get initial session\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n this.handleAuthStateChange(\"INITIAL_SESSION\", session);\n } catch (error) {\n console.error(\"Failed to initialize Supabase:\", error);\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(\n opts: {\n email?: string;\n password?: string;\n provider?: \"google\" | \"github\" | \"discord\" | \"twitter\" | \"facebook\";\n type?: \"signup\" | \"signin\" | \"magic_link\";\n options?: {\n data?: Record<string, unknown>;\n redirectTo?: string;\n shouldCreateUser?: boolean;\n };\n } = {}\n ): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n this.updateState({ status: \"loading\" });\n\n try {\n // Social provider login\n if (opts.provider) {\n const tenantId = this.getTenantId();\n const { error } = await this.supabase.auth.signInWithOAuth({\n provider: opts.provider,\n options: {\n redirectTo: opts.options?.redirectTo || window.location.origin,\n ...(tenantId !== \"default\" && {\n queryParams: { tenant: tenantId },\n }),\n },\n });\n\n if (error) throw error;\n return; // OAuth redirects, so we don't update state here\n }\n\n // Magic link\n if (opts.type === \"magic_link\" && opts.email) {\n const { error } = await this.supabase.auth.signInWithOtp({\n email: opts.email,\n options: opts.options,\n });\n\n if (error) throw error;\n this.updateState({ status: \"unauthenticated\" }); // Wait for email click\n return;\n }\n\n // Email/password signup\n if (opts.type === \"signup\" && opts.email && opts.password) {\n const { error } = await this.supabase.auth.signUp({\n email: opts.email,\n password: opts.password,\n options: opts.options,\n });\n\n if (error) throw error;\n return; // May need email confirmation\n }\n\n // Email/password signin (default)\n if (opts.email && opts.password) {\n const { error } = await this.supabase.auth.signInWithPassword({\n email: opts.email,\n password: opts.password,\n });\n\n if (error) throw error;\n return; // State will update via onAuthStateChange\n }\n\n throw new Error(\"Invalid sign in options provided\");\n } catch (error) {\n this.updateState({ user: null, status: \"unauthenticated\" });\n throw error;\n }\n }\n\n async signOut(): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.signOut();\n if (error) throw error;\n\n // State will update via onAuthStateChange\n }\n\n async getToken(): Promise<string | null> {\n if (!this.supabase) return null;\n\n try {\n const {\n data: { session },\n } = await this.supabase.auth.getSession();\n return session?.access_token || null;\n } catch (error) {\n console.error(\"Failed to get token:\", error);\n return null;\n }\n }\n\n async getUser(): Promise<User | null> {\n return this.currentState.user;\n }\n\n async refreshToken(): Promise<string | null> {\n if (!this.supabase) return null;\n try {\n const {\n data: { session },\n error,\n } = await this.supabase.auth.refreshSession();\n if (error) throw error;\n return session?.access_token || null;\n } catch {\n return null;\n }\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n // Supabase client cleanup is handled automatically\n }\n\n private handleAuthStateChange(\n _event: AuthChangeEvent | \"INITIAL_SESSION\",\n session: Session | null\n ): void {\n if (session) {\n const user: User = {\n id: session.user.id,\n email: session.user.email ?? \"\",\n name:\n session.user.user_metadata?.display_name ||\n session.user.user_metadata?.full_name ||\n session.user.user_metadata?.name ||\n session.user.email?.split(\"@\")[0],\n avatar:\n session.user.user_metadata?.avatar_url ||\n session.user.user_metadata?.picture,\n metadata: {\n ...session.user.user_metadata,\n provider: \"supabase\",\n subject: session.user.id,\n },\n credits: { balance: 0, reserved: 0 },\n };\n\n this.updateState({ user, status: \"authenticated\" });\n } else {\n this.updateState({ user: null, status: \"unauthenticated\" });\n }\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n\n /**\n * Get the tenant ID from config.\n */\n protected override getTenantId(): string {\n return this.config.tenantId ?? \"default\";\n }\n\n /**\n * Get the underlying Supabase client for advanced operations.\n */\n getSupabaseClient(): SupabaseClient | null {\n return this.supabase;\n }\n\n /**\n * Reset password for email.\n */\n async resetPassword(email: string, redirectTo?: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.resetPasswordForEmail(email, {\n redirectTo: redirectTo || `${window.location.origin}/reset-password`,\n });\n\n if (error) throw error;\n }\n\n /**\n * Update user password.\n */\n async updatePassword(newPassword: string): Promise<void> {\n if (!this.supabase) {\n throw new Error(\"Supabase not initialized\");\n }\n\n const { error } = await this.supabase.auth.updateUser({\n password: newPassword,\n });\n\n if (error) throw error;\n }\n}\n","/**\n * Supabase auth provider types.\n */\n\nimport type { AuthProviderConfig } from \"@weirdfingers/boards\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/**\n * Options for Supabase client configuration.\n */\nexport interface SupabaseAuthOptions {\n debug?: boolean;\n persistSession?: boolean;\n detectSessionInUrl?: boolean;\n headers?: Record<string, string>;\n}\n\n/**\n * Base configuration shared by all config variants.\n */\ninterface SupabaseConfigBase extends AuthProviderConfig {\n /**\n * Optional tenant ID for multi-tenant setups.\n */\n tenantId?: string;\n}\n\n/**\n * Configuration for creating a new Supabase client.\n */\nexport interface SupabaseConfigWithCredentials extends SupabaseConfigBase {\n /**\n * Supabase project URL.\n */\n url: string;\n\n /**\n * Supabase anonymous/public key.\n */\n anonKey: string;\n\n /**\n * Additional Supabase client options.\n */\n options?: SupabaseAuthOptions;\n\n /**\n * When using credentials, client should not be provided.\n */\n client?: never;\n}\n\n/**\n * Configuration for using an existing Supabase client.\n */\nexport interface SupabaseConfigWithClient extends SupabaseConfigBase {\n /**\n * Pre-configured Supabase client instance.\n */\n client: SupabaseClient;\n\n /**\n * When using an existing client, credentials should not be provided.\n */\n url?: never;\n anonKey?: never;\n options?: never;\n}\n\n/**\n * Supabase configuration - either provide credentials to create a new client,\n * or provide an existing client instance.\n */\nexport type SupabaseConfig = SupabaseConfigWithCredentials | SupabaseConfigWithClient;\n\n/**\n * Type guard to check if config uses credentials.\n */\nexport function isCredentialsConfig(\n config: SupabaseConfig\n): config is SupabaseConfigWithCredentials {\n return \"url\" in config && \"anonKey\" in config && !(\"client\" in config && config.client);\n}\n\n/**\n * Type guard to check if config uses an existing client.\n */\nexport function isClientConfig(config: SupabaseConfig): config is SupabaseConfigWithClient {\n return \"client\" in config && config.client !== undefined;\n}\n"],"mappings":"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","names":["session"]}
package/package.json CHANGED
@@ -1,17 +1,10 @@
1
1
  {
2
2
  "name": "@weirdfingers/boards-auth-supabase",
3
- "version": "0.9.13",
3
+ "version": "0.10.1",
4
4
  "description": "Supabase authentication provider for Boards",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
- "scripts": {
9
- "build": "tsup",
10
- "dev": "tsup --watch",
11
- "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
12
- "lint": "eslint src --ext .ts,.tsx",
13
- "test": "vitest --run --passWithNoTests"
14
- },
15
8
  "keywords": [
16
9
  "boards",
17
10
  "authentication",
@@ -23,19 +16,19 @@
23
16
  "license": "MIT",
24
17
  "peerDependencies": {
25
18
  "@supabase/supabase-js": "^2.50.2",
26
- "@weirdfingers/boards": "workspace:*",
27
- "react": "^18.0.0"
19
+ "react": "^18.0.0",
20
+ "@weirdfingers/boards": "0.10.1"
28
21
  },
29
22
  "devDependencies": {
30
23
  "@supabase/supabase-js": "^2.50.2",
31
24
  "@types/react": "^18.0.0",
32
25
  "@typescript-eslint/eslint-plugin": "^8.42.0",
33
26
  "@typescript-eslint/parser": "^8.42.0",
34
- "@weirdfingers/boards": "workspace:*",
35
27
  "eslint": "^8.0.0",
36
28
  "tsup": "^8.0.0",
37
29
  "typescript": "^5.0.0",
38
- "vitest": "^1.0.0"
30
+ "vitest": "^1.0.0",
31
+ "@weirdfingers/boards": "0.10.1"
39
32
  },
40
33
  "files": [
41
34
  "dist",
@@ -45,5 +38,12 @@
45
38
  "type": "git",
46
39
  "url": "https://github.com/weirdfingers/boards.git",
47
40
  "directory": "packages/auth-supabase"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
46
+ "lint": "eslint src --ext .ts,.tsx",
47
+ "test": "vitest --run --passWithNoTests"
48
48
  }
49
- }
49
+ }