@deepkey/sdk 1.0.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/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # @deepkey/sdk
2
+
3
+ Authentication SDK for **DeepKey** — passwordless and social sign-in with a **supabase-js compatible surface**. If you have code written against `supabase.auth.*`, the call sites, response envelopes, and auth events port 1:1.
4
+
5
+ The full reference lives at [deepkey.dev/sdk](https://deepkey.dev/sdk).
6
+
7
+ Two entry points:
8
+
9
+ | Import | Runs in | Key used | Purpose |
10
+ |---|---|---|---|
11
+ | `@deepkey/sdk` | Browser (SPA) | Publishable key (`bt_pub_…`) | Sign-in flows, session management, auto-refresh |
12
+ | `@deepkey/sdk/server` | Server (Node ≥ 18, Bun, edge) | Secret key (`bt_secret_…`) | Validate access tokens, fetch the user |
13
+
14
+ ```bash
15
+ npm install @deepkey/sdk
16
+ ```
17
+
18
+ ## Core concepts
19
+
20
+ - **Hosted API** — every request goes to `https://deepkey.dev/api/auth/v1/*`. The URL is built in; you only pass a key.
21
+ - **Project** — each consuming app is a project on DeepKey. The project is resolved from the API key sent with every request (`apikey` header).
22
+ - **Publishable key** (`bt_pub_<project-slug>_<random>`) — safe to ship in browser bundles. Identifies the project; grants no privileged access.
23
+ - **Secret key** (`bt_secret_…`) — server-side only. Never expose it in client code.
24
+ - **Session** — `{ access_token, refresh_token, token_type: 'bearer', expires_in, expires_at, user }`. The access token is an ES256 JWT (short-lived); the refresh token is opaque and **rotates on every refresh**.
25
+ - **Sign-in flows** — passwordless only: email OTP (6-digit code), magic link, and OAuth (Google, X). There is **no password sign-in**. Magic link and OAuth complete via the *implicit flow*: DeepKey redirects back to your app with tokens in the URL fragment (`#access_token=…`), which the client picks up automatically.
26
+ - **Redirect allow-list** — every `redirectTo` / `emailRedirectTo` URL must be allow-listed in the project's settings on the DeepKey console (wildcards supported: `*` doesn't cross `/` or `.`, `**` crosses everything). ⚠️ A redirect that is *not* on the list is **not an error** — the service silently falls back to the project's Site URL (same semantics as Supabase). If your login "works but lands on the wrong page", this is why.
27
+
28
+ ## Response envelope (never throws)
29
+
30
+ Every method resolves to `{ data, error }` — network and API failures are returned, not thrown:
31
+
32
+ ```ts
33
+ const { data, error } = await deepkey.auth.getUser()
34
+ if (error) {
35
+ // error is an AuthError: { message: string, status?: number, code?: string }
36
+ // error.code === 'network_error' → request never reached the service (status 0)
37
+ }
38
+ ```
39
+
40
+ Error messages use Supabase's English phrasing (e.g. `Token has expired or is invalid`, `Signups not allowed`), so regex-based error translation written for Supabase keeps working.
41
+
42
+ ## Browser client
43
+
44
+ ### Setup
45
+
46
+ ```ts
47
+ import { createAuthClient } from '@deepkey/sdk'
48
+
49
+ export const deepkey = createAuthClient(import.meta.env.VITE_DEEPKEY_PUB_KEY) // bt_pub_...
50
+ // deepkey.auth is the supabase-js-shaped auth interface
51
+ ```
52
+
53
+ Create **one client per app** (module singleton). On construction the client:
54
+
55
+ 1. Checks the URL fragment for implicit-flow tokens (`#access_token=…`) — if present, strips them from the address bar, validates them against the service, saves the session, and emits `SIGNED_IN`.
56
+ 2. Otherwise restores the persisted session from `localStorage` (refreshing it first if expired).
57
+ 3. Starts a background refresh timer (checks every 30s, refreshes when the access token is within 90s of expiry).
58
+
59
+ An empty key does **not** throw at construction — failures surface on the first call.
60
+
61
+ The constant `DEEPKEY_API_URL` exports the hosted origin for building your own URLs (for example the JWKS endpoint).
62
+
63
+ ### Options (all optional)
64
+
65
+ ```ts
66
+ createAuthClient(publishableKey, {
67
+ persistSession: true, // persist to storage (default true)
68
+ autoRefreshToken: true, // background refresh + refresh-on-demand (default true)
69
+ detectSessionInUrl: true, // pick up #access_token fragments (default true)
70
+ storageKey: 'custom-key', // default: 'bt-<project-slug>-auth-token' (derived from the publishable key)
71
+ storage: customAdapter, // { getItem, setItem, removeItem } — default: localStorage, in-memory fallback
72
+ fetch: customFetch, // custom fetch implementation
73
+ })
74
+ ```
75
+
76
+ ### Email OTP / magic link
77
+
78
+ ```ts
79
+ // 1. Send the email (contains BOTH a 6-digit code and a magic link)
80
+ const { error } = await deepkey.auth.signInWithOtp({
81
+ email: 'user@example.com',
82
+ options: {
83
+ emailRedirectTo: window.location.origin, // where the magic link lands (must be allow-listed)
84
+ shouldCreateUser: true, // set false to reject emails without an account
85
+ },
86
+ })
87
+
88
+ // 2a. User types the 6-digit code → verify it
89
+ const { data, error } = await deepkey.auth.verifyOtp({
90
+ email: 'user@example.com',
91
+ token: '123456',
92
+ type: 'email',
93
+ })
94
+ // data.session / data.user are set on success; SIGNED_IN is emitted
95
+
96
+ // 2b. OR the user clicks the magic link → redirected to emailRedirectTo with
97
+ // #access_token=… in the URL; the client handles it automatically on load
98
+ // (detectSessionInUrl) and emits SIGNED_IN. No code needed.
99
+ ```
100
+
101
+ ### OAuth (Google, X)
102
+
103
+ ```ts
104
+ await deepkey.auth.signInWithOAuth({
105
+ provider: 'google', // or 'x'
106
+ options: {
107
+ redirectTo: window.location.origin, // must be allow-listed
108
+ // scopes: 'extra scopes',
109
+ // queryParams: { prompt: 'select_account' },
110
+ // skipBrowserRedirect: true, // don't navigate; just return data.url
111
+ },
112
+ })
113
+ // Performs a full-page redirect to the provider. After consent DeepKey
114
+ // redirects back to redirectTo with #access_token=… — handled automatically
115
+ // on load, SIGNED_IN is emitted.
116
+ ```
117
+
118
+ ### Auth state (drive your UI from this)
119
+
120
+ ```ts
121
+ const { data: { subscription } } = deepkey.auth.onAuthStateChange((event, session) => {
122
+ // event: 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED'
123
+ // session: Session | null
124
+ })
125
+ subscription.unsubscribe()
126
+ ```
127
+
128
+ - Every subscriber receives **`INITIAL_SESSION`** (asynchronously) once initialization settles — use it to resolve your app's loading state. `session` is `null` if the user is signed out.
129
+ - `TOKEN_REFRESHED` fires on background refreshes and cross-tab session updates.
130
+ - `SIGNED_OUT` fires on `signOut()`, when the refresh token is rejected, and when another tab signs out.
131
+ - Sessions sync across tabs automatically (via `storage` events).
132
+
133
+ ### Session access
134
+
135
+ ```ts
136
+ // Current session (refreshes first if expired) — local, fast, use for tokens:
137
+ const { data: { session } } = await deepkey.auth.getSession()
138
+ const accessToken = session?.access_token // send as Authorization: Bearer <token> to YOUR api
139
+
140
+ // Authoritative user check (validates against DeepKey):
141
+ const { data: { user }, error } = await deepkey.auth.getUser()
142
+
143
+ // Manual refresh (rarely needed — auto-refresh covers normal usage):
144
+ await deepkey.auth.refreshSession()
145
+
146
+ // Sign out (revokes server-side, clears storage, emits SIGNED_OUT):
147
+ await deepkey.auth.signOut()
148
+ ```
149
+
150
+ `getSession()` returns `{ session: null }` (with `error: null`) when signed out or when the stored session could not be refreshed. On *network* failures it keeps and returns the existing session so a flaky connection doesn't log the user out.
151
+
152
+ ### React integration pattern
153
+
154
+ ```tsx
155
+ function AuthProvider({ children }: { children: React.ReactNode }) {
156
+ const [session, setSession] = useState<Session | null>(null)
157
+ const [loading, setLoading] = useState(true)
158
+
159
+ useEffect(() => {
160
+ const { data: { subscription } } = deepkey.auth.onAuthStateChange((_event, session) => {
161
+ setSession(session)
162
+ setLoading(false) // INITIAL_SESSION always arrives, even when signed out
163
+ })
164
+ return () => subscription.unsubscribe()
165
+ }, [])
166
+
167
+ if (loading) return <Spinner />
168
+ return <AuthContext.Provider value={{ session }}>{children}</AuthContext.Provider>
169
+ }
170
+ ```
171
+
172
+ ### Calling your own backend
173
+
174
+ DeepKey authenticates users; **your** API authorizes them. Attach the access token to your requests:
175
+
176
+ ```ts
177
+ const { data: { session } } = await deepkey.auth.getSession()
178
+ await fetch('/api/things', {
179
+ headers: { Authorization: `Bearer ${session?.access_token}` },
180
+ })
181
+ ```
182
+
183
+ ## Server client (validating tokens in your backend)
184
+
185
+ ```ts
186
+ import { createServerClient } from '@deepkey/sdk/server'
187
+
188
+ const deepkey = createServerClient(process.env.DEEPKEY_SECRET_KEY) // bt_secret_...
189
+
190
+ // In your request handler:
191
+ const jwt = request.headers.get('authorization')?.replace(/^Bearer /, '')
192
+ const { data: { user }, error } = await deepkey.auth.getUser(jwt)
193
+ if (error || !user) return new Response('Unauthorized', { status: 401 })
194
+ // user.id is the stable user UUID — key your own tables on it
195
+ ```
196
+
197
+ Alternative — **local JWT verification without a network round-trip**: access tokens are ES256 JWTs; public keys are served at `https://deepkey.dev/api/auth/v1/.well-known/jwks.json`. Verify with `jose`:
198
+
199
+ ```ts
200
+ import { DEEPKEY_API_URL } from '@deepkey/sdk/server'
201
+ import { createRemoteJWKSet, jwtVerify } from 'jose'
202
+
203
+ const jwks = createRemoteJWKSet(new URL(`${DEEPKEY_API_URL}/auth/v1/.well-known/jwks.json`))
204
+ const { payload } = await jwtVerify(jwt, jwks) // payload.sub = user id
205
+ ```
206
+
207
+ Use `getUser()` when you need revocation-awareness (a signed-out session fails immediately); use JWKS verification when latency matters (tokens remain valid until expiry).
208
+
209
+ ## Types (full public surface)
210
+
211
+ ```ts
212
+ // '@deepkey/sdk'
213
+ const DEEPKEY_API_URL: 'https://deepkey.dev/api'
214
+ function createAuthClient(publishableKey: string, options?: AuthClientOptions): { auth: Auth }
215
+
216
+ class Auth {
217
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<AuthResponse<{ user: null; session: null }>>
218
+ verifyOtp(params: VerifyOtpParams): Promise<AuthResponse<{ user: User | null; session: Session | null }>>
219
+ signInWithOAuth(credentials: SignInWithOAuthCredentials): Promise<AuthResponse<{ provider: string; url: string }>>
220
+ onAuthStateChange(cb: (event: AuthChangeEvent, session: Session | null) => void): { data: { subscription: Subscription } }
221
+ getSession(): Promise<AuthResponse<{ session: Session | null }>>
222
+ getUser(jwt?: string): Promise<AuthResponse<{ user: User | null }>>
223
+ refreshSession(currentSession?: { refresh_token: string }): Promise<AuthResponse<{ session: Session | null; user: User | null }>>
224
+ signOut(): Promise<{ error: AuthError | null }>
225
+ }
226
+
227
+ interface AuthClientOptions {
228
+ persistSession?: boolean
229
+ autoRefreshToken?: boolean
230
+ detectSessionInUrl?: boolean
231
+ storageKey?: string
232
+ storage?: StorageAdapter
233
+ fetch?: typeof fetch
234
+ }
235
+
236
+ type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED'
237
+ interface AuthResponse<T> { data: T; error: AuthError | null }
238
+ class AuthError extends Error { status?: number; code?: string }
239
+
240
+ interface Session {
241
+ access_token: string // ES256 JWT
242
+ refresh_token: string // opaque, single-use (rotates on refresh)
243
+ token_type: 'bearer'
244
+ expires_in: number // seconds
245
+ expires_at: number // unix epoch seconds
246
+ user: User
247
+ }
248
+
249
+ interface User {
250
+ id: string // stable UUID — use as the foreign key in your app
251
+ aud: string
252
+ role: string
253
+ email: string | null
254
+ email_confirmed_at: string | null
255
+ app_metadata: { provider?: string | null; providers?: string[] }
256
+ user_metadata: { name?: string; full_name?: string; avatar_url?: string; picture?: string; email?: string }
257
+ identities?: UserIdentity[] // one per linked provider (google, x, email, …)
258
+ created_at: string
259
+ }
260
+
261
+ // '@deepkey/sdk/server'
262
+ const DEEPKEY_API_URL: 'https://deepkey.dev/api'
263
+ function createServerClient(secretKey: string, options?: ServerClientOptions): {
264
+ auth: { getUser(jwt: string): Promise<{ data: { user: User | null }; error: AuthError | null }> }
265
+ }
266
+ interface ServerClientOptions { fetch?: typeof fetch }
267
+ ```
268
+
269
+ ## HTTP endpoints used (for debugging)
270
+
271
+ All calls send the API key as the `apikey` header against `https://deepkey.dev/api/auth/v1`:
272
+
273
+ | Method call | HTTP request |
274
+ |---|---|
275
+ | `signInWithOtp` | `POST /otp` |
276
+ | `verifyOtp` | `POST /verify` |
277
+ | `signInWithOAuth` | navigate to `GET /authorize?provider=…&apikey=…` |
278
+ | (magic link click) | `GET /verify?token=…` → 302 to your app with `#access_token=…` |
279
+ | token refresh | `POST /token?grant_type=refresh_token` |
280
+ | `getUser` | `GET /user` (with `Authorization: Bearer`) |
281
+ | `signOut` | `POST /logout` |
282
+
283
+ ## Gotchas & troubleshooting
284
+
285
+ - **Login redirects to the wrong URL** → your `redirectTo`/`emailRedirectTo` is not on the project's redirect allow-list; the service silently fell back to the Site URL. Add the URL (with wildcards if needed) in the console.
286
+ - **Session not restored after redirect** → the tokens arrive in the URL *fragment* (`#access_token=…`). Make sure the client is constructed on the page the user lands on, before anything rewrites `location`, and that `detectSessionInUrl` isn't disabled. The fragment is stripped from the address bar immediately after being read.
287
+ - **Using the secret key in the browser (or the publishable key on the server)** → key types are not interchangeable: `bt_pub_…` for the browser client, `bt_secret_…` for `createServerClient`.
288
+ - **`getUser()` returns `Auth session missing!`** (`code: 'session_missing'`) → no active session and no `jwt` argument was passed.
289
+ - **SSR** → the default storage falls back to in-memory when `localStorage` is unavailable, so importing the client on the server is safe, but sessions only persist in the browser. Do sign-in flows client-side; validate tokens server-side with `@deepkey/sdk/server`.
290
+ - **Multiple tabs** → handled: sessions sync via storage events, and refresh-token rotation has a grace window on the service to absorb concurrent refreshes.
291
+
292
+ ## Compatibility with supabase-js
293
+
294
+ Supported and drop-in: `signInWithOtp`, `verifyOtp`, `signInWithOAuth`, `onAuthStateChange`, `getSession`, `getUser`, `refreshSession`, `signOut`, the `{ data, error }` envelopes, the event lifecycle, localStorage persistence, and implicit-flow fragment handling. Not implemented: password auth, phone auth, `updateUser`, admin APIs, and PKCE on the client (the service supports PKCE; the SDK uses the implicit flow).
@@ -0,0 +1,23 @@
1
+ // src/constants.ts
2
+ var DEEPKEY_API_URL = "https://deepkey.dev/api";
3
+ var resolveBaseUrl = (url) => {
4
+ const candidate = typeof url === "string" ? url.trim() : "";
5
+ return (candidate || DEEPKEY_API_URL).replace(/\/+$/, "");
6
+ };
7
+
8
+ // src/types.ts
9
+ var AuthError = class extends Error {
10
+ constructor(message, status, code) {
11
+ super(message);
12
+ this.name = "AuthError";
13
+ this.status = status;
14
+ this.code = code;
15
+ }
16
+ };
17
+
18
+ export {
19
+ DEEPKEY_API_URL,
20
+ resolveBaseUrl,
21
+ AuthError
22
+ };
23
+ //# sourceMappingURL=chunk-IFNRLMVX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/types.ts"],"sourcesContent":["// 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":";AAEO,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;","names":[]}
@@ -0,0 +1,98 @@
1
+ interface UserIdentity {
2
+ identity_id: string;
3
+ id: string;
4
+ user_id: string;
5
+ provider: string;
6
+ identity_data: Record<string, unknown>;
7
+ last_sign_in_at: string | null;
8
+ created_at: string;
9
+ updated_at: string;
10
+ }
11
+ interface User {
12
+ id: string;
13
+ aud: string;
14
+ role: string;
15
+ email: string | null;
16
+ email_confirmed_at: string | null;
17
+ app_metadata: {
18
+ provider?: string | null;
19
+ providers?: string[];
20
+ [key: string]: unknown;
21
+ };
22
+ user_metadata: {
23
+ name?: string;
24
+ full_name?: string;
25
+ avatar_url?: string;
26
+ picture?: string;
27
+ email?: string;
28
+ [key: string]: unknown;
29
+ };
30
+ identities?: UserIdentity[];
31
+ created_at: string;
32
+ updated_at?: string;
33
+ last_sign_in_at?: string | null;
34
+ }
35
+ interface Session {
36
+ access_token: string;
37
+ refresh_token: string;
38
+ token_type: 'bearer';
39
+ expires_in: number;
40
+ expires_at: number;
41
+ user: User;
42
+ }
43
+ declare class AuthError extends Error {
44
+ status?: number;
45
+ code?: string;
46
+ constructor(message: string, status?: number, code?: string);
47
+ }
48
+ type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED';
49
+ interface Subscription {
50
+ id: string;
51
+ unsubscribe: () => void;
52
+ }
53
+ interface StorageAdapter {
54
+ getItem(key: string): string | null;
55
+ setItem(key: string, value: string): void;
56
+ removeItem(key: string): void;
57
+ }
58
+ interface AuthClientOptions {
59
+ storageKey?: string;
60
+ autoRefreshToken?: boolean;
61
+ detectSessionInUrl?: boolean;
62
+ persistSession?: boolean;
63
+ storage?: StorageAdapter;
64
+ fetch?: typeof fetch;
65
+ }
66
+ interface ServerClientOptions {
67
+ fetch?: typeof fetch;
68
+ }
69
+ interface SignInWithOtpCredentials {
70
+ email: string;
71
+ options?: {
72
+ emailRedirectTo?: string;
73
+ shouldCreateUser?: boolean;
74
+ data?: Record<string, unknown>;
75
+ };
76
+ }
77
+ interface VerifyOtpParams {
78
+ email: string;
79
+ token: string;
80
+ type: 'email' | 'magiclink';
81
+ }
82
+ interface SignInWithOAuthCredentials {
83
+ provider: string;
84
+ options?: {
85
+ redirectTo?: string;
86
+ scopes?: string;
87
+ queryParams?: Record<string, string>;
88
+ skipBrowserRedirect?: boolean;
89
+ };
90
+ }
91
+ interface AuthResponse<T> {
92
+ data: T;
93
+ error: AuthError | null;
94
+ }
95
+
96
+ declare const DEEPKEY_API_URL = "https://deepkey.dev/api";
97
+
98
+ export { type AuthClientOptions as A, DEEPKEY_API_URL as D, type SignInWithOtpCredentials as S, type User as U, type VerifyOtpParams as V, type AuthResponse as a, type Session as b, type SignInWithOAuthCredentials as c, type AuthChangeEvent as d, type Subscription as e, AuthError as f, type ServerClientOptions as g, type StorageAdapter as h, type UserIdentity as i };
@@ -0,0 +1,98 @@
1
+ interface UserIdentity {
2
+ identity_id: string;
3
+ id: string;
4
+ user_id: string;
5
+ provider: string;
6
+ identity_data: Record<string, unknown>;
7
+ last_sign_in_at: string | null;
8
+ created_at: string;
9
+ updated_at: string;
10
+ }
11
+ interface User {
12
+ id: string;
13
+ aud: string;
14
+ role: string;
15
+ email: string | null;
16
+ email_confirmed_at: string | null;
17
+ app_metadata: {
18
+ provider?: string | null;
19
+ providers?: string[];
20
+ [key: string]: unknown;
21
+ };
22
+ user_metadata: {
23
+ name?: string;
24
+ full_name?: string;
25
+ avatar_url?: string;
26
+ picture?: string;
27
+ email?: string;
28
+ [key: string]: unknown;
29
+ };
30
+ identities?: UserIdentity[];
31
+ created_at: string;
32
+ updated_at?: string;
33
+ last_sign_in_at?: string | null;
34
+ }
35
+ interface Session {
36
+ access_token: string;
37
+ refresh_token: string;
38
+ token_type: 'bearer';
39
+ expires_in: number;
40
+ expires_at: number;
41
+ user: User;
42
+ }
43
+ declare class AuthError extends Error {
44
+ status?: number;
45
+ code?: string;
46
+ constructor(message: string, status?: number, code?: string);
47
+ }
48
+ type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED';
49
+ interface Subscription {
50
+ id: string;
51
+ unsubscribe: () => void;
52
+ }
53
+ interface StorageAdapter {
54
+ getItem(key: string): string | null;
55
+ setItem(key: string, value: string): void;
56
+ removeItem(key: string): void;
57
+ }
58
+ interface AuthClientOptions {
59
+ storageKey?: string;
60
+ autoRefreshToken?: boolean;
61
+ detectSessionInUrl?: boolean;
62
+ persistSession?: boolean;
63
+ storage?: StorageAdapter;
64
+ fetch?: typeof fetch;
65
+ }
66
+ interface ServerClientOptions {
67
+ fetch?: typeof fetch;
68
+ }
69
+ interface SignInWithOtpCredentials {
70
+ email: string;
71
+ options?: {
72
+ emailRedirectTo?: string;
73
+ shouldCreateUser?: boolean;
74
+ data?: Record<string, unknown>;
75
+ };
76
+ }
77
+ interface VerifyOtpParams {
78
+ email: string;
79
+ token: string;
80
+ type: 'email' | 'magiclink';
81
+ }
82
+ interface SignInWithOAuthCredentials {
83
+ provider: string;
84
+ options?: {
85
+ redirectTo?: string;
86
+ scopes?: string;
87
+ queryParams?: Record<string, string>;
88
+ skipBrowserRedirect?: boolean;
89
+ };
90
+ }
91
+ interface AuthResponse<T> {
92
+ data: T;
93
+ error: AuthError | null;
94
+ }
95
+
96
+ declare const DEEPKEY_API_URL = "https://deepkey.dev/api";
97
+
98
+ export { type AuthClientOptions as A, DEEPKEY_API_URL as D, type SignInWithOtpCredentials as S, type User as U, type VerifyOtpParams as V, type AuthResponse as a, type Session as b, type SignInWithOAuthCredentials as c, type AuthChangeEvent as d, type Subscription as e, AuthError as f, type ServerClientOptions as g, type StorageAdapter as h, type UserIdentity as i };