@smarthivelabs-devs/auth-sdk 1.5.2 → 1.5.4
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 +10 -6
- package/dist/index.cjs +42 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +42 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,9 +21,13 @@ yarn add @smarthivelabs-devs/auth-sdk
|
|
|
21
21
|
You need a SmartHive Auth project. From your SmartHive dashboard grab:
|
|
22
22
|
|
|
23
23
|
- `projectId` — e.g. `proj_abc123`
|
|
24
|
-
- `publishableKey` — e.g. `
|
|
24
|
+
- `publishableKey` — e.g. `pk_prod_abc123` (production) or `pk_dev_abc123` (development)
|
|
25
25
|
- `baseUrl` — the URL of your SmartHive Auth service instance
|
|
26
26
|
|
|
27
|
+
### Publishable key format
|
|
28
|
+
|
|
29
|
+
The key prefix encodes the environment: `pk_prod_*` routes to the production database, `pk_dev_*` routes to the dev database. There is no separate staging environment. All headless requests automatically include the `x-smarthive-publishable-key` header so the server can identify both the project and environment from a single base URL (`/api/auth/*`) — no environment prefix in the path is needed.
|
|
30
|
+
|
|
27
31
|
---
|
|
28
32
|
|
|
29
33
|
## Quick Start
|
|
@@ -33,7 +37,7 @@ import { initAuth } from "@smarthivelabs-devs/auth-sdk";
|
|
|
33
37
|
|
|
34
38
|
const client = initAuth({
|
|
35
39
|
projectId: "proj_abc123",
|
|
36
|
-
publishableKey: "
|
|
40
|
+
publishableKey: "pk_prod_abc123",
|
|
37
41
|
baseUrl: "https://auth.myapp.com",
|
|
38
42
|
redirectUri: "https://myapp.com/auth/callback",
|
|
39
43
|
});
|
|
@@ -103,7 +107,7 @@ Creates and returns a `SmartHiveAuthClient`. Call this once at your app's entry
|
|
|
103
107
|
```ts
|
|
104
108
|
const client = initAuth({
|
|
105
109
|
projectId: "proj_abc123",
|
|
106
|
-
publishableKey: "
|
|
110
|
+
publishableKey: "pk_prod_abc123",
|
|
107
111
|
baseUrl: "https://auth.myapp.com",
|
|
108
112
|
});
|
|
109
113
|
```
|
|
@@ -336,7 +340,7 @@ const myStorage: AuthStorage = {
|
|
|
336
340
|
|
|
337
341
|
const client = initAuth({
|
|
338
342
|
projectId: "proj_abc123",
|
|
339
|
-
publishableKey: "
|
|
343
|
+
publishableKey: "pk_prod_abc123",
|
|
340
344
|
baseUrl: "https://auth.myapp.com",
|
|
341
345
|
storage: myStorage,
|
|
342
346
|
});
|
|
@@ -397,8 +401,8 @@ Common error codes:
|
|
|
397
401
|
import { initAuth, SmartHiveAuthError } from "@smarthivelabs-devs/auth-sdk";
|
|
398
402
|
|
|
399
403
|
const client = initAuth({
|
|
400
|
-
projectId: import.meta.env.VITE_SMARTHIVE_AUTH_PROJECT_ID,
|
|
401
|
-
publishableKey: import.meta.env.VITE_SMARTHIVE_AUTH_PUBLISHABLE_KEY,
|
|
404
|
+
projectId: import.meta.env.VITE_SMARTHIVE_AUTH_PROJECT_ID, // e.g. "proj_abc123"
|
|
405
|
+
publishableKey: import.meta.env.VITE_SMARTHIVE_AUTH_PUBLISHABLE_KEY, // e.g. "pk_prod_abc123"
|
|
402
406
|
baseUrl: import.meta.env.VITE_SMARTHIVE_AUTH_BASE_URL,
|
|
403
407
|
redirectUri: `${window.location.origin}/auth/callback`,
|
|
404
408
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -75,16 +75,14 @@ function normalizeBaseUrl(baseUrl) {
|
|
|
75
75
|
return baseUrl.replace(/\/$/, "");
|
|
76
76
|
}
|
|
77
77
|
function envFromPublishableKey(publishableKey) {
|
|
78
|
-
|
|
79
|
-
return match ? match[1] : "prod";
|
|
78
|
+
return publishableKey.startsWith("pk_dev_") ? "dev" : "prod";
|
|
80
79
|
}
|
|
81
80
|
function initAuth(config) {
|
|
82
81
|
const baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
83
82
|
const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);
|
|
84
83
|
const storage = config.storage ?? browserStorage();
|
|
85
84
|
const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();
|
|
86
|
-
const
|
|
87
|
-
const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;
|
|
85
|
+
const headlessBase = `${baseUrl}/api/auth/headless`;
|
|
88
86
|
async function saveSession(session) {
|
|
89
87
|
if (!session) {
|
|
90
88
|
await storage.removeItem(smartHiveAuthStorageKeys.session);
|
|
@@ -109,7 +107,10 @@ function initAuth(config) {
|
|
|
109
107
|
try {
|
|
110
108
|
res = await fetch(`${headlessBase}${path}`, {
|
|
111
109
|
method: "POST",
|
|
112
|
-
headers: {
|
|
110
|
+
headers: {
|
|
111
|
+
"content-type": "application/json",
|
|
112
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
113
|
+
},
|
|
113
114
|
body: JSON.stringify(body)
|
|
114
115
|
});
|
|
115
116
|
} catch {
|
|
@@ -165,7 +166,10 @@ function initAuth(config) {
|
|
|
165
166
|
async email({ email, password, name }) {
|
|
166
167
|
const res = await fetch(`${headlessBase}/sign-up/email`, {
|
|
167
168
|
method: "POST",
|
|
168
|
-
headers: {
|
|
169
|
+
headers: {
|
|
170
|
+
"content-type": "application/json",
|
|
171
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
172
|
+
},
|
|
169
173
|
body: JSON.stringify({ email, password, name })
|
|
170
174
|
});
|
|
171
175
|
if (res.status === 202) {
|
|
@@ -181,9 +185,12 @@ function initAuth(config) {
|
|
|
181
185
|
return result;
|
|
182
186
|
},
|
|
183
187
|
async resendVerificationEmail({ email }) {
|
|
184
|
-
const res = await fetch(`${authBase}
|
|
188
|
+
const res = await fetch(`${authBase}/api/auth/send-verification-email`, {
|
|
185
189
|
method: "POST",
|
|
186
|
-
headers: {
|
|
190
|
+
headers: {
|
|
191
|
+
"content-type": "application/json",
|
|
192
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
193
|
+
},
|
|
187
194
|
body: JSON.stringify({ email })
|
|
188
195
|
});
|
|
189
196
|
if (!res.ok) {
|
|
@@ -209,7 +216,10 @@ function initAuth(config) {
|
|
|
209
216
|
if (token) {
|
|
210
217
|
await fetch(`${headlessBase}/sign-out`, {
|
|
211
218
|
method: "POST",
|
|
212
|
-
headers: {
|
|
219
|
+
headers: {
|
|
220
|
+
"content-type": "application/json",
|
|
221
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
222
|
+
},
|
|
213
223
|
body: JSON.stringify({ refresh_token: token })
|
|
214
224
|
}).catch(() => {
|
|
215
225
|
});
|
|
@@ -297,7 +307,7 @@ function initAuth(config) {
|
|
|
297
307
|
url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);
|
|
298
308
|
url.searchParams.set("redirect_uri", redirectUri);
|
|
299
309
|
} else {
|
|
300
|
-
url = new URL(`${authBase}
|
|
310
|
+
url = new URL(`${authBase}/api/auth/social/${provider}`);
|
|
301
311
|
url.searchParams.set("project_id", config.projectId);
|
|
302
312
|
url.searchParams.set("redirect_uri", redirectUri);
|
|
303
313
|
}
|
|
@@ -331,7 +341,14 @@ function initAuth(config) {
|
|
|
331
341
|
const session = await readSession();
|
|
332
342
|
if (!session) return null;
|
|
333
343
|
if (session.expiresAt && Date.now() > session.expiresAt - 3e4) {
|
|
334
|
-
|
|
344
|
+
try {
|
|
345
|
+
return (await client.refreshSession())?.accessToken ?? null;
|
|
346
|
+
} catch (err) {
|
|
347
|
+
if (err instanceof SmartHiveAuthError && err.code === "network_error") {
|
|
348
|
+
return session.accessToken;
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
335
352
|
}
|
|
336
353
|
return session.accessToken;
|
|
337
354
|
},
|
|
@@ -352,15 +369,20 @@ function initAuth(config) {
|
|
|
352
369
|
async refreshSession() {
|
|
353
370
|
const session = await readSession();
|
|
354
371
|
if (!session?.refreshToken) return session;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
372
|
+
let response;
|
|
373
|
+
try {
|
|
374
|
+
response = await fetch(`${authBase}/api/auth/oauth2/token`, {
|
|
375
|
+
method: "POST",
|
|
376
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
377
|
+
body: new URLSearchParams({
|
|
378
|
+
grant_type: "refresh_token",
|
|
379
|
+
refresh_token: session.refreshToken,
|
|
380
|
+
client_id: config.publishableKey
|
|
381
|
+
})
|
|
382
|
+
});
|
|
383
|
+
} catch {
|
|
384
|
+
throw new SmartHiveAuthError("network_error", "Unable to reach the auth service. Check your connection.");
|
|
385
|
+
}
|
|
364
386
|
if (!response.ok) {
|
|
365
387
|
const err = await response.json().catch(() => ({}));
|
|
366
388
|
if (response.status < 500) await saveSession(null);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n\n /**\n * Re-send the email verification link to the given address.\n * Use this when the user did not receive the initial verification email.\n */\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n let res: Response;\n try {\n res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string; issues?: unknown[] };\n const detail = err.issues?.length ? ` (${(err.issues as Array<{ message?: string }>).map((i) => i.message).filter(Boolean).join(\"; \")})` : \"\";\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n (err.message ?? `Request to ${path} failed.`) + detail\n );\n }\n\n const data = await res.json().catch(() => {\n throw new SmartHiveAuthError(\"invalid_response\", \"The auth service returned an unexpected response.\");\n }) as RawHeadlessResponse;\n return data;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n\n async resendVerificationEmail({ email }) {\n const res = await fetch(`${authBase}/${environment}/api/auth/send-verification-email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email }),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { message?: string };\n throw new SmartHiveAuthError(\"resend_failed\", err.message ?? \"Failed to resend verification email.\");\n }\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"project_not_found\",\n err.message ?? \"Smart Hive Auth project configuration was not found.\"\n );\n }\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken,\n client_id: config.publishableKey,\n })\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string; message?: string };\n // Only clear the local session on auth failures (4xx) — keep it on server errors (5xx)\n if (response.status < 500) await saveSession(null);\n throw new SmartHiveAuthError(\n err.error ?? \"session_expired\",\n err.error_description ?? err.message ?? \"Session expired. Please sign in again.\"\n );\n }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n if (response.status === 401) return null;\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"userinfo_failed\", err.message ?? \"Failed to fetch user profile.\");\n }\n return response.json();\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n\n /**\n * Re-send the email verification link to the given address.\n * Use this when the user did not receive the initial verification email.\n */\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_* or pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): \"dev\" | \"prod\" {\n return publishableKey.startsWith(\"pk_dev_\") ? \"dev\" : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const headlessBase = `${baseUrl}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n let res: Response;\n try {\n res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify(body),\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string; issues?: unknown[] };\n const detail = err.issues?.length ? ` (${(err.issues as Array<{ message?: string }>).map((i) => i.message).filter(Boolean).join(\"; \")})` : \"\";\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n (err.message ?? `Request to ${path} failed.`) + detail\n );\n }\n\n const data = await res.json().catch(() => {\n throw new SmartHiveAuthError(\"invalid_response\", \"The auth service returned an unexpected response.\");\n }) as RawHeadlessResponse;\n return data;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n\n async resendVerificationEmail({ email }) {\n const res = await fetch(`${authBase}/api/auth/send-verification-email`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ email }),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { message?: string };\n throw new SmartHiveAuthError(\"resend_failed\", err.message ?? \"Failed to resend verification email.\");\n }\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"project_not_found\",\n err.message ?? \"Smart Hive Auth project configuration was not found.\"\n );\n }\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n try {\n return (await client.refreshSession())?.accessToken ?? null;\n } catch (err) {\n // Network unreachable — return the stale token so callers don't crash.\n // The server will 401 if truly expired; on-401 retry will refresh when\n // the network comes back.\n if (err instanceof SmartHiveAuthError && err.code === \"network_error\") {\n return session.accessToken;\n }\n return null;\n }\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n let response: Response;\n try {\n response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken,\n client_id: config.publishableKey,\n })\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string; message?: string };\n // Only clear the local session on auth failures (4xx) — keep it on server errors (5xx)\n if (response.status < 500) await saveSession(null);\n throw new SmartHiveAuthError(\n err.error ?? \"session_expired\",\n err.error_description ?? err.message ?? \"Session expired. Please sign in again.\"\n );\n }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n if (response.status === 401) return null;\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"userinfo_failed\", err.message ?? \"Failed to fetch user profile.\");\n }\n return response.json();\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -175,8 +175,8 @@ declare const smartHiveAuthStorageKeys: {
|
|
|
175
175
|
readonly pkceVerifier: "smarthive.auth.pkce_verifier";
|
|
176
176
|
readonly pkceState: "smarthive.auth.pkce_state";
|
|
177
177
|
};
|
|
178
|
-
/** Extract the environment prefix from a publishable key (pk_dev_
|
|
179
|
-
declare function envFromPublishableKey(publishableKey: string):
|
|
178
|
+
/** Extract the environment prefix from a publishable key (pk_dev_* or pk_prod_*). */
|
|
179
|
+
declare function envFromPublishableKey(publishableKey: string): "dev" | "prod";
|
|
180
180
|
declare function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient;
|
|
181
181
|
|
|
182
182
|
export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, type SocialProvider, envFromPublishableKey, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
|
package/dist/index.d.ts
CHANGED
|
@@ -175,8 +175,8 @@ declare const smartHiveAuthStorageKeys: {
|
|
|
175
175
|
readonly pkceVerifier: "smarthive.auth.pkce_verifier";
|
|
176
176
|
readonly pkceState: "smarthive.auth.pkce_state";
|
|
177
177
|
};
|
|
178
|
-
/** Extract the environment prefix from a publishable key (pk_dev_
|
|
179
|
-
declare function envFromPublishableKey(publishableKey: string):
|
|
178
|
+
/** Extract the environment prefix from a publishable key (pk_dev_* or pk_prod_*). */
|
|
179
|
+
declare function envFromPublishableKey(publishableKey: string): "dev" | "prod";
|
|
180
180
|
declare function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient;
|
|
181
181
|
|
|
182
182
|
export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, type SocialProvider, envFromPublishableKey, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
|
package/dist/index.js
CHANGED
|
@@ -46,16 +46,14 @@ function normalizeBaseUrl(baseUrl) {
|
|
|
46
46
|
return baseUrl.replace(/\/$/, "");
|
|
47
47
|
}
|
|
48
48
|
function envFromPublishableKey(publishableKey) {
|
|
49
|
-
|
|
50
|
-
return match ? match[1] : "prod";
|
|
49
|
+
return publishableKey.startsWith("pk_dev_") ? "dev" : "prod";
|
|
51
50
|
}
|
|
52
51
|
function initAuth(config) {
|
|
53
52
|
const baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
54
53
|
const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);
|
|
55
54
|
const storage = config.storage ?? browserStorage();
|
|
56
55
|
const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();
|
|
57
|
-
const
|
|
58
|
-
const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;
|
|
56
|
+
const headlessBase = `${baseUrl}/api/auth/headless`;
|
|
59
57
|
async function saveSession(session) {
|
|
60
58
|
if (!session) {
|
|
61
59
|
await storage.removeItem(smartHiveAuthStorageKeys.session);
|
|
@@ -80,7 +78,10 @@ function initAuth(config) {
|
|
|
80
78
|
try {
|
|
81
79
|
res = await fetch(`${headlessBase}${path}`, {
|
|
82
80
|
method: "POST",
|
|
83
|
-
headers: {
|
|
81
|
+
headers: {
|
|
82
|
+
"content-type": "application/json",
|
|
83
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
84
|
+
},
|
|
84
85
|
body: JSON.stringify(body)
|
|
85
86
|
});
|
|
86
87
|
} catch {
|
|
@@ -136,7 +137,10 @@ function initAuth(config) {
|
|
|
136
137
|
async email({ email, password, name }) {
|
|
137
138
|
const res = await fetch(`${headlessBase}/sign-up/email`, {
|
|
138
139
|
method: "POST",
|
|
139
|
-
headers: {
|
|
140
|
+
headers: {
|
|
141
|
+
"content-type": "application/json",
|
|
142
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
143
|
+
},
|
|
140
144
|
body: JSON.stringify({ email, password, name })
|
|
141
145
|
});
|
|
142
146
|
if (res.status === 202) {
|
|
@@ -152,9 +156,12 @@ function initAuth(config) {
|
|
|
152
156
|
return result;
|
|
153
157
|
},
|
|
154
158
|
async resendVerificationEmail({ email }) {
|
|
155
|
-
const res = await fetch(`${authBase}
|
|
159
|
+
const res = await fetch(`${authBase}/api/auth/send-verification-email`, {
|
|
156
160
|
method: "POST",
|
|
157
|
-
headers: {
|
|
161
|
+
headers: {
|
|
162
|
+
"content-type": "application/json",
|
|
163
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
164
|
+
},
|
|
158
165
|
body: JSON.stringify({ email })
|
|
159
166
|
});
|
|
160
167
|
if (!res.ok) {
|
|
@@ -180,7 +187,10 @@ function initAuth(config) {
|
|
|
180
187
|
if (token) {
|
|
181
188
|
await fetch(`${headlessBase}/sign-out`, {
|
|
182
189
|
method: "POST",
|
|
183
|
-
headers: {
|
|
190
|
+
headers: {
|
|
191
|
+
"content-type": "application/json",
|
|
192
|
+
"x-smarthive-publishable-key": config.publishableKey
|
|
193
|
+
},
|
|
184
194
|
body: JSON.stringify({ refresh_token: token })
|
|
185
195
|
}).catch(() => {
|
|
186
196
|
});
|
|
@@ -268,7 +278,7 @@ function initAuth(config) {
|
|
|
268
278
|
url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);
|
|
269
279
|
url.searchParams.set("redirect_uri", redirectUri);
|
|
270
280
|
} else {
|
|
271
|
-
url = new URL(`${authBase}
|
|
281
|
+
url = new URL(`${authBase}/api/auth/social/${provider}`);
|
|
272
282
|
url.searchParams.set("project_id", config.projectId);
|
|
273
283
|
url.searchParams.set("redirect_uri", redirectUri);
|
|
274
284
|
}
|
|
@@ -302,7 +312,14 @@ function initAuth(config) {
|
|
|
302
312
|
const session = await readSession();
|
|
303
313
|
if (!session) return null;
|
|
304
314
|
if (session.expiresAt && Date.now() > session.expiresAt - 3e4) {
|
|
305
|
-
|
|
315
|
+
try {
|
|
316
|
+
return (await client.refreshSession())?.accessToken ?? null;
|
|
317
|
+
} catch (err) {
|
|
318
|
+
if (err instanceof SmartHiveAuthError && err.code === "network_error") {
|
|
319
|
+
return session.accessToken;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
306
323
|
}
|
|
307
324
|
return session.accessToken;
|
|
308
325
|
},
|
|
@@ -323,15 +340,20 @@ function initAuth(config) {
|
|
|
323
340
|
async refreshSession() {
|
|
324
341
|
const session = await readSession();
|
|
325
342
|
if (!session?.refreshToken) return session;
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
343
|
+
let response;
|
|
344
|
+
try {
|
|
345
|
+
response = await fetch(`${authBase}/api/auth/oauth2/token`, {
|
|
346
|
+
method: "POST",
|
|
347
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
348
|
+
body: new URLSearchParams({
|
|
349
|
+
grant_type: "refresh_token",
|
|
350
|
+
refresh_token: session.refreshToken,
|
|
351
|
+
client_id: config.publishableKey
|
|
352
|
+
})
|
|
353
|
+
});
|
|
354
|
+
} catch {
|
|
355
|
+
throw new SmartHiveAuthError("network_error", "Unable to reach the auth service. Check your connection.");
|
|
356
|
+
}
|
|
335
357
|
if (!response.ok) {
|
|
336
358
|
const err = await response.json().catch(() => ({}));
|
|
337
359
|
if (response.status < 500) await saveSession(null);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n\n /**\n * Re-send the email verification link to the given address.\n * Use this when the user did not receive the initial verification email.\n */\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n let res: Response;\n try {\n res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string; issues?: unknown[] };\n const detail = err.issues?.length ? ` (${(err.issues as Array<{ message?: string }>).map((i) => i.message).filter(Boolean).join(\"; \")})` : \"\";\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n (err.message ?? `Request to ${path} failed.`) + detail\n );\n }\n\n const data = await res.json().catch(() => {\n throw new SmartHiveAuthError(\"invalid_response\", \"The auth service returned an unexpected response.\");\n }) as RawHeadlessResponse;\n return data;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n\n async resendVerificationEmail({ email }) {\n const res = await fetch(`${authBase}/${environment}/api/auth/send-verification-email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email }),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { message?: string };\n throw new SmartHiveAuthError(\"resend_failed\", err.message ?? \"Failed to resend verification email.\");\n }\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"project_not_found\",\n err.message ?? \"Smart Hive Auth project configuration was not found.\"\n );\n }\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken,\n client_id: config.publishableKey,\n })\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string; message?: string };\n // Only clear the local session on auth failures (4xx) — keep it on server errors (5xx)\n if (response.status < 500) await saveSession(null);\n throw new SmartHiveAuthError(\n err.error ?? \"session_expired\",\n err.error_description ?? err.message ?? \"Session expired. Please sign in again.\"\n );\n }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n if (response.status === 401) return null;\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"userinfo_failed\", err.message ?? \"Failed to fetch user profile.\");\n }\n return response.json();\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n\n /**\n * Re-send the email verification link to the given address.\n * Use this when the user did not receive the initial verification email.\n */\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_* or pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): \"dev\" | \"prod\" {\n return publishableKey.startsWith(\"pk_dev_\") ? \"dev\" : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const headlessBase = `${baseUrl}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n let res: Response;\n try {\n res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify(body),\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string; issues?: unknown[] };\n const detail = err.issues?.length ? ` (${(err.issues as Array<{ message?: string }>).map((i) => i.message).filter(Boolean).join(\"; \")})` : \"\";\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n (err.message ?? `Request to ${path} failed.`) + detail\n );\n }\n\n const data = await res.json().catch(() => {\n throw new SmartHiveAuthError(\"invalid_response\", \"The auth service returned an unexpected response.\");\n }) as RawHeadlessResponse;\n return data;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n\n async resendVerificationEmail({ email }) {\n const res = await fetch(`${authBase}/api/auth/send-verification-email`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ email }),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { message?: string };\n throw new SmartHiveAuthError(\"resend_failed\", err.message ?? \"Failed to resend verification email.\");\n }\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smarthive-publishable-key\": config.publishableKey,\n },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"project_not_found\",\n err.message ?? \"Smart Hive Auth project configuration was not found.\"\n );\n }\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n try {\n return (await client.refreshSession())?.accessToken ?? null;\n } catch (err) {\n // Network unreachable — return the stale token so callers don't crash.\n // The server will 401 if truly expired; on-401 retry will refresh when\n // the network comes back.\n if (err instanceof SmartHiveAuthError && err.code === \"network_error\") {\n return session.accessToken;\n }\n return null;\n }\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n let response: Response;\n try {\n response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken,\n client_id: config.publishableKey,\n })\n });\n } catch {\n throw new SmartHiveAuthError(\"network_error\", \"Unable to reach the auth service. Check your connection.\");\n }\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string; message?: string };\n // Only clear the local session on auth failures (4xx) — keep it on server errors (5xx)\n if (response.status < 500) await saveSession(null);\n throw new SmartHiveAuthError(\n err.error ?? \"session_expired\",\n err.error_description ?? err.message ?? \"Session expired. Please sign in again.\"\n );\n }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n if (response.status === 401) return null;\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"userinfo_failed\", err.message ?? \"Failed to fetch user profile.\");\n }\n return response.json();\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED