@deepkey/sdk 1.0.0 → 1.2.0

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.d.cts CHANGED
@@ -1,5 +1,27 @@
1
- import { A as AuthClientOptions, S as SignInWithOtpCredentials, a as AuthResponse, V as VerifyOtpParams, U as User, b as Session, c as SignInWithOAuthCredentials, d as AuthChangeEvent, e as Subscription, f as AuthError } from './constants-BQhswdms.cjs';
2
- export { D as DEEPKEY_API_URL, g as ServerClientOptions, h as StorageAdapter, i as UserIdentity } from './constants-BQhswdms.cjs';
1
+ import { C as ConnectProviderCredentials, A as AuthResponse, P as ProviderConnection, a as AuthError, b as AuthClientOptions, S as SignInWithOtpCredentials, V as VerifyOtpParams, U as User, c as Session, d as SignInWithOAuthCredentials, e as AuthChangeEvent, f as Subscription } from './constants-ByCalul7.cjs';
2
+ export { D as DEEPKEY_API_URL, g as ProviderAccessToken, h as ServerClientOptions, i as StorageAdapter, j as UserApiKey, k as UserIdentity } from './constants-ByCalul7.cjs';
3
+
4
+ interface ConnectionsOptions {
5
+ apikey: string;
6
+ baseUrl: string;
7
+ fetchImpl?: typeof fetch;
8
+ }
9
+ declare class Connections {
10
+ private auth;
11
+ private options;
12
+ constructor(auth: Auth, options: ConnectionsOptions);
13
+ connect(credentials: ConnectProviderCredentials): Promise<AuthResponse<{
14
+ provider: string;
15
+ url: string | null;
16
+ }>>;
17
+ list(): Promise<AuthResponse<{
18
+ connections: ProviderConnection[];
19
+ }>>;
20
+ revoke(connectionId: string): Promise<{
21
+ error: AuthError | null;
22
+ }>;
23
+ private request;
24
+ }
3
25
 
4
26
  type Listener = (event: AuthChangeEvent, session: Session | null) => void;
5
27
  declare class Auth {
@@ -66,7 +88,8 @@ declare class Auth {
66
88
  }
67
89
  interface AuthClient {
68
90
  auth: Auth;
91
+ connections: Connections;
69
92
  }
70
93
  declare const createAuthClient: (publishableKey: string, options?: AuthClientOptions) => AuthClient;
71
94
 
72
- export { Auth, AuthChangeEvent, type AuthClient, AuthClientOptions, AuthError, AuthResponse, Session, SignInWithOAuthCredentials, SignInWithOtpCredentials, Subscription, User, VerifyOtpParams, createAuthClient };
95
+ export { Auth, AuthChangeEvent, type AuthClient, AuthClientOptions, AuthError, AuthResponse, ConnectProviderCredentials, Connections, ProviderConnection, Session, SignInWithOAuthCredentials, SignInWithOtpCredentials, Subscription, User, VerifyOtpParams, createAuthClient };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,27 @@
1
- import { A as AuthClientOptions, S as SignInWithOtpCredentials, a as AuthResponse, V as VerifyOtpParams, U as User, b as Session, c as SignInWithOAuthCredentials, d as AuthChangeEvent, e as Subscription, f as AuthError } from './constants-BQhswdms.js';
2
- export { D as DEEPKEY_API_URL, g as ServerClientOptions, h as StorageAdapter, i as UserIdentity } from './constants-BQhswdms.js';
1
+ import { C as ConnectProviderCredentials, A as AuthResponse, P as ProviderConnection, a as AuthError, b as AuthClientOptions, S as SignInWithOtpCredentials, V as VerifyOtpParams, U as User, c as Session, d as SignInWithOAuthCredentials, e as AuthChangeEvent, f as Subscription } from './constants-ByCalul7.js';
2
+ export { D as DEEPKEY_API_URL, g as ProviderAccessToken, h as ServerClientOptions, i as StorageAdapter, j as UserApiKey, k as UserIdentity } from './constants-ByCalul7.js';
3
+
4
+ interface ConnectionsOptions {
5
+ apikey: string;
6
+ baseUrl: string;
7
+ fetchImpl?: typeof fetch;
8
+ }
9
+ declare class Connections {
10
+ private auth;
11
+ private options;
12
+ constructor(auth: Auth, options: ConnectionsOptions);
13
+ connect(credentials: ConnectProviderCredentials): Promise<AuthResponse<{
14
+ provider: string;
15
+ url: string | null;
16
+ }>>;
17
+ list(): Promise<AuthResponse<{
18
+ connections: ProviderConnection[];
19
+ }>>;
20
+ revoke(connectionId: string): Promise<{
21
+ error: AuthError | null;
22
+ }>;
23
+ private request;
24
+ }
3
25
 
4
26
  type Listener = (event: AuthChangeEvent, session: Session | null) => void;
5
27
  declare class Auth {
@@ -66,7 +88,8 @@ declare class Auth {
66
88
  }
67
89
  interface AuthClient {
68
90
  auth: Auth;
91
+ connections: Connections;
69
92
  }
70
93
  declare const createAuthClient: (publishableKey: string, options?: AuthClientOptions) => AuthClient;
71
94
 
72
- export { Auth, AuthChangeEvent, type AuthClient, AuthClientOptions, AuthError, AuthResponse, Session, SignInWithOAuthCredentials, SignInWithOtpCredentials, Subscription, User, VerifyOtpParams, createAuthClient };
95
+ export { Auth, AuthChangeEvent, type AuthClient, AuthClientOptions, AuthError, AuthResponse, ConnectProviderCredentials, Connections, ProviderConnection, Session, SignInWithOAuthCredentials, SignInWithOtpCredentials, Subscription, User, VerifyOtpParams, createAuthClient };
package/dist/index.js CHANGED
@@ -1,43 +1,44 @@
1
1
  import {
2
2
  AuthError,
3
3
  DEEPKEY_API_URL,
4
+ request,
4
5
  resolveBaseUrl
5
- } from "./chunk-IFNRLMVX.js";
6
+ } from "./chunk-J4IK2N4V.js";
6
7
 
7
- // src/fetch.ts
8
- var request = async (options) => {
9
- const fetchImpl = options.fetchImpl ?? fetch;
10
- try {
11
- const headers = { apikey: options.apikey };
12
- if (options.body !== void 0) headers["Content-Type"] = "application/json";
13
- if (options.accessToken) headers.Authorization = `Bearer ${options.accessToken}`;
14
- const response = await fetchImpl(`${options.baseUrl}${options.path}`, {
15
- method: options.method,
16
- headers,
17
- body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
18
- });
19
- if (response.status === 204) return { data: {}, error: null };
20
- let payload;
21
- try {
22
- payload = await response.json();
23
- } catch {
24
- payload = null;
8
+ // src/connections.ts
9
+ var Connections = class {
10
+ constructor(auth, options) {
11
+ this.auth = auth;
12
+ this.options = options;
13
+ }
14
+ async connect(credentials) {
15
+ const { data, error } = await this.request(
16
+ "POST",
17
+ "/auth/v1/connections/authorize",
18
+ { provider: credentials.provider, redirect_to: credentials.options?.redirectTo }
19
+ );
20
+ if (error || !data) return { data: { provider: credentials.provider, url: null }, error };
21
+ if (!credentials.options?.skipBrowserRedirect && typeof window !== "undefined") {
22
+ window.location.assign(data.url);
25
23
  }
26
- if (!response.ok) {
27
- const errorBody = payload?.error;
28
- return {
29
- data: null,
30
- error: new AuthError(
31
- errorBody?.message ?? `Request failed with status ${response.status}`,
32
- response.status,
33
- errorBody?.code
34
- )
35
- };
24
+ return { data: { provider: credentials.provider, url: data.url }, error: null };
25
+ }
26
+ async list() {
27
+ const { data, error } = await this.request("GET", "/auth/v1/connections");
28
+ return { data: { connections: data?.connections ?? [] }, error };
29
+ }
30
+ async revoke(connectionId) {
31
+ const { error } = await this.request("DELETE", `/auth/v1/connections/${encodeURIComponent(connectionId)}`);
32
+ return { error };
33
+ }
34
+ async request(method, path, body) {
35
+ const {
36
+ data: { session }
37
+ } = await this.auth.getSession();
38
+ if (!session) {
39
+ return { data: null, error: new AuthError("Auth session missing!", 400, "session_missing") };
36
40
  }
37
- return { data: payload, error: null };
38
- } catch (err) {
39
- const message = err instanceof Error ? err.message : "Network request failed";
40
- return { data: null, error: new AuthError(message, 0, "network_error") };
41
+ return request({ method, path, body, accessToken: session.access_token, ...this.options });
41
42
  }
42
43
  };
43
44
 
@@ -385,11 +386,18 @@ var Auth = class {
385
386
  }
386
387
  };
387
388
  var createAuthClient = (publishableKey, options) => {
388
- return { auth: new Auth(publishableKey, options) };
389
+ const auth = new Auth(publishableKey, options);
390
+ const connections = new Connections(auth, {
391
+ apikey: publishableKey ?? "",
392
+ baseUrl: resolveBaseUrl(options?.__internalBaseUrl),
393
+ fetchImpl: options?.fetch
394
+ });
395
+ return { auth, connections };
389
396
  };
390
397
  export {
391
398
  Auth,
392
399
  AuthError,
400
+ Connections,
393
401
  DEEPKEY_API_URL,
394
402
  createAuthClient
395
403
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fetch.ts","../src/storage.ts","../src/url.ts","../src/client.ts"],"sourcesContent":["import { AuthError } from './types'\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PUT' | 'DELETE'\n path: string\n apikey: string\n baseUrl: string\n accessToken?: string\n body?: unknown\n fetchImpl?: typeof fetch\n}\n\nexport interface RequestResult<T> {\n data: T | null\n error: AuthError | null\n}\n\n// All service errors are shaped { error: { code, message } }.\nexport const request = async <T>(options: RequestOptions): Promise<RequestResult<T>> => {\n const fetchImpl = options.fetchImpl ?? fetch\n try {\n const headers: Record<string, string> = { apikey: options.apikey }\n if (options.body !== undefined) headers['Content-Type'] = 'application/json'\n if (options.accessToken) headers.Authorization = `Bearer ${options.accessToken}`\n\n const response = await fetchImpl(`${options.baseUrl}${options.path}`, {\n method: options.method,\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n })\n\n if (response.status === 204) return { data: {} as T, error: null }\n\n let payload: unknown\n try {\n payload = await response.json()\n } catch {\n payload = null\n }\n\n if (!response.ok) {\n const errorBody = (payload as { error?: { code?: string; message?: string } } | null)?.error\n return {\n data: null,\n error: new AuthError(\n errorBody?.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody?.code,\n ),\n }\n }\n\n return { data: payload as T, error: null }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Network request failed'\n return { data: null, error: new AuthError(message, 0, 'network_error') }\n }\n}\n","import type { StorageAdapter } from './types'\n\nclass MemoryStorage implements StorageAdapter {\n private store = new Map<string, string>()\n getItem(key: string) {\n return this.store.get(key) ?? null\n }\n setItem(key: string, value: string) {\n this.store.set(key, value)\n }\n removeItem(key: string) {\n this.store.delete(key)\n }\n}\n\n// localStorage when available, in-memory fallback (SSR, tests, restricted contexts).\nexport const defaultStorage = (): StorageAdapter => {\n try {\n if (typeof window !== 'undefined' && window.localStorage) {\n const probe = '__bt_auth_probe__'\n window.localStorage.setItem(probe, '1')\n window.localStorage.removeItem(probe)\n return window.localStorage\n }\n } catch {\n // fall through to memory storage\n }\n return new MemoryStorage()\n}\n\n// Publishable keys look like `bt_pub_<project-slug>_<random>`; the slug namespaces the\n// persisted session per project (mirrors supabase's `sb-<ref>-auth-token`).\nexport const deriveStorageKey = (publishableKey: string | undefined): string => {\n const match = publishableKey?.match(/^bt_pub_([a-z0-9-]+)_[A-Za-z0-9_-]+$/)\n return match ? `bt-${match[1]}-auth-token` : 'bt-auth-token'\n}\n","export interface FragmentTokens {\n access_token: string\n refresh_token: string\n expires_in: number\n expires_at: number\n token_type: 'bearer'\n type?: string\n}\n\nexport interface FragmentError {\n error: string\n error_code?: string\n error_description?: string\n}\n\nexport type ParsedFragment = { tokens: FragmentTokens } | { authError: FragmentError } | null\n\n// Parses the implicit-flow return fragment (`#access_token=...` or `#error=...`).\nexport const parseFragment = (hash: string): ParsedFragment => {\n if (!hash || hash.length < 2) return null\n const params = new URLSearchParams(hash.startsWith('#') ? hash.slice(1) : hash)\n\n const error = params.get('error')\n if (error) {\n return {\n authError: {\n error,\n error_code: params.get('error_code') ?? undefined,\n error_description: params.get('error_description') ?? undefined,\n },\n }\n }\n\n const accessToken = params.get('access_token')\n const refreshToken = params.get('refresh_token')\n if (!accessToken || !refreshToken) return null\n\n const expiresIn = Number(params.get('expires_in') ?? 3600)\n const expiresAt = Number(params.get('expires_at') ?? Math.floor(Date.now() / 1000) + expiresIn)\n\n return {\n tokens: {\n access_token: accessToken,\n refresh_token: refreshToken,\n expires_in: expiresIn,\n expires_at: expiresAt,\n token_type: 'bearer',\n type: params.get('type') ?? undefined,\n },\n }\n}\n\n// Removes the auth fragment from the address bar (before any await, so tokens never\n// linger in history).\nexport const cleanFragmentFromUrl = () => {\n if (typeof window === 'undefined' || typeof history === 'undefined') return\n history.replaceState(null, '', window.location.pathname + window.location.search)\n}\n","import { resolveBaseUrl } from './constants'\nimport { request } from './fetch'\nimport { defaultStorage, deriveStorageKey } from './storage'\nimport {\n AuthError,\n type AuthChangeEvent,\n type AuthClientOptions,\n type AuthResponse,\n type Session,\n type SignInWithOAuthCredentials,\n type SignInWithOtpCredentials,\n type StorageAdapter,\n type Subscription,\n type User,\n type VerifyOtpParams,\n} from './types'\nimport { cleanFragmentFromUrl, parseFragment } from './url'\n\nconst REFRESH_TICK_MS = 30_000\n// Refresh when the access token is within this margin of expiry.\nconst EXPIRY_MARGIN_SECONDS = 90\n\ntype Listener = (event: AuthChangeEvent, session: Session | null) => void\n\nexport class Auth {\n private baseUrl: string\n private apikey: string\n private storage: StorageAdapter\n private storageKey: string\n private persistSession: boolean\n private autoRefreshToken: boolean\n private detectSessionInUrl: boolean\n private fetchImpl?: typeof fetch\n\n private session: Session | null = null\n private listeners = new Map<string, Listener>()\n private listenerSeq = 0\n private initializePromise: Promise<void> | null = null\n private refreshPromise: Promise<AuthResponse<{ session: Session | null; user: User | null }>> | null = null\n private refreshTimer: ReturnType<typeof setInterval> | null = null\n\n constructor(publishableKey: string, options: AuthClientOptions = {}) {\n // Lazy by design: an empty key must not throw at construction time (CI builds\n // with empty envs import this module transitively). Failures surface on first call.\n // The hosted DeepKey API is the only supported origin. The internal override\n // exists for DeepKey's console and tests and is not part of the public contract.\n this.baseUrl = resolveBaseUrl(options.__internalBaseUrl)\n this.apikey = publishableKey ?? ''\n this.persistSession = options.persistSession ?? true\n this.autoRefreshToken = options.autoRefreshToken ?? true\n this.detectSessionInUrl = options.detectSessionInUrl ?? true\n this.storage = options.storage ?? defaultStorage()\n this.storageKey = options.storageKey ?? deriveStorageKey(publishableKey)\n this.fetchImpl = options.fetch\n\n this.setupCrossTabSync()\n }\n\n // ---- public API (supabase-js compatible) ----\n\n async signInWithOtp(credentials: SignInWithOtpCredentials): Promise<AuthResponse<{ user: null; session: null }>> {\n const { error } = await this.request<Record<string, never>>('POST', '/auth/v1/otp', {\n email: credentials.email,\n create_user: credentials.options?.shouldCreateUser,\n redirect_to: credentials.options?.emailRedirectTo,\n })\n return { data: { user: null, session: null }, error }\n }\n\n async verifyOtp(params: VerifyOtpParams): Promise<AuthResponse<{ user: User | null; session: Session | null }>> {\n const { data, error } = await this.request<Session>('POST', '/auth/v1/verify', {\n type: 'email',\n email: params.email,\n token: params.token,\n })\n if (error || !data) return { data: { user: null, session: null }, error }\n\n await this.saveSession(data)\n this.emit('SIGNED_IN', data)\n return { data: { user: data.user, session: data }, error: null }\n }\n\n async signInWithOAuth(\n credentials: SignInWithOAuthCredentials,\n ): Promise<AuthResponse<{ provider: string; url: string }>> {\n const url = new URL(`${this.baseUrl}/auth/v1/authorize`)\n url.searchParams.set('provider', credentials.provider)\n url.searchParams.set('apikey', this.apikey)\n if (credentials.options?.redirectTo) url.searchParams.set('redirect_to', credentials.options.redirectTo)\n if (credentials.options?.scopes) url.searchParams.set('scopes', credentials.options.scopes)\n for (const [key, value] of Object.entries(credentials.options?.queryParams ?? {})) {\n url.searchParams.set(key, value)\n }\n\n if (!credentials.options?.skipBrowserRedirect && typeof window !== 'undefined') {\n window.location.assign(url.toString())\n }\n return { data: { provider: credentials.provider, url: url.toString() }, error: null }\n }\n\n onAuthStateChange(callback: Listener): { data: { subscription: Subscription } } {\n const id = `listener-${++this.listenerSeq}`\n this.listeners.set(id, callback)\n\n // Every subscriber receives INITIAL_SESSION asynchronously once initialization\n // settles — the supabase-js contract that AuthProviders rely on to resolve loading.\n this.initialize().then(() => {\n if (this.listeners.has(id)) callback('INITIAL_SESSION', this.session)\n })\n\n return {\n data: {\n subscription: {\n id,\n unsubscribe: () => {\n this.listeners.delete(id)\n },\n },\n },\n }\n }\n\n async signOut(): Promise<{ error: AuthError | null }> {\n await this.initialize()\n const session = this.session\n if (session) {\n // Best-effort server-side revocation; local sign-out always succeeds.\n await this.request('POST', '/auth/v1/logout', {}, session.access_token)\n }\n this.clearSession()\n this.emit('SIGNED_OUT', null)\n return { error: null }\n }\n\n async getSession(): Promise<AuthResponse<{ session: Session | null }>> {\n await this.initialize()\n\n if (this.session && this.isExpired(this.session) && this.autoRefreshToken) {\n const { error } = await this.refreshWithLock()\n if (error && error.code !== 'network_error') {\n return { data: { session: null }, error: null }\n }\n }\n\n return { data: { session: this.session }, error: null }\n }\n\n async getUser(jwt?: string): Promise<AuthResponse<{ user: User | null }>> {\n let token = jwt\n if (!token) {\n const {\n data: { session },\n } = await this.getSession()\n token = session?.access_token\n }\n if (!token) {\n return { data: { user: null }, error: new AuthError('Auth session missing!', 400, 'session_missing') }\n }\n\n const { data, error } = await this.request<User>('GET', '/auth/v1/user', undefined, token)\n return { data: { user: data }, error }\n }\n\n async refreshSession(currentSession?: {\n refresh_token: string\n }): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n await this.initialize()\n const refreshToken = currentSession?.refresh_token ?? this.session?.refresh_token\n if (!refreshToken) {\n return {\n data: { session: null, user: null },\n error: new AuthError('Auth session missing!', 400, 'session_missing'),\n }\n }\n return this.refreshWithLock(refreshToken)\n }\n\n // ---- internals ----\n\n private async request<T>(method: 'GET' | 'POST', path: string, body?: unknown, accessToken?: string) {\n return request<T>({\n method,\n path,\n body,\n accessToken,\n apikey: this.apikey,\n baseUrl: this.baseUrl,\n fetchImpl: this.fetchImpl,\n })\n }\n\n private initialize(): Promise<void> {\n this.initializePromise ??= this.doInitialize()\n return this.initializePromise\n }\n\n private async doInitialize(): Promise<void> {\n if (this.detectSessionInUrl && typeof window !== 'undefined') {\n const parsed = parseFragment(window.location.hash)\n if (parsed) {\n // Strip tokens from the address bar synchronously, before any await.\n cleanFragmentFromUrl()\n\n if ('authError' in parsed) {\n console.warn(\n `[deepkey] Auth redirect returned an error: ${parsed.authError.error_code ?? parsed.authError.error}`,\n parsed.authError.error_description ?? '',\n )\n } else {\n const { data: user } = await this.request<User>('GET', '/auth/v1/user', undefined, parsed.tokens.access_token)\n if (user) {\n const session: Session = { ...parsed.tokens, token_type: 'bearer', user }\n await this.saveSession(session)\n this.emit('SIGNED_IN', session)\n return\n }\n }\n }\n }\n\n const stored = this.loadStoredSession()\n if (!stored) return\n\n if (this.isExpired(stored)) {\n if (!this.autoRefreshToken) return\n this.session = stored\n const { error } = await this.refreshWithLock()\n if (error && error.code !== 'network_error') this.clearSession()\n return\n }\n\n this.session = stored\n this.startRefreshTimer()\n }\n\n private isExpired(session: Session): boolean {\n return session.expires_at <= Math.floor(Date.now() / 1000) + EXPIRY_MARGIN_SECONDS\n }\n\n private async refreshWithLock(\n refreshToken?: string,\n ): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n this.refreshPromise ??= this.doRefresh(refreshToken).finally(() => {\n this.refreshPromise = null\n })\n return this.refreshPromise\n }\n\n private async doRefresh(\n refreshToken?: string,\n ): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n const token = refreshToken ?? this.session?.refresh_token\n if (!token) {\n return {\n data: { session: null, user: null },\n error: new AuthError('Auth session missing!', 400, 'session_missing'),\n }\n }\n\n const { data, error } = await this.request<Session>('POST', '/auth/v1/token?grant_type=refresh_token', {\n refresh_token: token,\n })\n\n if (error) {\n // Network failures keep the session (retry next tick); auth failures clear it.\n if (error.code !== 'network_error') {\n this.clearSession()\n this.emit('SIGNED_OUT', null)\n }\n return { data: { session: null, user: null }, error }\n }\n\n if (data) {\n await this.saveSession(data)\n this.emit('TOKEN_REFRESHED', data)\n return { data: { session: data, user: data.user }, error: null }\n }\n return { data: { session: null, user: null }, error: new AuthError('Empty refresh response') }\n }\n\n private async saveSession(session: Session) {\n this.session = session\n if (this.persistSession) {\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(session))\n } catch {\n // Persistence is best-effort (private mode, quota).\n }\n }\n this.startRefreshTimer()\n }\n\n private clearSession() {\n this.session = null\n try {\n this.storage.removeItem(this.storageKey)\n } catch {\n // ignore\n }\n this.stopRefreshTimer()\n }\n\n private loadStoredSession(): Session | null {\n if (!this.persistSession) return null\n try {\n const raw = this.storage.getItem(this.storageKey)\n if (!raw) return null\n const parsed = JSON.parse(raw) as Session\n if (!parsed.access_token || !parsed.refresh_token) return null\n return parsed\n } catch {\n return null\n }\n }\n\n private startRefreshTimer() {\n if (!this.autoRefreshToken || this.refreshTimer || typeof setInterval === 'undefined') return\n this.refreshTimer = setInterval(() => {\n if (this.session && this.isExpired(this.session)) void this.refreshWithLock()\n }, REFRESH_TICK_MS)\n // Do not keep node processes alive because of the timer (no-op in browsers).\n const timer = this.refreshTimer as unknown as { unref?: () => void }\n if (typeof timer === 'object' && typeof timer.unref === 'function') timer.unref()\n }\n\n private stopRefreshTimer() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n\n private setupCrossTabSync() {\n if (typeof window === 'undefined' || !this.persistSession) return\n window.addEventListener('storage', event => {\n if (event.key !== this.storageKey) return\n if (!event.newValue) {\n if (this.session) {\n this.session = null\n this.stopRefreshTimer()\n this.emit('SIGNED_OUT', null)\n }\n return\n }\n try {\n const next = JSON.parse(event.newValue) as Session\n const changed = next.access_token !== this.session?.access_token\n this.session = next\n this.startRefreshTimer()\n if (changed) this.emit('TOKEN_REFRESHED', next)\n } catch {\n // ignore malformed writes\n }\n })\n }\n\n private emit(event: AuthChangeEvent, session: Session | null) {\n for (const listener of this.listeners.values()) {\n try {\n listener(event, session)\n } catch (err) {\n console.error('[deepkey] onAuthStateChange listener threw', err)\n }\n }\n }\n}\n\nexport interface AuthClient {\n auth: Auth\n}\n\nexport const createAuthClient = (publishableKey: string, options?: AuthClientOptions): AuthClient => {\n return { auth: new Auth(publishableKey, options) }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/connections.ts","../src/storage.ts","../src/url.ts","../src/client.ts"],"sourcesContent":["import type { Auth } from './client'\nimport { request } from './fetch'\nimport { AuthError, type AuthResponse, type ConnectProviderCredentials, type ProviderConnection } from './types'\n\nexport interface ConnectionsOptions {\n apikey: string\n baseUrl: string\n fetchImpl?: typeof fetch\n}\n\n// Durable provider access for the signed-in user, kept apart from login identities:\n// a user who signed in with Google can connect several X accounts. Provider refresh\n// tokens stay on DeepKey; browsers only ever see connection metadata.\nexport class Connections {\n constructor(\n private auth: Auth,\n private options: ConnectionsOptions,\n ) {}\n\n async connect(\n credentials: ConnectProviderCredentials,\n ): Promise<AuthResponse<{ provider: string; url: string | null }>> {\n const { data, error } = await this.request<{ provider: string; url: string }>(\n 'POST',\n '/auth/v1/connections/authorize',\n { provider: credentials.provider, redirect_to: credentials.options?.redirectTo },\n )\n if (error || !data) return { data: { provider: credentials.provider, url: null }, error }\n\n if (!credentials.options?.skipBrowserRedirect && typeof window !== 'undefined') {\n window.location.assign(data.url)\n }\n return { data: { provider: credentials.provider, url: data.url }, error: null }\n }\n\n async list(): Promise<AuthResponse<{ connections: ProviderConnection[] }>> {\n const { data, error } = await this.request<{ connections: ProviderConnection[] }>('GET', '/auth/v1/connections')\n return { data: { connections: data?.connections ?? [] }, error }\n }\n\n async revoke(connectionId: string): Promise<{ error: AuthError | null }> {\n const { error } = await this.request('DELETE', `/auth/v1/connections/${encodeURIComponent(connectionId)}`)\n return { error }\n }\n\n private async request<T>(method: 'GET' | 'POST' | 'DELETE', path: string, body?: unknown) {\n const {\n data: { session },\n } = await this.auth.getSession()\n if (!session) {\n return { data: null, error: new AuthError('Auth session missing!', 400, 'session_missing') }\n }\n return request<T>({ method, path, body, accessToken: session.access_token, ...this.options })\n }\n}\n","import type { StorageAdapter } from './types'\n\nclass MemoryStorage implements StorageAdapter {\n private store = new Map<string, string>()\n getItem(key: string) {\n return this.store.get(key) ?? null\n }\n setItem(key: string, value: string) {\n this.store.set(key, value)\n }\n removeItem(key: string) {\n this.store.delete(key)\n }\n}\n\n// localStorage when available, in-memory fallback (SSR, tests, restricted contexts).\nexport const defaultStorage = (): StorageAdapter => {\n try {\n if (typeof window !== 'undefined' && window.localStorage) {\n const probe = '__bt_auth_probe__'\n window.localStorage.setItem(probe, '1')\n window.localStorage.removeItem(probe)\n return window.localStorage\n }\n } catch {\n // fall through to memory storage\n }\n return new MemoryStorage()\n}\n\n// Publishable keys look like `bt_pub_<project-slug>_<random>`; the slug namespaces the\n// persisted session per project (mirrors supabase's `sb-<ref>-auth-token`).\nexport const deriveStorageKey = (publishableKey: string | undefined): string => {\n const match = publishableKey?.match(/^bt_pub_([a-z0-9-]+)_[A-Za-z0-9_-]+$/)\n return match ? `bt-${match[1]}-auth-token` : 'bt-auth-token'\n}\n","export interface FragmentTokens {\n access_token: string\n refresh_token: string\n expires_in: number\n expires_at: number\n token_type: 'bearer'\n type?: string\n}\n\nexport interface FragmentError {\n error: string\n error_code?: string\n error_description?: string\n}\n\nexport type ParsedFragment = { tokens: FragmentTokens } | { authError: FragmentError } | null\n\n// Parses the implicit-flow return fragment (`#access_token=...` or `#error=...`).\nexport const parseFragment = (hash: string): ParsedFragment => {\n if (!hash || hash.length < 2) return null\n const params = new URLSearchParams(hash.startsWith('#') ? hash.slice(1) : hash)\n\n const error = params.get('error')\n if (error) {\n return {\n authError: {\n error,\n error_code: params.get('error_code') ?? undefined,\n error_description: params.get('error_description') ?? undefined,\n },\n }\n }\n\n const accessToken = params.get('access_token')\n const refreshToken = params.get('refresh_token')\n if (!accessToken || !refreshToken) return null\n\n const expiresIn = Number(params.get('expires_in') ?? 3600)\n const expiresAt = Number(params.get('expires_at') ?? Math.floor(Date.now() / 1000) + expiresIn)\n\n return {\n tokens: {\n access_token: accessToken,\n refresh_token: refreshToken,\n expires_in: expiresIn,\n expires_at: expiresAt,\n token_type: 'bearer',\n type: params.get('type') ?? undefined,\n },\n }\n}\n\n// Removes the auth fragment from the address bar (before any await, so tokens never\n// linger in history).\nexport const cleanFragmentFromUrl = () => {\n if (typeof window === 'undefined' || typeof history === 'undefined') return\n history.replaceState(null, '', window.location.pathname + window.location.search)\n}\n","import { Connections } from './connections'\nimport { resolveBaseUrl } from './constants'\nimport { request } from './fetch'\nimport { defaultStorage, deriveStorageKey } from './storage'\nimport {\n AuthError,\n type AuthChangeEvent,\n type AuthClientOptions,\n type AuthResponse,\n type Session,\n type SignInWithOAuthCredentials,\n type SignInWithOtpCredentials,\n type StorageAdapter,\n type Subscription,\n type User,\n type VerifyOtpParams,\n} from './types'\nimport { cleanFragmentFromUrl, parseFragment } from './url'\n\nconst REFRESH_TICK_MS = 30_000\n// Refresh when the access token is within this margin of expiry.\nconst EXPIRY_MARGIN_SECONDS = 90\n\ntype Listener = (event: AuthChangeEvent, session: Session | null) => void\n\nexport class Auth {\n private baseUrl: string\n private apikey: string\n private storage: StorageAdapter\n private storageKey: string\n private persistSession: boolean\n private autoRefreshToken: boolean\n private detectSessionInUrl: boolean\n private fetchImpl?: typeof fetch\n\n private session: Session | null = null\n private listeners = new Map<string, Listener>()\n private listenerSeq = 0\n private initializePromise: Promise<void> | null = null\n private refreshPromise: Promise<AuthResponse<{ session: Session | null; user: User | null }>> | null = null\n private refreshTimer: ReturnType<typeof setInterval> | null = null\n\n constructor(publishableKey: string, options: AuthClientOptions = {}) {\n // Lazy by design: an empty key must not throw at construction time (CI builds\n // with empty envs import this module transitively). Failures surface on first call.\n // The hosted DeepKey API is the only supported origin. The internal override\n // exists for DeepKey's console and tests and is not part of the public contract.\n this.baseUrl = resolveBaseUrl(options.__internalBaseUrl)\n this.apikey = publishableKey ?? ''\n this.persistSession = options.persistSession ?? true\n this.autoRefreshToken = options.autoRefreshToken ?? true\n this.detectSessionInUrl = options.detectSessionInUrl ?? true\n this.storage = options.storage ?? defaultStorage()\n this.storageKey = options.storageKey ?? deriveStorageKey(publishableKey)\n this.fetchImpl = options.fetch\n\n this.setupCrossTabSync()\n }\n\n // ---- public API (supabase-js compatible) ----\n\n async signInWithOtp(credentials: SignInWithOtpCredentials): Promise<AuthResponse<{ user: null; session: null }>> {\n const { error } = await this.request<Record<string, never>>('POST', '/auth/v1/otp', {\n email: credentials.email,\n create_user: credentials.options?.shouldCreateUser,\n redirect_to: credentials.options?.emailRedirectTo,\n })\n return { data: { user: null, session: null }, error }\n }\n\n async verifyOtp(params: VerifyOtpParams): Promise<AuthResponse<{ user: User | null; session: Session | null }>> {\n const { data, error } = await this.request<Session>('POST', '/auth/v1/verify', {\n type: 'email',\n email: params.email,\n token: params.token,\n })\n if (error || !data) return { data: { user: null, session: null }, error }\n\n await this.saveSession(data)\n this.emit('SIGNED_IN', data)\n return { data: { user: data.user, session: data }, error: null }\n }\n\n async signInWithOAuth(\n credentials: SignInWithOAuthCredentials,\n ): Promise<AuthResponse<{ provider: string; url: string }>> {\n const url = new URL(`${this.baseUrl}/auth/v1/authorize`)\n url.searchParams.set('provider', credentials.provider)\n url.searchParams.set('apikey', this.apikey)\n if (credentials.options?.redirectTo) url.searchParams.set('redirect_to', credentials.options.redirectTo)\n if (credentials.options?.scopes) url.searchParams.set('scopes', credentials.options.scopes)\n for (const [key, value] of Object.entries(credentials.options?.queryParams ?? {})) {\n url.searchParams.set(key, value)\n }\n\n if (!credentials.options?.skipBrowserRedirect && typeof window !== 'undefined') {\n window.location.assign(url.toString())\n }\n return { data: { provider: credentials.provider, url: url.toString() }, error: null }\n }\n\n onAuthStateChange(callback: Listener): { data: { subscription: Subscription } } {\n const id = `listener-${++this.listenerSeq}`\n this.listeners.set(id, callback)\n\n // Every subscriber receives INITIAL_SESSION asynchronously once initialization\n // settles — the supabase-js contract that AuthProviders rely on to resolve loading.\n this.initialize().then(() => {\n if (this.listeners.has(id)) callback('INITIAL_SESSION', this.session)\n })\n\n return {\n data: {\n subscription: {\n id,\n unsubscribe: () => {\n this.listeners.delete(id)\n },\n },\n },\n }\n }\n\n async signOut(): Promise<{ error: AuthError | null }> {\n await this.initialize()\n const session = this.session\n if (session) {\n // Best-effort server-side revocation; local sign-out always succeeds.\n await this.request('POST', '/auth/v1/logout', {}, session.access_token)\n }\n this.clearSession()\n this.emit('SIGNED_OUT', null)\n return { error: null }\n }\n\n async getSession(): Promise<AuthResponse<{ session: Session | null }>> {\n await this.initialize()\n\n if (this.session && this.isExpired(this.session) && this.autoRefreshToken) {\n const { error } = await this.refreshWithLock()\n if (error && error.code !== 'network_error') {\n return { data: { session: null }, error: null }\n }\n }\n\n return { data: { session: this.session }, error: null }\n }\n\n async getUser(jwt?: string): Promise<AuthResponse<{ user: User | null }>> {\n let token = jwt\n if (!token) {\n const {\n data: { session },\n } = await this.getSession()\n token = session?.access_token\n }\n if (!token) {\n return { data: { user: null }, error: new AuthError('Auth session missing!', 400, 'session_missing') }\n }\n\n const { data, error } = await this.request<User>('GET', '/auth/v1/user', undefined, token)\n return { data: { user: data }, error }\n }\n\n async refreshSession(currentSession?: {\n refresh_token: string\n }): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n await this.initialize()\n const refreshToken = currentSession?.refresh_token ?? this.session?.refresh_token\n if (!refreshToken) {\n return {\n data: { session: null, user: null },\n error: new AuthError('Auth session missing!', 400, 'session_missing'),\n }\n }\n return this.refreshWithLock(refreshToken)\n }\n\n // ---- internals ----\n\n private async request<T>(method: 'GET' | 'POST', path: string, body?: unknown, accessToken?: string) {\n return request<T>({\n method,\n path,\n body,\n accessToken,\n apikey: this.apikey,\n baseUrl: this.baseUrl,\n fetchImpl: this.fetchImpl,\n })\n }\n\n private initialize(): Promise<void> {\n this.initializePromise ??= this.doInitialize()\n return this.initializePromise\n }\n\n private async doInitialize(): Promise<void> {\n if (this.detectSessionInUrl && typeof window !== 'undefined') {\n const parsed = parseFragment(window.location.hash)\n if (parsed) {\n // Strip tokens from the address bar synchronously, before any await.\n cleanFragmentFromUrl()\n\n if ('authError' in parsed) {\n console.warn(\n `[deepkey] Auth redirect returned an error: ${parsed.authError.error_code ?? parsed.authError.error}`,\n parsed.authError.error_description ?? '',\n )\n } else {\n const { data: user } = await this.request<User>('GET', '/auth/v1/user', undefined, parsed.tokens.access_token)\n if (user) {\n const session: Session = { ...parsed.tokens, token_type: 'bearer', user }\n await this.saveSession(session)\n this.emit('SIGNED_IN', session)\n return\n }\n }\n }\n }\n\n const stored = this.loadStoredSession()\n if (!stored) return\n\n if (this.isExpired(stored)) {\n if (!this.autoRefreshToken) return\n this.session = stored\n const { error } = await this.refreshWithLock()\n if (error && error.code !== 'network_error') this.clearSession()\n return\n }\n\n this.session = stored\n this.startRefreshTimer()\n }\n\n private isExpired(session: Session): boolean {\n return session.expires_at <= Math.floor(Date.now() / 1000) + EXPIRY_MARGIN_SECONDS\n }\n\n private async refreshWithLock(\n refreshToken?: string,\n ): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n this.refreshPromise ??= this.doRefresh(refreshToken).finally(() => {\n this.refreshPromise = null\n })\n return this.refreshPromise\n }\n\n private async doRefresh(\n refreshToken?: string,\n ): Promise<AuthResponse<{ session: Session | null; user: User | null }>> {\n const token = refreshToken ?? this.session?.refresh_token\n if (!token) {\n return {\n data: { session: null, user: null },\n error: new AuthError('Auth session missing!', 400, 'session_missing'),\n }\n }\n\n const { data, error } = await this.request<Session>('POST', '/auth/v1/token?grant_type=refresh_token', {\n refresh_token: token,\n })\n\n if (error) {\n // Network failures keep the session (retry next tick); auth failures clear it.\n if (error.code !== 'network_error') {\n this.clearSession()\n this.emit('SIGNED_OUT', null)\n }\n return { data: { session: null, user: null }, error }\n }\n\n if (data) {\n await this.saveSession(data)\n this.emit('TOKEN_REFRESHED', data)\n return { data: { session: data, user: data.user }, error: null }\n }\n return { data: { session: null, user: null }, error: new AuthError('Empty refresh response') }\n }\n\n private async saveSession(session: Session) {\n this.session = session\n if (this.persistSession) {\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(session))\n } catch {\n // Persistence is best-effort (private mode, quota).\n }\n }\n this.startRefreshTimer()\n }\n\n private clearSession() {\n this.session = null\n try {\n this.storage.removeItem(this.storageKey)\n } catch {\n // ignore\n }\n this.stopRefreshTimer()\n }\n\n private loadStoredSession(): Session | null {\n if (!this.persistSession) return null\n try {\n const raw = this.storage.getItem(this.storageKey)\n if (!raw) return null\n const parsed = JSON.parse(raw) as Session\n if (!parsed.access_token || !parsed.refresh_token) return null\n return parsed\n } catch {\n return null\n }\n }\n\n private startRefreshTimer() {\n if (!this.autoRefreshToken || this.refreshTimer || typeof setInterval === 'undefined') return\n this.refreshTimer = setInterval(() => {\n if (this.session && this.isExpired(this.session)) void this.refreshWithLock()\n }, REFRESH_TICK_MS)\n // Do not keep node processes alive because of the timer (no-op in browsers).\n const timer = this.refreshTimer as unknown as { unref?: () => void }\n if (typeof timer === 'object' && typeof timer.unref === 'function') timer.unref()\n }\n\n private stopRefreshTimer() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n\n private setupCrossTabSync() {\n if (typeof window === 'undefined' || !this.persistSession) return\n window.addEventListener('storage', event => {\n if (event.key !== this.storageKey) return\n if (!event.newValue) {\n if (this.session) {\n this.session = null\n this.stopRefreshTimer()\n this.emit('SIGNED_OUT', null)\n }\n return\n }\n try {\n const next = JSON.parse(event.newValue) as Session\n const changed = next.access_token !== this.session?.access_token\n this.session = next\n this.startRefreshTimer()\n if (changed) this.emit('TOKEN_REFRESHED', next)\n } catch {\n // ignore malformed writes\n }\n })\n }\n\n private emit(event: AuthChangeEvent, session: Session | null) {\n for (const listener of this.listeners.values()) {\n try {\n listener(event, session)\n } catch (err) {\n console.error('[deepkey] onAuthStateChange listener threw', err)\n }\n }\n }\n}\n\nexport interface AuthClient {\n auth: Auth\n connections: Connections\n}\n\nexport const createAuthClient = (publishableKey: string, options?: AuthClientOptions): AuthClient => {\n const auth = new Auth(publishableKey, options)\n const connections = new Connections(auth, {\n apikey: publishableKey ?? '',\n baseUrl: resolveBaseUrl(options?.__internalBaseUrl),\n fetchImpl: options?.fetch,\n })\n return { auth, connections }\n}\n"],"mappings":"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","names":[]}
package/dist/server.cjs CHANGED
@@ -43,39 +43,111 @@ var AuthError = class extends Error {
43
43
  }
44
44
  };
45
45
 
46
+ // src/fetch.ts
47
+ var request = async (options) => {
48
+ const fetchImpl = options.fetchImpl ?? fetch;
49
+ try {
50
+ const headers = { apikey: options.apikey };
51
+ if (options.body !== void 0) headers["Content-Type"] = "application/json";
52
+ if (options.accessToken) headers.Authorization = `Bearer ${options.accessToken}`;
53
+ const response = await fetchImpl(`${options.baseUrl}${options.path}`, {
54
+ method: options.method,
55
+ headers,
56
+ body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
57
+ });
58
+ if (response.status === 204) return { data: {}, error: null };
59
+ let payload;
60
+ try {
61
+ payload = await response.json();
62
+ } catch {
63
+ payload = null;
64
+ }
65
+ if (!response.ok) {
66
+ const errorBody = payload?.error;
67
+ return {
68
+ data: null,
69
+ error: new AuthError(
70
+ errorBody?.message ?? `Request failed with status ${response.status}`,
71
+ response.status,
72
+ errorBody?.code
73
+ )
74
+ };
75
+ }
76
+ return { data: payload, error: null };
77
+ } catch (err) {
78
+ const message = err instanceof Error ? err.message : "Network request failed";
79
+ return { data: null, error: new AuthError(message, 0, "network_error") };
80
+ }
81
+ };
82
+
46
83
  // src/server.ts
47
84
  var createServerClient = (secretKey, options = {}) => {
48
- const baseUrl = resolveBaseUrl(options.__internalBaseUrl);
49
- const fetchImpl = options.fetch ?? fetch;
85
+ const base = { apikey: secretKey, baseUrl: resolveBaseUrl(options.__internalBaseUrl), fetchImpl: options.fetch };
86
+ const connection = (id) => `/auth/v1/connections/${encodeURIComponent(id)}`;
50
87
  return {
51
88
  auth: {
52
89
  async getUser(jwt) {
53
- try {
54
- const response = await fetchImpl(`${baseUrl}/auth/v1/user`, {
55
- headers: { Authorization: `Bearer ${jwt}`, apikey: secretKey }
56
- });
57
- let payload = null;
58
- try {
59
- payload = await response.json();
60
- } catch {
61
- payload = null;
62
- }
63
- if (!response.ok) {
64
- const errorBody = payload?.error;
65
- return {
66
- data: { user: null },
67
- error: new AuthError(
68
- errorBody?.message ?? `Request failed with status ${response.status}`,
69
- response.status,
70
- errorBody?.code
71
- )
72
- };
73
- }
74
- return { data: { user: payload }, error: null };
75
- } catch (err) {
76
- const message = err instanceof Error ? err.message : "Network request failed";
77
- return { data: { user: null }, error: new AuthError(message, 0, "network_error") };
78
- }
90
+ const { data, error } = await request({ ...base, method: "GET", path: "/auth/v1/user", accessToken: jwt });
91
+ return { data: { user: data }, error };
92
+ }
93
+ },
94
+ connections: {
95
+ async list({ userId }) {
96
+ const { data, error } = await request({
97
+ ...base,
98
+ method: "GET",
99
+ path: `/auth/v1/connections?user_id=${encodeURIComponent(userId)}`
100
+ });
101
+ return { data: { connections: data?.connections ?? [] }, error };
102
+ },
103
+ async issueAccessToken(connectionId) {
104
+ return request({
105
+ ...base,
106
+ method: "POST",
107
+ path: `${connection(connectionId)}/token`,
108
+ body: {}
109
+ });
110
+ },
111
+ async revoke(connectionId) {
112
+ const { error } = await request({ ...base, method: "DELETE", path: connection(connectionId) });
113
+ return { error };
114
+ }
115
+ },
116
+ apiKeys: {
117
+ async create({ userId, name }) {
118
+ const { data, error } = await request({
119
+ ...base,
120
+ method: "POST",
121
+ path: "/auth/v1/api-keys",
122
+ body: { user_id: userId, name }
123
+ });
124
+ return { data: { apiKey: data?.api_key ?? null, key: data?.key ?? null }, error };
125
+ },
126
+ async list({ userId }) {
127
+ const { data, error } = await request({
128
+ ...base,
129
+ method: "GET",
130
+ path: `/auth/v1/api-keys?user_id=${encodeURIComponent(userId)}`
131
+ });
132
+ return { data: { apiKeys: data?.api_keys ?? [] }, error };
133
+ },
134
+ async revoke(apiKeyId) {
135
+ const { error } = await request({
136
+ ...base,
137
+ method: "DELETE",
138
+ path: `/auth/v1/api-keys/${encodeURIComponent(apiKeyId)}`
139
+ });
140
+ return { error };
141
+ },
142
+ // The key travels in the request body so it never reaches a URL or an access log.
143
+ async verify(apiKey) {
144
+ const { data, error } = await request({
145
+ ...base,
146
+ method: "POST",
147
+ path: "/auth/v1/api-keys/verify",
148
+ body: { api_key: apiKey }
149
+ });
150
+ return { data: { user: data?.user ?? null, apiKey: data?.api_key ?? null }, error };
79
151
  }
80
152
  }
81
153
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/constants.ts","../src/types.ts"],"sourcesContent":["import { resolveBaseUrl } from './constants'\nimport { AuthError, type ServerClientOptions, type User } from './types'\n\nexport interface ServerAuthClient {\n auth: {\n // Mirrors `supabase.auth.getUser(jwt)` server-side: validates the access token\n // against the auth service and returns the user.\n getUser(jwt: string): Promise<{ data: { user: User | null }; error: AuthError | null }>\n }\n}\n\n// Runs anywhere with global fetch (Bun, Node >= 18). `secretKey` is the project's\n// bt_secret_... key. Requests target the hosted DeepKey API; the internal\n// override is reserved for DeepKey's console and tests.\nexport const createServerClient = (secretKey: string, options: ServerClientOptions = {}): ServerAuthClient => {\n const baseUrl = resolveBaseUrl(options.__internalBaseUrl)\n const fetchImpl = options.fetch ?? fetch\n\n return {\n auth: {\n async getUser(jwt: string) {\n try {\n const response = await fetchImpl(`${baseUrl}/auth/v1/user`, {\n headers: { Authorization: `Bearer ${jwt}`, apikey: secretKey },\n })\n\n let payload: unknown = null\n try {\n payload = await response.json()\n } catch {\n payload = null\n }\n\n if (!response.ok) {\n const errorBody = (payload as { error?: { code?: string; message?: string } } | null)?.error\n return {\n data: { user: null },\n error: new AuthError(\n errorBody?.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody?.code,\n ),\n }\n }\n\n return { data: { user: payload as User }, error: null }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Network request failed'\n return { data: { user: null }, error: new AuthError(message, 0, 'network_error') }\n }\n },\n },\n }\n}\n\nexport { DEEPKEY_API_URL } from './constants'\nexport { AuthError, type ServerClientOptions, type User } from './types'\n","// The hosted DeepKey API. Every client talks to this origin; only DeepKey's own\n// console and test suites replace it through the internal override.\nexport const DEEPKEY_API_URL = 'https://deepkey.dev/api'\n\n// Resolves the base URL used for every request. An absent or blank internal\n// override keeps the hosted API; a provided value has any trailing slash removed\n// so path joins stay predictable.\nexport const resolveBaseUrl = (url?: string | null): string => {\n const candidate = typeof url === 'string' ? url.trim() : ''\n return (candidate || DEEPKEY_API_URL).replace(/\\/+$/, '')\n}\n","export interface UserIdentity {\n identity_id: string\n id: string\n user_id: string\n provider: string\n identity_data: Record<string, unknown>\n last_sign_in_at: string | null\n created_at: string\n updated_at: string\n}\n\nexport interface User {\n id: string\n aud: string\n role: string\n email: string | null\n email_confirmed_at: string | null\n app_metadata: { provider?: string | null; providers?: string[]; [key: string]: unknown }\n user_metadata: {\n name?: string\n full_name?: string\n avatar_url?: string\n picture?: string\n email?: string\n [key: string]: unknown\n }\n identities?: UserIdentity[]\n created_at: string\n updated_at?: string\n last_sign_in_at?: string | null\n}\n\nexport interface Session {\n access_token: string\n refresh_token: string\n token_type: 'bearer'\n expires_in: number\n expires_at: number\n user: User\n}\n\nexport class AuthError extends Error {\n status?: number\n code?: string\n\n constructor(message: string, status?: number, code?: string) {\n super(message)\n this.name = 'AuthError'\n this.status = status\n this.code = code\n }\n}\n\nexport type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED'\n\nexport interface Subscription {\n id: string\n unsubscribe: () => void\n}\n\nexport interface StorageAdapter {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\nexport interface AuthClientOptions {\n /**\n * @internal Replaces the hosted DeepKey API origin. Used only by DeepKey's own\n * console and test suites; not supported for consumers and stripped from the\n * published type declarations.\n */\n __internalBaseUrl?: string\n storageKey?: string\n autoRefreshToken?: boolean\n detectSessionInUrl?: boolean\n persistSession?: boolean\n storage?: StorageAdapter\n fetch?: typeof fetch\n}\n\nexport interface ServerClientOptions {\n /**\n * @internal Replaces the hosted DeepKey API origin. Used only by DeepKey's own\n * console and test suites; not supported for consumers and stripped from the\n * published type declarations.\n */\n __internalBaseUrl?: string\n fetch?: typeof fetch\n}\n\nexport interface SignInWithOtpCredentials {\n email: string\n options?: {\n emailRedirectTo?: string\n shouldCreateUser?: boolean\n data?: Record<string, unknown>\n }\n}\n\nexport interface VerifyOtpParams {\n email: string\n token: string\n type: 'email' | 'magiclink'\n}\n\nexport interface SignInWithOAuthCredentials {\n provider: string\n options?: {\n redirectTo?: string\n scopes?: string\n queryParams?: Record<string, string>\n skipBrowserRedirect?: boolean\n }\n}\n\nexport interface AuthResponse<T> {\n data: T\n error: AuthError | null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,kBAAkB;AAKxB,IAAM,iBAAiB,CAAC,QAAgC;AAC7D,QAAM,YAAY,OAAO,QAAQ,WAAW,IAAI,KAAK,IAAI;AACzD,UAAQ,aAAa,iBAAiB,QAAQ,QAAQ,EAAE;AAC1D;;;AC+BO,IAAM,YAAN,cAAwB,MAAM;AAAA,EAInC,YAAY,SAAiB,QAAiB,MAAe;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;;;AFrCO,IAAM,qBAAqB,CAAC,WAAmB,UAA+B,CAAC,MAAwB;AAC5G,QAAM,UAAU,eAAe,QAAQ,iBAAiB;AACxD,QAAM,YAAY,QAAQ,SAAS;AAEnC,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,MAAM,QAAQ,KAAa;AACzB,YAAI;AACF,gBAAM,WAAW,MAAM,UAAU,GAAG,OAAO,iBAAiB;AAAA,YAC1D,SAAS,EAAE,eAAe,UAAU,GAAG,IAAI,QAAQ,UAAU;AAAA,UAC/D,CAAC;AAED,cAAI,UAAmB;AACvB,cAAI;AACF,sBAAU,MAAM,SAAS,KAAK;AAAA,UAChC,QAAQ;AACN,sBAAU;AAAA,UACZ;AAEA,cAAI,CAAC,SAAS,IAAI;AAChB,kBAAM,YAAa,SAAoE;AACvF,mBAAO;AAAA,cACL,MAAM,EAAE,MAAM,KAAK;AAAA,cACnB,OAAO,IAAI;AAAA,gBACT,WAAW,WAAW,8BAA8B,SAAS,MAAM;AAAA,gBACnE,SAAS;AAAA,gBACT,WAAW;AAAA,cACb;AAAA,YACF;AAAA,UACF;AAEA,iBAAO,EAAE,MAAM,EAAE,MAAM,QAAgB,GAAG,OAAO,KAAK;AAAA,QACxD,SAAS,KAAK;AACZ,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,iBAAO,EAAE,MAAM,EAAE,MAAM,KAAK,GAAG,OAAO,IAAI,UAAU,SAAS,GAAG,eAAe,EAAE;AAAA,QACnF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/server.ts","../src/constants.ts","../src/types.ts","../src/fetch.ts"],"sourcesContent":["import { resolveBaseUrl } from './constants'\nimport { request } from './fetch'\nimport type {\n AuthError,\n AuthResponse,\n ProviderAccessToken,\n ProviderConnection,\n ServerClientOptions,\n User,\n UserApiKey,\n} from './types'\n\nexport interface ServerAuthClient {\n auth: {\n // Mirrors `supabase.auth.getUser(jwt)` server-side: validates the access token\n // against the auth service and returns the user.\n getUser(jwt: string): Promise<AuthResponse<{ user: User | null }>>\n }\n // Provider connections a user granted through the browser SDK. The secret key acts\n // for the whole project; provider access tokens are issued only here, never to browsers.\n connections: {\n list(params: { userId: string }): Promise<AuthResponse<{ connections: ProviderConnection[] }>>\n issueAccessToken(connectionId: string): Promise<AuthResponse<ProviderAccessToken | null>>\n revoke(connectionId: string): Promise<{ error: AuthError | null }>\n }\n // Long-lived keys your application issues to its own users. Every call uses the secret\n // key; `verify` is the API-key counterpart of `auth.getUser(jwt)` and returns the same user.\n apiKeys: {\n // `key` is the plaintext. It is returned here once and cannot be read again.\n create(params: {\n userId: string\n name?: string\n }): Promise<AuthResponse<{ apiKey: UserApiKey | null; key: string | null }>>\n list(params: { userId: string }): Promise<AuthResponse<{ apiKeys: UserApiKey[] }>>\n revoke(apiKeyId: string): Promise<{ error: AuthError | null }>\n verify(apiKey: string): Promise<AuthResponse<{ user: User | null; apiKey: UserApiKey | null }>>\n }\n}\n\n// Runs anywhere with global fetch (Bun, Node >= 18). `secretKey` is the project's\n// bt_secret_... key. Requests target the hosted DeepKey API; the internal\n// override is reserved for DeepKey's console and tests.\nexport const createServerClient = (secretKey: string, options: ServerClientOptions = {}): ServerAuthClient => {\n const base = { apikey: secretKey, baseUrl: resolveBaseUrl(options.__internalBaseUrl), fetchImpl: options.fetch }\n const connection = (id: string) => `/auth/v1/connections/${encodeURIComponent(id)}`\n\n return {\n auth: {\n async getUser(jwt: string) {\n const { data, error } = await request<User>({ ...base, method: 'GET', path: '/auth/v1/user', accessToken: jwt })\n return { data: { user: data }, error }\n },\n },\n connections: {\n async list({ userId }) {\n const { data, error } = await request<{ connections: ProviderConnection[] }>({\n ...base,\n method: 'GET',\n path: `/auth/v1/connections?user_id=${encodeURIComponent(userId)}`,\n })\n return { data: { connections: data?.connections ?? [] }, error }\n },\n async issueAccessToken(connectionId) {\n return request<ProviderAccessToken>({\n ...base,\n method: 'POST',\n path: `${connection(connectionId)}/token`,\n body: {},\n })\n },\n async revoke(connectionId) {\n const { error } = await request({ ...base, method: 'DELETE', path: connection(connectionId) })\n return { error }\n },\n },\n apiKeys: {\n async create({ userId, name }) {\n const { data, error } = await request<{ api_key: UserApiKey; key: string }>({\n ...base,\n method: 'POST',\n path: '/auth/v1/api-keys',\n body: { user_id: userId, name },\n })\n return { data: { apiKey: data?.api_key ?? null, key: data?.key ?? null }, error }\n },\n async list({ userId }) {\n const { data, error } = await request<{ api_keys: UserApiKey[] }>({\n ...base,\n method: 'GET',\n path: `/auth/v1/api-keys?user_id=${encodeURIComponent(userId)}`,\n })\n return { data: { apiKeys: data?.api_keys ?? [] }, error }\n },\n async revoke(apiKeyId) {\n const { error } = await request({\n ...base,\n method: 'DELETE',\n path: `/auth/v1/api-keys/${encodeURIComponent(apiKeyId)}`,\n })\n return { error }\n },\n // The key travels in the request body so it never reaches a URL or an access log.\n async verify(apiKey) {\n const { data, error } = await request<{ user: User; api_key: UserApiKey }>({\n ...base,\n method: 'POST',\n path: '/auth/v1/api-keys/verify',\n body: { api_key: apiKey },\n })\n return { data: { user: data?.user ?? null, apiKey: data?.api_key ?? null }, error }\n },\n },\n }\n}\n\nexport { DEEPKEY_API_URL } from './constants'\nexport {\n AuthError,\n type AuthResponse,\n type ProviderAccessToken,\n type ProviderConnection,\n type ServerClientOptions,\n type User,\n type UserApiKey,\n} from './types'\n","// The hosted DeepKey API. Every client talks to this origin; only DeepKey's own\n// console and test suites replace it through the internal override.\nexport const DEEPKEY_API_URL = 'https://deepkey.dev/api'\n\n// Resolves the base URL used for every request. An absent or blank internal\n// override keeps the hosted API; a provided value has any trailing slash removed\n// so path joins stay predictable.\nexport const resolveBaseUrl = (url?: string | null): string => {\n const candidate = typeof url === 'string' ? url.trim() : ''\n return (candidate || DEEPKEY_API_URL).replace(/\\/+$/, '')\n}\n","export interface UserIdentity {\n identity_id: string\n id: string\n user_id: string\n provider: string\n identity_data: Record<string, unknown>\n last_sign_in_at: string | null\n created_at: string\n updated_at: string\n}\n\nexport interface User {\n id: string\n aud: string\n role: string\n email: string | null\n email_confirmed_at: string | null\n app_metadata: { provider?: string | null; providers?: string[]; [key: string]: unknown }\n user_metadata: {\n name?: string\n full_name?: string\n avatar_url?: string\n picture?: string\n email?: string\n [key: string]: unknown\n }\n identities?: UserIdentity[]\n created_at: string\n updated_at?: string\n last_sign_in_at?: string | null\n}\n\nexport interface Session {\n access_token: string\n refresh_token: string\n token_type: 'bearer'\n expires_in: number\n expires_at: number\n user: User\n}\n\nexport class AuthError extends Error {\n status?: number\n code?: string\n\n constructor(message: string, status?: number, code?: string) {\n super(message)\n this.name = 'AuthError'\n this.status = status\n this.code = code\n }\n}\n\nexport type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED'\n\nexport interface Subscription {\n id: string\n unsubscribe: () => void\n}\n\nexport interface StorageAdapter {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\nexport interface AuthClientOptions {\n /**\n * @internal Replaces the hosted DeepKey API origin. Used only by DeepKey's own\n * console and test suites; not supported for consumers and stripped from the\n * published type declarations.\n */\n __internalBaseUrl?: string\n storageKey?: string\n autoRefreshToken?: boolean\n detectSessionInUrl?: boolean\n persistSession?: boolean\n storage?: StorageAdapter\n fetch?: typeof fetch\n}\n\nexport interface ServerClientOptions {\n /**\n * @internal Replaces the hosted DeepKey API origin. Used only by DeepKey's own\n * console and test suites; not supported for consumers and stripped from the\n * published type declarations.\n */\n __internalBaseUrl?: string\n fetch?: typeof fetch\n}\n\nexport interface SignInWithOtpCredentials {\n email: string\n options?: {\n emailRedirectTo?: string\n shouldCreateUser?: boolean\n data?: Record<string, unknown>\n }\n}\n\nexport interface VerifyOtpParams {\n email: string\n token: string\n type: 'email' | 'magiclink'\n}\n\nexport interface ConnectProviderCredentials {\n provider: string\n options?: {\n redirectTo?: string\n skipBrowserRedirect?: boolean\n }\n}\n\n// Metadata only: provider tokens never appear in browser responses.\nexport interface ProviderConnection {\n id: string\n // The DeepKey user that granted the connection: the same `user.id` your server gets from getUser(jwt).\n user_id: string\n provider: string\n provider_user_id: string\n identity_data: Record<string, unknown>\n scope: string | null\n status: 'active' | 'reauthorization_required'\n created_at: string\n updated_at: string\n}\n\n// Issued to consumer servers through the secret key; short-lived and refreshed by DeepKey.\nexport interface ProviderAccessToken {\n access_token: string\n token_type: 'bearer'\n expires_at: number | null\n scope: string | null\n}\n\n// A long-lived credential your application issues to one of its users. Not the project\n// key: the plaintext is returned once by `apiKeys.create` and is never readable again.\nexport interface UserApiKey {\n id: string\n // The DeepKey user the key acts for: the same `user.id` your server gets from getUser(jwt).\n user_id: string\n name: string | null\n // Last four characters of the plaintext, for display.\n last4: string\n // Last successful `apiKeys.verify`; null until the key is used.\n last_used_at: string | null\n // Set once the key is revoked; a revoked key never verifies again.\n revoked_at: string | null\n created_at: string\n}\n\nexport interface SignInWithOAuthCredentials {\n provider: string\n options?: {\n redirectTo?: string\n scopes?: string\n queryParams?: Record<string, string>\n skipBrowserRedirect?: boolean\n }\n}\n\nexport interface AuthResponse<T> {\n data: T\n error: AuthError | null\n}\n","import { AuthError } from './types'\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PUT' | 'DELETE'\n path: string\n apikey: string\n baseUrl: string\n accessToken?: string\n body?: unknown\n fetchImpl?: typeof fetch\n}\n\nexport interface RequestResult<T> {\n data: T | null\n error: AuthError | null\n}\n\n// All service errors are shaped { error: { code, message } }.\nexport const request = async <T>(options: RequestOptions): Promise<RequestResult<T>> => {\n const fetchImpl = options.fetchImpl ?? fetch\n try {\n const headers: Record<string, string> = { apikey: options.apikey }\n if (options.body !== undefined) headers['Content-Type'] = 'application/json'\n if (options.accessToken) headers.Authorization = `Bearer ${options.accessToken}`\n\n const response = await fetchImpl(`${options.baseUrl}${options.path}`, {\n method: options.method,\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n })\n\n if (response.status === 204) return { data: {} as T, error: null }\n\n let payload: unknown\n try {\n payload = await response.json()\n } catch {\n payload = null\n }\n\n if (!response.ok) {\n const errorBody = (payload as { error?: { code?: string; message?: string } } | null)?.error\n return {\n data: null,\n error: new AuthError(\n errorBody?.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody?.code,\n ),\n }\n }\n\n return { data: payload as T, error: null }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Network request failed'\n return { data: null, error: new AuthError(message, 0, 'network_error') }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/server.d.cts CHANGED
@@ -1,16 +1,45 @@
1
- import { U as User, f as AuthError, g as ServerClientOptions } from './constants-BQhswdms.cjs';
2
- export { D as DEEPKEY_API_URL } from './constants-BQhswdms.cjs';
1
+ import { A as AuthResponse, U as User, P as ProviderConnection, g as ProviderAccessToken, a as AuthError, j as UserApiKey, h as ServerClientOptions } from './constants-ByCalul7.cjs';
2
+ export { D as DEEPKEY_API_URL } from './constants-ByCalul7.cjs';
3
3
 
4
4
  interface ServerAuthClient {
5
5
  auth: {
6
- getUser(jwt: string): Promise<{
7
- data: {
8
- user: User | null;
9
- };
6
+ getUser(jwt: string): Promise<AuthResponse<{
7
+ user: User | null;
8
+ }>>;
9
+ };
10
+ connections: {
11
+ list(params: {
12
+ userId: string;
13
+ }): Promise<AuthResponse<{
14
+ connections: ProviderConnection[];
15
+ }>>;
16
+ issueAccessToken(connectionId: string): Promise<AuthResponse<ProviderAccessToken | null>>;
17
+ revoke(connectionId: string): Promise<{
18
+ error: AuthError | null;
19
+ }>;
20
+ };
21
+ apiKeys: {
22
+ create(params: {
23
+ userId: string;
24
+ name?: string;
25
+ }): Promise<AuthResponse<{
26
+ apiKey: UserApiKey | null;
27
+ key: string | null;
28
+ }>>;
29
+ list(params: {
30
+ userId: string;
31
+ }): Promise<AuthResponse<{
32
+ apiKeys: UserApiKey[];
33
+ }>>;
34
+ revoke(apiKeyId: string): Promise<{
10
35
  error: AuthError | null;
11
36
  }>;
37
+ verify(apiKey: string): Promise<AuthResponse<{
38
+ user: User | null;
39
+ apiKey: UserApiKey | null;
40
+ }>>;
12
41
  };
13
42
  }
14
43
  declare const createServerClient: (secretKey: string, options?: ServerClientOptions) => ServerAuthClient;
15
44
 
16
- export { AuthError, type ServerAuthClient, ServerClientOptions, User, createServerClient };
45
+ export { AuthError, AuthResponse, ProviderAccessToken, ProviderConnection, type ServerAuthClient, ServerClientOptions, User, UserApiKey, createServerClient };
package/dist/server.d.ts CHANGED
@@ -1,16 +1,45 @@
1
- import { U as User, f as AuthError, g as ServerClientOptions } from './constants-BQhswdms.js';
2
- export { D as DEEPKEY_API_URL } from './constants-BQhswdms.js';
1
+ import { A as AuthResponse, U as User, P as ProviderConnection, g as ProviderAccessToken, a as AuthError, j as UserApiKey, h as ServerClientOptions } from './constants-ByCalul7.js';
2
+ export { D as DEEPKEY_API_URL } from './constants-ByCalul7.js';
3
3
 
4
4
  interface ServerAuthClient {
5
5
  auth: {
6
- getUser(jwt: string): Promise<{
7
- data: {
8
- user: User | null;
9
- };
6
+ getUser(jwt: string): Promise<AuthResponse<{
7
+ user: User | null;
8
+ }>>;
9
+ };
10
+ connections: {
11
+ list(params: {
12
+ userId: string;
13
+ }): Promise<AuthResponse<{
14
+ connections: ProviderConnection[];
15
+ }>>;
16
+ issueAccessToken(connectionId: string): Promise<AuthResponse<ProviderAccessToken | null>>;
17
+ revoke(connectionId: string): Promise<{
18
+ error: AuthError | null;
19
+ }>;
20
+ };
21
+ apiKeys: {
22
+ create(params: {
23
+ userId: string;
24
+ name?: string;
25
+ }): Promise<AuthResponse<{
26
+ apiKey: UserApiKey | null;
27
+ key: string | null;
28
+ }>>;
29
+ list(params: {
30
+ userId: string;
31
+ }): Promise<AuthResponse<{
32
+ apiKeys: UserApiKey[];
33
+ }>>;
34
+ revoke(apiKeyId: string): Promise<{
10
35
  error: AuthError | null;
11
36
  }>;
37
+ verify(apiKey: string): Promise<AuthResponse<{
38
+ user: User | null;
39
+ apiKey: UserApiKey | null;
40
+ }>>;
12
41
  };
13
42
  }
14
43
  declare const createServerClient: (secretKey: string, options?: ServerClientOptions) => ServerAuthClient;
15
44
 
16
- export { AuthError, type ServerAuthClient, ServerClientOptions, User, createServerClient };
45
+ export { AuthError, AuthResponse, ProviderAccessToken, ProviderConnection, type ServerAuthClient, ServerClientOptions, User, UserApiKey, createServerClient };