@insforge/sdk 1.4.3 → 1.4.5-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,18 +33,19 @@ module.exports = __toCommonJS(middleware_exports);
33
33
  // src/lib/jwt.ts
34
34
  function decodeBase64Url(input) {
35
35
  const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
36
- const padded = normalized.padEnd(
37
- normalized.length + (4 - normalized.length % 4) % 4,
38
- "="
39
- );
36
+ const padded = normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "=");
40
37
  const binary = atob(padded);
41
38
  const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
42
39
  return new TextDecoder().decode(bytes);
43
40
  }
44
41
  function getJwtExpiration(token) {
45
- if (!token) return null;
42
+ if (!token) {
43
+ return null;
44
+ }
46
45
  const [, payload] = token.split(".");
47
- if (!payload) return null;
46
+ if (!payload) {
47
+ return null;
48
+ }
48
49
  try {
49
50
  const parsed = JSON.parse(decodeBase64Url(payload));
50
51
  if (typeof parsed.exp !== "number" || !Number.isFinite(parsed.exp)) {
@@ -56,9 +57,13 @@ function getJwtExpiration(token) {
56
57
  }
57
58
  }
58
59
  function isJwtExpiredOrExpiring(token, leewaySeconds = 60) {
59
- if (!token) return false;
60
+ if (!token) {
61
+ return false;
62
+ }
60
63
  const expires = getJwtExpiration(token);
61
- if (!expires) return true;
64
+ if (!expires) {
65
+ return true;
66
+ }
62
67
  return expires.getTime() <= Date.now() + leewaySeconds * 1e3;
63
68
  }
64
69
 
@@ -73,18 +78,28 @@ function getRefreshTokenCookieName(names) {
73
78
  return names?.refreshToken ?? DEFAULT_REFRESH_TOKEN_COOKIE;
74
79
  }
75
80
  function getCookieValue(cookies, name) {
76
- if (!cookies) return null;
81
+ if (!cookies) {
82
+ return null;
83
+ }
77
84
  const value = cookies.get(name);
78
- if (typeof value === "string") return value || null;
79
- if (value && typeof value.value === "string") return value.value || null;
85
+ if (typeof value === "string") {
86
+ return value || null;
87
+ }
88
+ if (value && typeof value.value === "string") {
89
+ return value.value || null;
90
+ }
80
91
  return null;
81
92
  }
82
93
  function getCookieValueFromHeader(cookieHeader, name) {
83
- if (!cookieHeader) return null;
94
+ if (!cookieHeader) {
95
+ return null;
96
+ }
84
97
  const parts = cookieHeader.split(";");
85
98
  for (const part of parts) {
86
99
  const [rawName, ...rawValue] = part.trim().split("=");
87
- if (rawName !== name) continue;
100
+ if (rawName !== name) {
101
+ continue;
102
+ }
88
103
  try {
89
104
  return decodeURIComponent(rawValue.join("="));
90
105
  } catch {
@@ -127,11 +142,15 @@ function expiredCookieOptions(overrides) {
127
142
  };
128
143
  }
129
144
  function setCookie(cookies, name, value, options) {
130
- if (!cookies?.set) return;
145
+ if (!cookies?.set) {
146
+ return;
147
+ }
131
148
  cookies.set(name, value, options);
132
149
  }
133
150
  function deleteCookie(cookies, name, options) {
134
- if (!cookies) return;
151
+ if (!cookies) {
152
+ return;
153
+ }
135
154
  if (cookies.set) {
136
155
  cookies.set(name, "", expiredCookieOptions(options));
137
156
  return;
@@ -140,12 +159,24 @@ function deleteCookie(cookies, name, options) {
140
159
  }
141
160
  function serializeCookie(name, value, options = {}) {
142
161
  const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
143
- if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
144
- if (options.domain) parts.push(`Domain=${options.domain}`);
145
- if (options.path) parts.push(`Path=${options.path}`);
146
- if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
147
- if (options.httpOnly) parts.push("HttpOnly");
148
- if (options.secure) parts.push("Secure");
162
+ if (options.maxAge !== void 0) {
163
+ parts.push(`Max-Age=${options.maxAge}`);
164
+ }
165
+ if (options.domain) {
166
+ parts.push(`Domain=${options.domain}`);
167
+ }
168
+ if (options.path) {
169
+ parts.push(`Path=${options.path}`);
170
+ }
171
+ if (options.expires) {
172
+ parts.push(`Expires=${options.expires.toUTCString()}`);
173
+ }
174
+ if (options.httpOnly) {
175
+ parts.push("HttpOnly");
176
+ }
177
+ if (options.secure) {
178
+ parts.push("Secure");
179
+ }
149
180
  if (options.sameSite) {
150
181
  const sameSite = options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1);
151
182
  parts.push(`SameSite=${sameSite}`);
@@ -158,20 +189,14 @@ function appendSetCookie(headers, name, value, options) {
158
189
  function setAuthCookies(cookies, tokens, settings = {}) {
159
190
  const accessName = getAccessTokenCookieName(settings.names);
160
191
  const refreshName = getRefreshTokenCookieName(settings.names);
161
- const accessOptions = accessTokenCookieOptions(
162
- tokens.accessToken,
163
- settings.options?.accessToken
164
- );
192
+ const accessOptions = accessTokenCookieOptions(tokens.accessToken, settings.options?.accessToken);
165
193
  setCookie(cookies, accessName, tokens.accessToken, accessOptions);
166
194
  if (tokens.refreshToken) {
167
195
  setCookie(
168
196
  cookies,
169
197
  refreshName,
170
198
  tokens.refreshToken,
171
- refreshTokenCookieOptions(
172
- tokens.refreshToken,
173
- settings.options?.refreshToken
174
- )
199
+ refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)
175
200
  );
176
201
  }
177
202
  }
@@ -197,10 +222,7 @@ function setAuthCookieHeaders(headers, tokens, settings = {}) {
197
222
  headers,
198
223
  refreshName,
199
224
  tokens.refreshToken,
200
- refreshTokenCookieOptions(
201
- tokens.refreshToken,
202
- settings.options?.refreshToken
203
- )
225
+ refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)
204
226
  );
205
227
  }
206
228
  }
@@ -248,7 +270,9 @@ function jsonResponse(body, init = {}, headers = new Headers(init.headers)) {
248
270
  });
249
271
  }
250
272
  function normalizeError(error) {
251
- if (error instanceof InsForgeError) return error;
273
+ if (error instanceof InsForgeError) {
274
+ return error;
275
+ }
252
276
  if (error && typeof error === "object") {
253
277
  const body = error;
254
278
  return new InsForgeError(
@@ -265,18 +289,21 @@ function normalizeError(error) {
265
289
  }
266
290
  async function readJson(response) {
267
291
  const contentType = response.headers.get("content-type");
268
- if (!contentType?.includes("json")) return null;
292
+ if (!contentType?.includes("json")) {
293
+ return null;
294
+ }
269
295
  return response.json();
270
296
  }
271
297
  function readRefreshToken(options) {
272
- if (options.refreshToken) return options.refreshToken;
298
+ if (options.refreshToken) {
299
+ return options.refreshToken;
300
+ }
273
301
  const refreshCookieName = getRefreshTokenCookieName(options.names);
274
302
  const cookieValue = getCookieValue(options.cookies, refreshCookieName);
275
- if (cookieValue) return cookieValue;
276
- return getCookieValueFromHeader(
277
- options.request?.headers.get("cookie"),
278
- refreshCookieName
279
- );
303
+ if (cookieValue) {
304
+ return cookieValue;
305
+ }
306
+ return getCookieValueFromHeader(options.request?.headers.get("cookie"), refreshCookieName);
280
307
  }
281
308
  async function refreshAuth(options = {}) {
282
309
  const headers = new Headers();
@@ -317,9 +344,7 @@ async function refreshAuth(options = {}) {
317
344
  }
318
345
  const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
319
346
  if (!fetchImpl) {
320
- throw new Error(
321
- "Fetch is not available. Please provide a fetch implementation."
322
- );
347
+ throw new Error("Fetch is not available. Please provide a fetch implementation.");
323
348
  }
324
349
  const requestHeaders = new Headers(options.headers);
325
350
  requestHeaders.set("Authorization", `Bearer ${anonKey}`);
@@ -397,10 +422,7 @@ async function refreshAuth(options = {}) {
397
422
  async function updateSession(options) {
398
423
  const accessCookieName = getAccessTokenCookieName(options.names);
399
424
  const refreshCookieName = getRefreshTokenCookieName(options.names);
400
- const accessToken = getCookieValue(
401
- options.requestCookies,
402
- accessCookieName
403
- );
425
+ const accessToken = getCookieValue(options.requestCookies, accessCookieName);
404
426
  if (accessToken && !isJwtExpiredOrExpiring(accessToken, options.refreshLeewaySeconds)) {
405
427
  return {
406
428
  refreshed: false,
@@ -408,10 +430,7 @@ async function updateSession(options) {
408
430
  error: null
409
431
  };
410
432
  }
411
- const refreshToken = getCookieValue(
412
- options.requestCookies,
413
- refreshCookieName
414
- );
433
+ const refreshToken = getCookieValue(options.requestCookies, refreshCookieName);
415
434
  if (!refreshToken) {
416
435
  if (accessToken) {
417
436
  clearAuthCookies(options.requestCookies, options);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ssr/middleware.ts","../../src/lib/jwt.ts","../../src/ssr/cookies.ts","../../src/types.ts","../../src/ssr/refresh.ts","../../src/ssr/update-session.ts"],"sourcesContent":["export {\n updateSession,\n type UpdateSessionOptions,\n type UpdateSessionResult,\n} from './update-session';\nexport {\n DEFAULT_ACCESS_TOKEN_COOKIE,\n DEFAULT_REFRESH_TOKEN_COOKIE,\n clearAuthCookies,\n getAccessTokenCookieName,\n getRefreshTokenCookieName,\n setAuthCookies,\n type AuthCookieNames,\n type AuthCookieOptions,\n type AuthCookieSettings,\n type CookieOptions,\n type CookieReader,\n type CookieStore,\n type CookieWriter,\n} from './cookies';\n","function decodeBase64Url(input: string): string {\n const normalized = input.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n '=',\n );\n\n const binary = atob(padded);\n const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));\n return new TextDecoder().decode(bytes);\n}\n\nexport function getJwtExpiration(token: string | null | undefined): Date | null {\n if (!token) return null;\n\n const [, payload] = token.split('.');\n if (!payload) return null;\n\n try {\n const parsed = JSON.parse(decodeBase64Url(payload)) as { exp?: unknown };\n if (typeof parsed.exp !== 'number' || !Number.isFinite(parsed.exp)) {\n return null;\n }\n return new Date(parsed.exp * 1000);\n } catch {\n return null;\n }\n}\n\nexport function isJwtExpiredOrExpiring(\n token: string | null | undefined,\n leewaySeconds = 60,\n): boolean {\n if (!token) return false;\n const expires = getJwtExpiration(token);\n if (!expires) return true;\n\n return expires.getTime() <= Date.now() + leewaySeconds * 1000;\n}\n","import { getJwtExpiration } from '../lib/jwt';\n\nexport const DEFAULT_ACCESS_TOKEN_COOKIE = 'insforge_access_token';\nexport const DEFAULT_REFRESH_TOKEN_COOKIE = 'insforge_refresh_token';\n\nexport interface AuthCookieNames {\n accessToken?: string;\n refreshToken?: string;\n}\n\nexport interface CookieOptions {\n domain?: string;\n path?: string;\n expires?: Date;\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n}\n\nexport interface AuthCookieOptions {\n accessToken?: CookieOptions;\n refreshToken?: CookieOptions;\n}\n\nexport type CookieStoreValue =\n | string\n | { value?: string | null }\n | undefined\n | null;\n\nexport interface CookieReader {\n get(name: string): CookieStoreValue;\n}\n\nexport interface CookieWriter {\n set?(name: string, value: string, options?: CookieOptions): unknown;\n set?(options: { name: string; value: string } & CookieOptions): unknown;\n delete?(name: string): unknown;\n delete?(options: { name: string } & CookieOptions): unknown;\n}\n\nexport interface CookieStore extends CookieReader, CookieWriter {}\n\nexport interface AuthCookieSettings {\n names?: AuthCookieNames;\n options?: AuthCookieOptions;\n}\n\nconst EXPIRED_DATE = new Date(0);\n\nexport function getAccessTokenCookieName(names?: AuthCookieNames): string {\n return names?.accessToken ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n}\n\nexport function getRefreshTokenCookieName(names?: AuthCookieNames): string {\n return names?.refreshToken ?? DEFAULT_REFRESH_TOKEN_COOKIE;\n}\n\nexport function getCookieValue(\n cookies: CookieReader | undefined,\n name: string,\n): string | null {\n if (!cookies) return null;\n\n const value = cookies.get(name);\n if (typeof value === 'string') return value || null;\n if (value && typeof value.value === 'string') return value.value || null;\n return null;\n}\n\nexport function getCookieValueFromHeader(\n cookieHeader: string | null | undefined,\n name: string,\n): string | null {\n if (!cookieHeader) return null;\n\n const parts = cookieHeader.split(';');\n for (const part of parts) {\n const [rawName, ...rawValue] = part.trim().split('=');\n if (rawName !== name) continue;\n try {\n return decodeURIComponent(rawValue.join('='));\n } catch {\n return rawValue.join('=');\n }\n }\n return null;\n}\n\nexport function getBrowserCookie(name: string): string | null {\n if (typeof document === 'undefined') return null;\n return getCookieValueFromHeader(document.cookie, name);\n}\n\nfunction defaultCookieOptions(): CookieOptions {\n const secure =\n typeof process !== 'undefined'\n ? process.env.NODE_ENV === 'production'\n : typeof location !== 'undefined' && location.protocol === 'https:';\n\n return {\n path: '/',\n sameSite: 'lax',\n secure,\n };\n}\n\nexport function accessTokenCookieOptions(\n token: string,\n overrides?: CookieOptions,\n): CookieOptions {\n return {\n ...defaultCookieOptions(),\n httpOnly: false,\n expires: getJwtExpiration(token) ?? undefined,\n ...overrides,\n };\n}\n\nexport function refreshTokenCookieOptions(\n token: string,\n overrides?: CookieOptions,\n): CookieOptions {\n return {\n ...defaultCookieOptions(),\n httpOnly: true,\n expires: getJwtExpiration(token) ?? undefined,\n ...overrides,\n };\n}\n\nexport function expiredCookieOptions(overrides?: CookieOptions): CookieOptions {\n const { expires: _expires, maxAge: _maxAge, ...safeOverrides } = overrides ?? {};\n return {\n ...defaultCookieOptions(),\n ...safeOverrides,\n expires: EXPIRED_DATE,\n maxAge: 0,\n };\n}\n\nexport function setCookie(\n cookies: CookieWriter | undefined,\n name: string,\n value: string,\n options?: CookieOptions,\n): void {\n if (!cookies?.set) return;\n cookies.set(name, value, options);\n}\n\nexport function deleteCookie(\n cookies: CookieWriter | undefined,\n name: string,\n options?: CookieOptions,\n): void {\n if (!cookies) return;\n if (cookies.set) {\n cookies.set(name, '', expiredCookieOptions(options));\n return;\n }\n cookies.delete?.(name);\n}\n\nexport function serializeCookie(\n name: string,\n value: string,\n options: CookieOptions = {},\n): string {\n const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];\n\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options.domain) parts.push(`Domain=${options.domain}`);\n if (options.path) parts.push(`Path=${options.path}`);\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n if (options.httpOnly) parts.push('HttpOnly');\n if (options.secure) parts.push('Secure');\n if (options.sameSite) {\n const sameSite =\n options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1);\n parts.push(`SameSite=${sameSite}`);\n }\n\n return parts.join('; ');\n}\n\nexport function appendSetCookie(\n headers: Headers,\n name: string,\n value: string,\n options?: CookieOptions,\n): void {\n headers.append('Set-Cookie', serializeCookie(name, value, options));\n}\n\nexport function setAuthCookies(\n cookies: CookieWriter | undefined,\n tokens: {\n accessToken: string;\n refreshToken?: string | null;\n },\n settings: AuthCookieSettings = {},\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n const accessOptions = accessTokenCookieOptions(\n tokens.accessToken,\n settings.options?.accessToken,\n );\n\n setCookie(cookies, accessName, tokens.accessToken, accessOptions);\n if (tokens.refreshToken) {\n setCookie(\n cookies,\n refreshName,\n tokens.refreshToken,\n refreshTokenCookieOptions(\n tokens.refreshToken,\n settings.options?.refreshToken,\n ),\n );\n }\n}\n\nexport function clearAuthCookies(\n cookies: CookieWriter | undefined,\n settings: AuthCookieSettings = {},\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n const accessOptions = expiredCookieOptions(settings.options?.accessToken);\n const refreshOptions = expiredCookieOptions(settings.options?.refreshToken);\n\n deleteCookie(cookies, accessName, accessOptions);\n deleteCookie(cookies, refreshName, refreshOptions);\n}\n\nexport function setAuthCookieHeaders(\n headers: Headers,\n tokens: {\n accessToken: string;\n refreshToken?: string | null;\n },\n settings: AuthCookieSettings = {},\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n\n appendSetCookie(\n headers,\n accessName,\n tokens.accessToken,\n accessTokenCookieOptions(tokens.accessToken, settings.options?.accessToken),\n );\n if (tokens.refreshToken) {\n appendSetCookie(\n headers,\n refreshName,\n tokens.refreshToken,\n refreshTokenCookieOptions(\n tokens.refreshToken,\n settings.options?.refreshToken,\n ),\n );\n }\n}\n\nexport function clearAuthCookieHeaders(\n headers: Headers,\n settings: AuthCookieSettings = {},\n): void {\n appendSetCookie(\n headers,\n getAccessTokenCookieName(settings.names),\n '',\n expiredCookieOptions(settings.options?.accessToken),\n );\n appendSetCookie(\n headers,\n getRefreshTokenCookieName(settings.names),\n '',\n expiredCookieOptions(settings.options?.refreshToken),\n );\n}\n","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { ErrorCode, UserSchema } from '@insforge/shared-schemas';\n\nexport type InsForgeErrorCode = ErrorCode | (string & {});\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Static access token (optional)\n * Seeds the client with a fixed bearer token used for all authenticated\n * requests — e.g. a user JWT inside an edge function, or a server-signed\n * JWT from an external auth provider. Disables automatic token refresh\n * and implies server mode unless `isServerMode` is set explicitly.\n */\n accessToken?: string;\n\n /**\n * @deprecated Use `accessToken` instead. Same behavior; `accessToken`\n * takes precedence when both are provided.\n */\n edgeFunctionToken?: string;\n\n /**\n * Direct URL to Deno Subhosting functions (optional)\n * When provided, SDK will try this URL first for function invocations.\n * Falls back to proxy URL if subhosting returns 404.\n * @example \"https://{appKey}.functions.insforge.app\"\n */\n functionsUrl?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Enable server-side auth mode (SSR/Node runtime)\n * In this mode auth endpoints use `client_type=mobile` and refresh_token body flow.\n *\n * @deprecated Use `createServerClient()`, `createBrowserClient()`, and\n * `updateSession()` from `@insforge/sdk/ssr` for SSR apps.\n * @default false\n */\n isServerMode?: boolean;\n\n /**\n * Advanced auth module options.\n */\n auth?: {\n /**\n * Detect and exchange OAuth callback parameters on browser client\n * initialization. SSR browser clients disable this so auth mutations can\n * stay server-owned.\n * @default true\n */\n detectOAuthCallback?: boolean;\n };\n\n /**\n * Database module options.\n */\n db?: {\n /**\n * Default Postgres schema for database queries. Maps to PostgREST's\n * `Accept-Profile`/`Content-Profile` headers. Override per-query with\n * `client.database.schema('other')`.\n * @default \"public\"\n */\n schema?: string;\n };\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n\n /**\n * Enable debug logging for HTTP requests and responses.\n * When true, request/response details are logged to the console.\n * Can also be a custom log function for advanced use cases.\n * @default false\n */\n debug?: boolean | ((message: string, ...args: any[]) => void);\n\n /**\n * Request timeout in milliseconds.\n * Requests that exceed this duration will be aborted.\n * Set to 0 to disable timeout.\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Maximum number of retry attempts for failed requests.\n * Retries are triggered on network errors and server errors (5xx).\n * Client errors (4xx) are never retried.\n * Set to 0 to disable retries.\n * @default 3\n */\n retryCount?: number;\n\n /**\n * Initial delay in milliseconds before the first retry.\n * The delay doubles with each subsequent attempt (exponential backoff)\n * with ±15% jitter to prevent thundering herd.\n * @default 500\n */\n retryDelay?: number;\n}\n\nexport type InsForgeAdminConfig = Omit<\n InsForgeConfig,\n 'anonKey' | 'accessToken' | 'edgeFunctionToken' | 'isServerMode'\n> & {\n /**\n * Project admin API key. Keep this server-side only.\n */\n apiKey: string;\n};\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface AuthRefreshResponse {\n user: UserSchema;\n accessToken: string;\n csrfToken?: string;\n refreshToken?: string;\n}\n\nexport interface ApiError {\n error: InsForgeErrorCode;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: InsForgeErrorCode;\n public nextActions?: string;\n\n constructor(\n message: string,\n statusCode: number,\n error: InsForgeErrorCode,\n nextActions?: string,\n ) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions,\n );\n }\n}\n","import {\n InsForgeError,\n type AuthRefreshResponse,\n type InsForgeConfig,\n} from '../types';\nimport { ERROR_CODES } from '@insforge/shared-schemas';\nimport {\n clearAuthCookieHeaders,\n getCookieValue,\n getCookieValueFromHeader,\n getRefreshTokenCookieName,\n setAuthCookieHeaders,\n type AuthCookieSettings,\n type CookieStore,\n} from './cookies';\n\nexport interface RefreshAuthOptions\n extends Omit<\n InsForgeConfig,\n 'accessToken' | 'edgeFunctionToken' | 'isServerMode' | 'auth'\n >,\n AuthCookieSettings {\n request?: Request;\n cookies?: Pick<CookieStore, 'get'>;\n refreshToken?: string;\n}\n\nexport interface RefreshAuthResult {\n response: Response;\n data: AuthRefreshResponse | null;\n accessToken: string | null;\n refreshToken: string | null;\n error: InsForgeError | null;\n}\n\nexport type RefreshAuthRouteHandler = (request: Request) => Promise<Response>;\n\nfunction jsonResponse(\n body: unknown,\n init: ResponseInit = {},\n headers = new Headers(init.headers),\n): Response {\n headers.set('Content-Type', 'application/json');\n return new Response(JSON.stringify(body), {\n ...init,\n headers,\n });\n}\n\nfunction normalizeError(error: unknown): InsForgeError {\n if (error instanceof InsForgeError) return error;\n\n if (error && typeof error === 'object') {\n const body = error as {\n error?: unknown;\n message?: unknown;\n statusCode?: unknown;\n };\n return new InsForgeError(\n typeof body.message === 'string'\n ? body.message\n : 'Failed to refresh auth session',\n typeof body.statusCode === 'number' ? body.statusCode : 500,\n typeof body.error === 'string'\n ? body.error\n : ERROR_CODES.UNKNOWN_ERROR,\n );\n }\n\n return new InsForgeError(\n error instanceof Error ? error.message : 'Failed to refresh auth session',\n 500,\n ERROR_CODES.UNKNOWN_ERROR,\n );\n}\n\nasync function readJson(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type');\n if (!contentType?.includes('json')) return null;\n return response.json();\n}\n\nfunction readRefreshToken(options: RefreshAuthOptions): string | null {\n if (options.refreshToken) return options.refreshToken;\n\n const refreshCookieName = getRefreshTokenCookieName(options.names);\n const cookieValue = getCookieValue(options.cookies, refreshCookieName);\n if (cookieValue) return cookieValue;\n\n return getCookieValueFromHeader(\n options.request?.headers.get('cookie'),\n refreshCookieName,\n );\n}\n\nexport async function refreshAuth(\n options: RefreshAuthOptions = {},\n): Promise<RefreshAuthResult> {\n const headers = new Headers();\n const refreshToken = readRefreshToken(options);\n\n if (!refreshToken) {\n clearAuthCookieHeaders(headers, options);\n const error = new InsForgeError(\n 'Refresh token cookie is missing',\n 401,\n ERROR_CODES.AUTH_UNAUTHORIZED,\n );\n return {\n response: jsonResponse(\n {\n error: error.error,\n message: error.message,\n statusCode: error.statusCode,\n },\n { status: error.statusCode },\n headers,\n ),\n data: null,\n accessToken: null,\n refreshToken: null,\n error,\n };\n }\n\n let { baseUrl, anonKey } = options;\n try {\n baseUrl ||= process.env.NEXT_PUBLIC_INSFORGE_URL;\n anonKey ||= process.env.NEXT_PUBLIC_INSFORGE_ANON_KEY;\n } catch {\n // process may be unavailable outside Next.js/browser-bundled envs.\n }\n if (!baseUrl || !anonKey) {\n throw new Error(\n 'Missing InsForge baseUrl or anonKey. Pass baseUrl and anonKey to refreshAuth() or set NEXT_PUBLIC_INSFORGE_URL and NEXT_PUBLIC_INSFORGE_ANON_KEY.',\n );\n }\n\n const fetchImpl =\n options.fetch ??\n (globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : (undefined as typeof fetch | undefined));\n if (!fetchImpl) {\n throw new Error(\n 'Fetch is not available. Please provide a fetch implementation.',\n );\n }\n\n const requestHeaders = new Headers(options.headers);\n requestHeaders.set('Authorization', `Bearer ${anonKey}`);\n requestHeaders.set('Content-Type', 'application/json');\n requestHeaders.set('Accept', 'application/json');\n\n let data: AuthRefreshResponse | null = null;\n let error: InsForgeError | null = null;\n\n try {\n const response = await fetchImpl(\n new URL('/api/auth/refresh?client_type=mobile', baseUrl).toString(),\n {\n method: 'POST',\n headers: requestHeaders,\n body: JSON.stringify({ refresh_token: refreshToken }),\n },\n );\n const body = await readJson(response);\n if (!response.ok) {\n error = normalizeError(\n body ?? {\n message: 'Failed to refresh auth session',\n statusCode: response.status,\n error: ERROR_CODES.UNKNOWN_ERROR,\n },\n );\n } else {\n data = body as AuthRefreshResponse;\n }\n } catch (caught) {\n error = normalizeError(caught);\n }\n\n if (error || !data?.accessToken) {\n clearAuthCookieHeaders(headers, options);\n const normalized = normalizeError(error);\n return {\n response: jsonResponse(\n {\n error: normalized.error,\n message: normalized.message,\n statusCode: normalized.statusCode,\n },\n { status: normalized.statusCode || 500 },\n headers,\n ),\n data: null,\n accessToken: null,\n refreshToken: null,\n error: normalized,\n };\n }\n\n const nextRefreshToken = data.refreshToken ?? refreshToken;\n setAuthCookieHeaders(\n headers,\n {\n accessToken: data.accessToken,\n refreshToken: nextRefreshToken,\n },\n options,\n );\n\n const responseBody: AuthRefreshResponse = {\n accessToken: data.accessToken,\n user: data.user,\n csrfToken: data.csrfToken,\n };\n\n return {\n response: jsonResponse(responseBody, { status: 200 }, headers),\n data: responseBody,\n accessToken: data.accessToken,\n refreshToken: nextRefreshToken,\n error: null,\n };\n}\n\nexport function createRefreshAuthRouter(\n options: Omit<RefreshAuthOptions, 'request'> = {},\n): { POST: RefreshAuthRouteHandler } {\n return {\n POST: async (request: Request) =>\n (await refreshAuth({ ...options, request })).response,\n };\n}\n","import { isJwtExpiredOrExpiring } from '../lib/jwt';\nimport type { InsForgeConfig, InsForgeError } from '../types';\nimport {\n clearAuthCookies,\n getAccessTokenCookieName,\n getCookieValue,\n getRefreshTokenCookieName,\n setAuthCookies,\n type AuthCookieSettings,\n type CookieStore,\n} from './cookies';\nimport { refreshAuth } from './refresh';\n\nexport interface UpdateSessionOptions\n extends Omit<\n InsForgeConfig,\n 'accessToken' | 'edgeFunctionToken' | 'isServerMode' | 'auth'\n >,\n AuthCookieSettings {\n requestCookies: CookieStore;\n responseCookies: CookieStore;\n refreshLeewaySeconds?: number;\n}\n\nexport interface UpdateSessionResult {\n refreshed: boolean;\n accessToken: string | null;\n error: InsForgeError | null;\n}\n\nexport async function updateSession(\n options: UpdateSessionOptions,\n): Promise<UpdateSessionResult> {\n const accessCookieName = getAccessTokenCookieName(options.names);\n const refreshCookieName = getRefreshTokenCookieName(options.names);\n const accessToken = getCookieValue(\n options.requestCookies,\n accessCookieName,\n );\n\n if (\n accessToken &&\n !isJwtExpiredOrExpiring(accessToken, options.refreshLeewaySeconds)\n ) {\n return {\n refreshed: false,\n accessToken,\n error: null,\n };\n }\n\n const refreshToken = getCookieValue(\n options.requestCookies,\n refreshCookieName,\n );\n if (!refreshToken) {\n if (accessToken) {\n clearAuthCookies(options.requestCookies, options);\n clearAuthCookies(options.responseCookies, options);\n }\n return {\n refreshed: false,\n accessToken: null,\n error: null,\n };\n }\n\n const result = await refreshAuth({\n ...options,\n refreshToken,\n });\n\n if (result.error || !result.accessToken) {\n clearAuthCookies(options.requestCookies, options);\n clearAuthCookies(options.responseCookies, options);\n return {\n refreshed: false,\n accessToken: null,\n error: result.error,\n };\n }\n\n const tokens = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken ?? refreshToken,\n };\n setAuthCookies(options.requestCookies, tokens, options);\n setAuthCookies(options.responseCookies, tokens, options);\n\n return {\n refreshed: true,\n accessToken: result.accessToken,\n error: null,\n };\n}\n"],"mappings":"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","names":["error"]}
1
+ {"version":3,"sources":["../../src/ssr/middleware.ts","../../src/lib/jwt.ts","../../src/ssr/cookies.ts","../../src/types.ts","../../src/ssr/refresh.ts","../../src/ssr/update-session.ts"],"sourcesContent":["export {\n updateSession,\n type UpdateSessionOptions,\n type UpdateSessionResult,\n} from './update-session';\nexport {\n DEFAULT_ACCESS_TOKEN_COOKIE,\n DEFAULT_REFRESH_TOKEN_COOKIE,\n clearAuthCookies,\n getAccessTokenCookieName,\n getRefreshTokenCookieName,\n setAuthCookies,\n type AuthCookieNames,\n type AuthCookieOptions,\n type AuthCookieSettings,\n type CookieOptions,\n type CookieReader,\n type CookieStore,\n type CookieWriter,\n} from './cookies';\n","function decodeBase64Url(input: string): string {\n const normalized = input.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(normalized.length + ((4 - (normalized.length % 4)) % 4), '=');\n\n const binary = atob(padded);\n const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));\n return new TextDecoder().decode(bytes);\n}\n\nexport function getJwtExpiration(token: string | null | undefined): Date | null {\n if (!token) {\n return null;\n }\n\n const [, payload] = token.split('.');\n if (!payload) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(decodeBase64Url(payload)) as { exp?: unknown };\n if (typeof parsed.exp !== 'number' || !Number.isFinite(parsed.exp)) {\n return null;\n }\n return new Date(parsed.exp * 1000);\n } catch {\n return null;\n }\n}\n\nexport function isJwtExpiredOrExpiring(\n token: string | null | undefined,\n leewaySeconds = 60\n): boolean {\n if (!token) {\n return false;\n }\n const expires = getJwtExpiration(token);\n if (!expires) {\n return true;\n }\n\n return expires.getTime() <= Date.now() + leewaySeconds * 1000;\n}\n","import { getJwtExpiration } from '../lib/jwt';\n\nexport const DEFAULT_ACCESS_TOKEN_COOKIE = 'insforge_access_token';\nexport const DEFAULT_REFRESH_TOKEN_COOKIE = 'insforge_refresh_token';\n\nexport interface AuthCookieNames {\n accessToken?: string;\n refreshToken?: string;\n}\n\nexport interface CookieOptions {\n domain?: string;\n path?: string;\n expires?: Date;\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n}\n\nexport interface AuthCookieOptions {\n accessToken?: CookieOptions;\n refreshToken?: CookieOptions;\n}\n\nexport type CookieStoreValue = string | { value?: string | null } | undefined | null;\n\nexport interface CookieReader {\n get(name: string): CookieStoreValue;\n}\n\nexport interface CookieWriter {\n set?(name: string, value: string, options?: CookieOptions): unknown;\n set?(options: { name: string; value: string } & CookieOptions): unknown;\n delete?(name: string): unknown;\n delete?(options: { name: string } & CookieOptions): unknown;\n}\n\nexport interface CookieStore extends CookieReader, CookieWriter {}\n\nexport interface AuthCookieSettings {\n names?: AuthCookieNames;\n options?: AuthCookieOptions;\n}\n\nconst EXPIRED_DATE = new Date(0);\n\nexport function getAccessTokenCookieName(names?: AuthCookieNames): string {\n return names?.accessToken ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n}\n\nexport function getRefreshTokenCookieName(names?: AuthCookieNames): string {\n return names?.refreshToken ?? DEFAULT_REFRESH_TOKEN_COOKIE;\n}\n\nexport function getCookieValue(cookies: CookieReader | undefined, name: string): string | null {\n if (!cookies) {\n return null;\n }\n\n const value = cookies.get(name);\n if (typeof value === 'string') {\n return value || null;\n }\n if (value && typeof value.value === 'string') {\n return value.value || null;\n }\n return null;\n}\n\nexport function getCookieValueFromHeader(\n cookieHeader: string | null | undefined,\n name: string\n): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n const parts = cookieHeader.split(';');\n for (const part of parts) {\n const [rawName, ...rawValue] = part.trim().split('=');\n if (rawName !== name) {\n continue;\n }\n try {\n return decodeURIComponent(rawValue.join('='));\n } catch {\n return rawValue.join('=');\n }\n }\n return null;\n}\n\nexport function getBrowserCookie(name: string): string | null {\n if (typeof document === 'undefined') {\n return null;\n }\n return getCookieValueFromHeader(document.cookie, name);\n}\n\nfunction defaultCookieOptions(): CookieOptions {\n const secure =\n typeof process !== 'undefined'\n ? process.env.NODE_ENV === 'production'\n : typeof location !== 'undefined' && location.protocol === 'https:';\n\n return {\n path: '/',\n sameSite: 'lax',\n secure,\n };\n}\n\nexport function accessTokenCookieOptions(token: string, overrides?: CookieOptions): CookieOptions {\n return {\n ...defaultCookieOptions(),\n httpOnly: false,\n expires: getJwtExpiration(token) ?? undefined,\n ...overrides,\n };\n}\n\nexport function refreshTokenCookieOptions(token: string, overrides?: CookieOptions): CookieOptions {\n return {\n ...defaultCookieOptions(),\n httpOnly: true,\n expires: getJwtExpiration(token) ?? undefined,\n ...overrides,\n };\n}\n\nexport function expiredCookieOptions(overrides?: CookieOptions): CookieOptions {\n const { expires: _expires, maxAge: _maxAge, ...safeOverrides } = overrides ?? {};\n return {\n ...defaultCookieOptions(),\n ...safeOverrides,\n expires: EXPIRED_DATE,\n maxAge: 0,\n };\n}\n\nexport function setCookie(\n cookies: CookieWriter | undefined,\n name: string,\n value: string,\n options?: CookieOptions\n): void {\n if (!cookies?.set) {\n return;\n }\n cookies.set(name, value, options);\n}\n\nexport function deleteCookie(\n cookies: CookieWriter | undefined,\n name: string,\n options?: CookieOptions\n): void {\n if (!cookies) {\n return;\n }\n if (cookies.set) {\n cookies.set(name, '', expiredCookieOptions(options));\n return;\n }\n cookies.delete?.(name);\n}\n\nexport function serializeCookie(name: string, value: string, options: CookieOptions = {}): string {\n const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];\n\n if (options.maxAge !== undefined) {\n parts.push(`Max-Age=${options.maxAge}`);\n }\n if (options.domain) {\n parts.push(`Domain=${options.domain}`);\n }\n if (options.path) {\n parts.push(`Path=${options.path}`);\n }\n if (options.expires) {\n parts.push(`Expires=${options.expires.toUTCString()}`);\n }\n if (options.httpOnly) {\n parts.push('HttpOnly');\n }\n if (options.secure) {\n parts.push('Secure');\n }\n if (options.sameSite) {\n const sameSite = options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1);\n parts.push(`SameSite=${sameSite}`);\n }\n\n return parts.join('; ');\n}\n\nexport function appendSetCookie(\n headers: Headers,\n name: string,\n value: string,\n options?: CookieOptions\n): void {\n headers.append('Set-Cookie', serializeCookie(name, value, options));\n}\n\nexport function setAuthCookies(\n cookies: CookieWriter | undefined,\n tokens: {\n accessToken: string;\n refreshToken?: string | null;\n },\n settings: AuthCookieSettings = {}\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n const accessOptions = accessTokenCookieOptions(tokens.accessToken, settings.options?.accessToken);\n\n setCookie(cookies, accessName, tokens.accessToken, accessOptions);\n if (tokens.refreshToken) {\n setCookie(\n cookies,\n refreshName,\n tokens.refreshToken,\n refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)\n );\n }\n}\n\nexport function clearAuthCookies(\n cookies: CookieWriter | undefined,\n settings: AuthCookieSettings = {}\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n const accessOptions = expiredCookieOptions(settings.options?.accessToken);\n const refreshOptions = expiredCookieOptions(settings.options?.refreshToken);\n\n deleteCookie(cookies, accessName, accessOptions);\n deleteCookie(cookies, refreshName, refreshOptions);\n}\n\nexport function setAuthCookieHeaders(\n headers: Headers,\n tokens: {\n accessToken: string;\n refreshToken?: string | null;\n },\n settings: AuthCookieSettings = {}\n): void {\n const accessName = getAccessTokenCookieName(settings.names);\n const refreshName = getRefreshTokenCookieName(settings.names);\n\n appendSetCookie(\n headers,\n accessName,\n tokens.accessToken,\n accessTokenCookieOptions(tokens.accessToken, settings.options?.accessToken)\n );\n if (tokens.refreshToken) {\n appendSetCookie(\n headers,\n refreshName,\n tokens.refreshToken,\n refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)\n );\n }\n}\n\nexport function clearAuthCookieHeaders(headers: Headers, settings: AuthCookieSettings = {}): void {\n appendSetCookie(\n headers,\n getAccessTokenCookieName(settings.names),\n '',\n expiredCookieOptions(settings.options?.accessToken)\n );\n appendSetCookie(\n headers,\n getRefreshTokenCookieName(settings.names),\n '',\n expiredCookieOptions(settings.options?.refreshToken)\n );\n}\n","/**\n * InsForge SDK Types - only SDK-specific types here\n * Use @insforge/shared-schemas directly for API types\n */\n\nimport type { ErrorCode, UserSchema } from '@insforge/shared-schemas';\n\nexport type InsForgeErrorCode = ErrorCode | (string & {});\n\nexport interface InsForgeConfig {\n /**\n * The base URL of the InsForge backend API\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous API key (optional)\n * Used for public/unauthenticated requests when no user token is set\n */\n anonKey?: string;\n\n /**\n * Static access token (optional)\n * Seeds the client with a fixed bearer token used for all authenticated\n * requests — e.g. a user JWT inside an edge function, or a server-signed\n * JWT from an external auth provider. Disables automatic token refresh\n * and implies server mode unless `isServerMode` is set explicitly.\n */\n accessToken?: string;\n\n /**\n * @deprecated Use `accessToken` instead. Same behavior; `accessToken`\n * takes precedence when both are provided.\n */\n edgeFunctionToken?: string;\n\n /**\n * Direct URL to Deno Subhosting functions (optional)\n * When provided, SDK will try this URL first for function invocations.\n * Falls back to proxy URL if subhosting returns 404.\n * @example \"https://{appKey}.functions.insforge.app\"\n */\n functionsUrl?: string;\n\n /**\n * Custom fetch implementation (useful for Node.js environments)\n */\n fetch?: typeof fetch;\n\n /**\n * Enable server-side auth mode (SSR/Node runtime)\n * In this mode auth endpoints use `client_type=mobile` and refresh_token body flow.\n *\n * @deprecated Use `createServerClient()`, `createBrowserClient()`, and\n * `updateSession()` from `@insforge/sdk/ssr` for SSR apps.\n * @default false\n */\n isServerMode?: boolean;\n\n /**\n * Advanced auth module options.\n */\n auth?: {\n /**\n * Detect and exchange OAuth callback parameters on browser client\n * initialization. SSR browser clients disable this so auth mutations can\n * stay server-owned.\n * @default true\n */\n detectOAuthCallback?: boolean;\n };\n\n /**\n * Database module options.\n */\n db?: {\n /**\n * Default Postgres schema for database queries. Maps to PostgREST's\n * `Accept-Profile`/`Content-Profile` headers. Override per-query with\n * `client.database.schema('other')`.\n * @default \"public\"\n */\n schema?: string;\n };\n\n /**\n * Custom headers to include with every request\n */\n headers?: Record<string, string>;\n\n /**\n * Enable debug logging for HTTP requests and responses.\n * When true, request/response details are logged to the console.\n * Can also be a custom log function for advanced use cases.\n * @default false\n */\n debug?: boolean | ((message: string, ...args: any[]) => void);\n\n /**\n * Request timeout in milliseconds.\n * Requests that exceed this duration will be aborted.\n * Set to 0 to disable timeout.\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Maximum number of retry attempts for failed requests.\n * Retries are triggered on network errors and server errors (5xx).\n * Client errors (4xx) are never retried.\n * Set to 0 to disable retries.\n * @default 3\n */\n retryCount?: number;\n\n /**\n * Initial delay in milliseconds before the first retry.\n * The delay doubles with each subsequent attempt (exponential backoff)\n * with ±15% jitter to prevent thundering herd.\n * @default 500\n */\n retryDelay?: number;\n}\n\nexport type InsForgeAdminConfig = Omit<\n InsForgeConfig,\n 'anonKey' | 'accessToken' | 'edgeFunctionToken' | 'isServerMode'\n> & {\n /**\n * Project admin API key. Keep this server-side only.\n */\n apiKey: string;\n};\n\nexport interface AuthSession {\n user: UserSchema;\n accessToken: string;\n expiresAt?: Date;\n}\n\nexport interface AuthRefreshResponse {\n user: UserSchema;\n accessToken: string;\n csrfToken?: string;\n refreshToken?: string;\n}\n\nexport interface ApiError {\n error: InsForgeErrorCode;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class InsForgeError extends Error {\n public statusCode: number;\n public error: InsForgeErrorCode;\n public nextActions?: string;\n\n constructor(message: string, statusCode: number, error: InsForgeErrorCode, nextActions?: string) {\n super(message);\n this.name = 'InsForgeError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): InsForgeError {\n return new InsForgeError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions\n );\n }\n}\n","import { InsForgeError, type AuthRefreshResponse, type InsForgeConfig } from '../types';\nimport { ERROR_CODES } from '@insforge/shared-schemas';\nimport {\n clearAuthCookieHeaders,\n getCookieValue,\n getCookieValueFromHeader,\n getRefreshTokenCookieName,\n setAuthCookieHeaders,\n type AuthCookieSettings,\n type CookieStore,\n} from './cookies';\n\nexport interface RefreshAuthOptions\n extends\n Omit<InsForgeConfig, 'accessToken' | 'edgeFunctionToken' | 'isServerMode' | 'auth'>,\n AuthCookieSettings {\n request?: Request;\n cookies?: Pick<CookieStore, 'get'>;\n refreshToken?: string;\n}\n\nexport interface RefreshAuthResult {\n response: Response;\n data: AuthRefreshResponse | null;\n accessToken: string | null;\n refreshToken: string | null;\n error: InsForgeError | null;\n}\n\nexport type RefreshAuthRouteHandler = (request: Request) => Promise<Response>;\n\nfunction jsonResponse(\n body: unknown,\n init: ResponseInit = {},\n headers = new Headers(init.headers)\n): Response {\n headers.set('Content-Type', 'application/json');\n return new Response(JSON.stringify(body), {\n ...init,\n headers,\n });\n}\n\nfunction normalizeError(error: unknown): InsForgeError {\n if (error instanceof InsForgeError) {\n return error;\n }\n\n if (error && typeof error === 'object') {\n const body = error as {\n error?: unknown;\n message?: unknown;\n statusCode?: unknown;\n };\n return new InsForgeError(\n typeof body.message === 'string' ? body.message : 'Failed to refresh auth session',\n typeof body.statusCode === 'number' ? body.statusCode : 500,\n typeof body.error === 'string' ? body.error : ERROR_CODES.UNKNOWN_ERROR\n );\n }\n\n return new InsForgeError(\n error instanceof Error ? error.message : 'Failed to refresh auth session',\n 500,\n ERROR_CODES.UNKNOWN_ERROR\n );\n}\n\nasync function readJson(response: Response): Promise<unknown> {\n const contentType = response.headers.get('content-type');\n if (!contentType?.includes('json')) {\n return null;\n }\n return response.json();\n}\n\nfunction readRefreshToken(options: RefreshAuthOptions): string | null {\n if (options.refreshToken) {\n return options.refreshToken;\n }\n\n const refreshCookieName = getRefreshTokenCookieName(options.names);\n const cookieValue = getCookieValue(options.cookies, refreshCookieName);\n if (cookieValue) {\n return cookieValue;\n }\n\n return getCookieValueFromHeader(options.request?.headers.get('cookie'), refreshCookieName);\n}\n\nexport async function refreshAuth(options: RefreshAuthOptions = {}): Promise<RefreshAuthResult> {\n const headers = new Headers();\n const refreshToken = readRefreshToken(options);\n\n if (!refreshToken) {\n clearAuthCookieHeaders(headers, options);\n const error = new InsForgeError(\n 'Refresh token cookie is missing',\n 401,\n ERROR_CODES.AUTH_UNAUTHORIZED\n );\n return {\n response: jsonResponse(\n {\n error: error.error,\n message: error.message,\n statusCode: error.statusCode,\n },\n { status: error.statusCode },\n headers\n ),\n data: null,\n accessToken: null,\n refreshToken: null,\n error,\n };\n }\n\n let { baseUrl, anonKey } = options;\n try {\n baseUrl ||= process.env.NEXT_PUBLIC_INSFORGE_URL;\n anonKey ||= process.env.NEXT_PUBLIC_INSFORGE_ANON_KEY;\n } catch {\n // process may be unavailable outside Next.js/browser-bundled envs.\n }\n if (!baseUrl || !anonKey) {\n throw new Error(\n 'Missing InsForge baseUrl or anonKey. Pass baseUrl and anonKey to refreshAuth() or set NEXT_PUBLIC_INSFORGE_URL and NEXT_PUBLIC_INSFORGE_ANON_KEY.'\n );\n }\n\n const fetchImpl =\n options.fetch ??\n (globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : (undefined as typeof fetch | undefined));\n if (!fetchImpl) {\n throw new Error('Fetch is not available. Please provide a fetch implementation.');\n }\n\n const requestHeaders = new Headers(options.headers);\n requestHeaders.set('Authorization', `Bearer ${anonKey}`);\n requestHeaders.set('Content-Type', 'application/json');\n requestHeaders.set('Accept', 'application/json');\n\n let data: AuthRefreshResponse | null = null;\n let error: InsForgeError | null = null;\n\n try {\n const response = await fetchImpl(\n new URL('/api/auth/refresh?client_type=mobile', baseUrl).toString(),\n {\n method: 'POST',\n headers: requestHeaders,\n body: JSON.stringify({ refresh_token: refreshToken }),\n }\n );\n const body = await readJson(response);\n if (!response.ok) {\n error = normalizeError(\n body ?? {\n message: 'Failed to refresh auth session',\n statusCode: response.status,\n error: ERROR_CODES.UNKNOWN_ERROR,\n }\n );\n } else {\n data = body as AuthRefreshResponse;\n }\n } catch (caught) {\n error = normalizeError(caught);\n }\n\n if (error || !data?.accessToken) {\n clearAuthCookieHeaders(headers, options);\n const normalized = normalizeError(error);\n return {\n response: jsonResponse(\n {\n error: normalized.error,\n message: normalized.message,\n statusCode: normalized.statusCode,\n },\n { status: normalized.statusCode || 500 },\n headers\n ),\n data: null,\n accessToken: null,\n refreshToken: null,\n error: normalized,\n };\n }\n\n const nextRefreshToken = data.refreshToken ?? refreshToken;\n setAuthCookieHeaders(\n headers,\n {\n accessToken: data.accessToken,\n refreshToken: nextRefreshToken,\n },\n options\n );\n\n const responseBody: AuthRefreshResponse = {\n accessToken: data.accessToken,\n user: data.user,\n csrfToken: data.csrfToken,\n };\n\n return {\n response: jsonResponse(responseBody, { status: 200 }, headers),\n data: responseBody,\n accessToken: data.accessToken,\n refreshToken: nextRefreshToken,\n error: null,\n };\n}\n\nexport function createRefreshAuthRouter(options: Omit<RefreshAuthOptions, 'request'> = {}): {\n POST: RefreshAuthRouteHandler;\n} {\n return {\n POST: async (request: Request) => (await refreshAuth({ ...options, request })).response,\n };\n}\n","import { isJwtExpiredOrExpiring } from '../lib/jwt';\nimport type { InsForgeConfig, InsForgeError } from '../types';\nimport {\n clearAuthCookies,\n getAccessTokenCookieName,\n getCookieValue,\n getRefreshTokenCookieName,\n setAuthCookies,\n type AuthCookieSettings,\n type CookieStore,\n} from './cookies';\nimport { refreshAuth } from './refresh';\n\nexport interface UpdateSessionOptions\n extends\n Omit<InsForgeConfig, 'accessToken' | 'edgeFunctionToken' | 'isServerMode' | 'auth'>,\n AuthCookieSettings {\n requestCookies: CookieStore;\n responseCookies: CookieStore;\n refreshLeewaySeconds?: number;\n}\n\nexport interface UpdateSessionResult {\n refreshed: boolean;\n accessToken: string | null;\n error: InsForgeError | null;\n}\n\nexport async function updateSession(options: UpdateSessionOptions): Promise<UpdateSessionResult> {\n const accessCookieName = getAccessTokenCookieName(options.names);\n const refreshCookieName = getRefreshTokenCookieName(options.names);\n const accessToken = getCookieValue(options.requestCookies, accessCookieName);\n\n if (accessToken && !isJwtExpiredOrExpiring(accessToken, options.refreshLeewaySeconds)) {\n return {\n refreshed: false,\n accessToken,\n error: null,\n };\n }\n\n const refreshToken = getCookieValue(options.requestCookies, refreshCookieName);\n if (!refreshToken) {\n if (accessToken) {\n clearAuthCookies(options.requestCookies, options);\n clearAuthCookies(options.responseCookies, options);\n }\n return {\n refreshed: false,\n accessToken: null,\n error: null,\n };\n }\n\n const result = await refreshAuth({\n ...options,\n refreshToken,\n });\n\n if (result.error || !result.accessToken) {\n clearAuthCookies(options.requestCookies, options);\n clearAuthCookies(options.responseCookies, options);\n return {\n refreshed: false,\n accessToken: null,\n error: result.error,\n };\n }\n\n const tokens = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken ?? refreshToken,\n };\n setAuthCookies(options.requestCookies, tokens, options);\n setAuthCookies(options.responseCookies, tokens, options);\n\n return {\n refreshed: true,\n accessToken: result.accessToken,\n error: null,\n };\n}\n"],"mappings":"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","names":["error"]}
@@ -1,18 +1,19 @@
1
1
  // src/lib/jwt.ts
2
2
  function decodeBase64Url(input) {
3
3
  const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
4
- const padded = normalized.padEnd(
5
- normalized.length + (4 - normalized.length % 4) % 4,
6
- "="
7
- );
4
+ const padded = normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "=");
8
5
  const binary = atob(padded);
9
6
  const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
10
7
  return new TextDecoder().decode(bytes);
11
8
  }
12
9
  function getJwtExpiration(token) {
13
- if (!token) return null;
10
+ if (!token) {
11
+ return null;
12
+ }
14
13
  const [, payload] = token.split(".");
15
- if (!payload) return null;
14
+ if (!payload) {
15
+ return null;
16
+ }
16
17
  try {
17
18
  const parsed = JSON.parse(decodeBase64Url(payload));
18
19
  if (typeof parsed.exp !== "number" || !Number.isFinite(parsed.exp)) {
@@ -24,9 +25,13 @@ function getJwtExpiration(token) {
24
25
  }
25
26
  }
26
27
  function isJwtExpiredOrExpiring(token, leewaySeconds = 60) {
27
- if (!token) return false;
28
+ if (!token) {
29
+ return false;
30
+ }
28
31
  const expires = getJwtExpiration(token);
29
- if (!expires) return true;
32
+ if (!expires) {
33
+ return true;
34
+ }
30
35
  return expires.getTime() <= Date.now() + leewaySeconds * 1e3;
31
36
  }
32
37
 
@@ -41,18 +46,28 @@ function getRefreshTokenCookieName(names) {
41
46
  return names?.refreshToken ?? DEFAULT_REFRESH_TOKEN_COOKIE;
42
47
  }
43
48
  function getCookieValue(cookies, name) {
44
- if (!cookies) return null;
49
+ if (!cookies) {
50
+ return null;
51
+ }
45
52
  const value = cookies.get(name);
46
- if (typeof value === "string") return value || null;
47
- if (value && typeof value.value === "string") return value.value || null;
53
+ if (typeof value === "string") {
54
+ return value || null;
55
+ }
56
+ if (value && typeof value.value === "string") {
57
+ return value.value || null;
58
+ }
48
59
  return null;
49
60
  }
50
61
  function getCookieValueFromHeader(cookieHeader, name) {
51
- if (!cookieHeader) return null;
62
+ if (!cookieHeader) {
63
+ return null;
64
+ }
52
65
  const parts = cookieHeader.split(";");
53
66
  for (const part of parts) {
54
67
  const [rawName, ...rawValue] = part.trim().split("=");
55
- if (rawName !== name) continue;
68
+ if (rawName !== name) {
69
+ continue;
70
+ }
56
71
  try {
57
72
  return decodeURIComponent(rawValue.join("="));
58
73
  } catch {
@@ -95,11 +110,15 @@ function expiredCookieOptions(overrides) {
95
110
  };
96
111
  }
97
112
  function setCookie(cookies, name, value, options) {
98
- if (!cookies?.set) return;
113
+ if (!cookies?.set) {
114
+ return;
115
+ }
99
116
  cookies.set(name, value, options);
100
117
  }
101
118
  function deleteCookie(cookies, name, options) {
102
- if (!cookies) return;
119
+ if (!cookies) {
120
+ return;
121
+ }
103
122
  if (cookies.set) {
104
123
  cookies.set(name, "", expiredCookieOptions(options));
105
124
  return;
@@ -108,12 +127,24 @@ function deleteCookie(cookies, name, options) {
108
127
  }
109
128
  function serializeCookie(name, value, options = {}) {
110
129
  const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
111
- if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
112
- if (options.domain) parts.push(`Domain=${options.domain}`);
113
- if (options.path) parts.push(`Path=${options.path}`);
114
- if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
115
- if (options.httpOnly) parts.push("HttpOnly");
116
- if (options.secure) parts.push("Secure");
130
+ if (options.maxAge !== void 0) {
131
+ parts.push(`Max-Age=${options.maxAge}`);
132
+ }
133
+ if (options.domain) {
134
+ parts.push(`Domain=${options.domain}`);
135
+ }
136
+ if (options.path) {
137
+ parts.push(`Path=${options.path}`);
138
+ }
139
+ if (options.expires) {
140
+ parts.push(`Expires=${options.expires.toUTCString()}`);
141
+ }
142
+ if (options.httpOnly) {
143
+ parts.push("HttpOnly");
144
+ }
145
+ if (options.secure) {
146
+ parts.push("Secure");
147
+ }
117
148
  if (options.sameSite) {
118
149
  const sameSite = options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1);
119
150
  parts.push(`SameSite=${sameSite}`);
@@ -126,20 +157,14 @@ function appendSetCookie(headers, name, value, options) {
126
157
  function setAuthCookies(cookies, tokens, settings = {}) {
127
158
  const accessName = getAccessTokenCookieName(settings.names);
128
159
  const refreshName = getRefreshTokenCookieName(settings.names);
129
- const accessOptions = accessTokenCookieOptions(
130
- tokens.accessToken,
131
- settings.options?.accessToken
132
- );
160
+ const accessOptions = accessTokenCookieOptions(tokens.accessToken, settings.options?.accessToken);
133
161
  setCookie(cookies, accessName, tokens.accessToken, accessOptions);
134
162
  if (tokens.refreshToken) {
135
163
  setCookie(
136
164
  cookies,
137
165
  refreshName,
138
166
  tokens.refreshToken,
139
- refreshTokenCookieOptions(
140
- tokens.refreshToken,
141
- settings.options?.refreshToken
142
- )
167
+ refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)
143
168
  );
144
169
  }
145
170
  }
@@ -165,10 +190,7 @@ function setAuthCookieHeaders(headers, tokens, settings = {}) {
165
190
  headers,
166
191
  refreshName,
167
192
  tokens.refreshToken,
168
- refreshTokenCookieOptions(
169
- tokens.refreshToken,
170
- settings.options?.refreshToken
171
- )
193
+ refreshTokenCookieOptions(tokens.refreshToken, settings.options?.refreshToken)
172
194
  );
173
195
  }
174
196
  }
@@ -216,7 +238,9 @@ function jsonResponse(body, init = {}, headers = new Headers(init.headers)) {
216
238
  });
217
239
  }
218
240
  function normalizeError(error) {
219
- if (error instanceof InsForgeError) return error;
241
+ if (error instanceof InsForgeError) {
242
+ return error;
243
+ }
220
244
  if (error && typeof error === "object") {
221
245
  const body = error;
222
246
  return new InsForgeError(
@@ -233,18 +257,21 @@ function normalizeError(error) {
233
257
  }
234
258
  async function readJson(response) {
235
259
  const contentType = response.headers.get("content-type");
236
- if (!contentType?.includes("json")) return null;
260
+ if (!contentType?.includes("json")) {
261
+ return null;
262
+ }
237
263
  return response.json();
238
264
  }
239
265
  function readRefreshToken(options) {
240
- if (options.refreshToken) return options.refreshToken;
266
+ if (options.refreshToken) {
267
+ return options.refreshToken;
268
+ }
241
269
  const refreshCookieName = getRefreshTokenCookieName(options.names);
242
270
  const cookieValue = getCookieValue(options.cookies, refreshCookieName);
243
- if (cookieValue) return cookieValue;
244
- return getCookieValueFromHeader(
245
- options.request?.headers.get("cookie"),
246
- refreshCookieName
247
- );
271
+ if (cookieValue) {
272
+ return cookieValue;
273
+ }
274
+ return getCookieValueFromHeader(options.request?.headers.get("cookie"), refreshCookieName);
248
275
  }
249
276
  async function refreshAuth(options = {}) {
250
277
  const headers = new Headers();
@@ -285,9 +312,7 @@ async function refreshAuth(options = {}) {
285
312
  }
286
313
  const fetchImpl = options.fetch ?? (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
287
314
  if (!fetchImpl) {
288
- throw new Error(
289
- "Fetch is not available. Please provide a fetch implementation."
290
- );
315
+ throw new Error("Fetch is not available. Please provide a fetch implementation.");
291
316
  }
292
317
  const requestHeaders = new Headers(options.headers);
293
318
  requestHeaders.set("Authorization", `Bearer ${anonKey}`);
@@ -365,10 +390,7 @@ async function refreshAuth(options = {}) {
365
390
  async function updateSession(options) {
366
391
  const accessCookieName = getAccessTokenCookieName(options.names);
367
392
  const refreshCookieName = getRefreshTokenCookieName(options.names);
368
- const accessToken = getCookieValue(
369
- options.requestCookies,
370
- accessCookieName
371
- );
393
+ const accessToken = getCookieValue(options.requestCookies, accessCookieName);
372
394
  if (accessToken && !isJwtExpiredOrExpiring(accessToken, options.refreshLeewaySeconds)) {
373
395
  return {
374
396
  refreshed: false,
@@ -376,10 +398,7 @@ async function updateSession(options) {
376
398
  error: null
377
399
  };
378
400
  }
379
- const refreshToken = getCookieValue(
380
- options.requestCookies,
381
- refreshCookieName
382
- );
401
+ const refreshToken = getCookieValue(options.requestCookies, refreshCookieName);
383
402
  if (!refreshToken) {
384
403
  if (accessToken) {
385
404
  clearAuthCookies(options.requestCookies, options);