@sylphx/sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -0
- package/dist/index.d.cts +13938 -0
- package/dist/index.d.ts +13938 -0
- package/dist/index.js +3291 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3058 -0
- package/dist/index.mjs.map +1 -0
- package/dist/nextjs/index.d.cts +2089 -0
- package/dist/nextjs/index.d.ts +2089 -0
- package/dist/nextjs/index.js +1994 -0
- package/dist/nextjs/index.js.map +1 -0
- package/dist/nextjs/index.mjs +1941 -0
- package/dist/nextjs/index.mjs.map +1 -0
- package/dist/react/index.d.cts +14894 -0
- package/dist/react/index.d.ts +14894 -0
- package/dist/react/index.js +90818 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +90573 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/server/index.d.cts +9908 -0
- package/dist/server/index.d.ts +9908 -0
- package/dist/server/index.js +2733 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +2660 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/web-analytics.d.cts +90 -0
- package/dist/web-analytics.d.ts +90 -0
- package/dist/web-analytics.js +250 -0
- package/dist/web-analytics.js.map +1 -0
- package/dist/web-analytics.mjs +221 -0
- package/dist/web-analytics.mjs.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../../../node_modules/jose/dist/webapi/lib/buffer_utils.js","../../../../node_modules/jose/dist/webapi/lib/base64.js","../../../../node_modules/jose/dist/webapi/util/base64url.js","../../../../node_modules/jose/dist/webapi/util/errors.js","../../../../node_modules/jose/dist/webapi/lib/crypto_key.js","../../../../node_modules/jose/dist/webapi/lib/invalid_key_input.js","../../../../node_modules/jose/dist/webapi/lib/is_key_like.js","../../../../node_modules/jose/dist/webapi/lib/is_disjoint.js","../../../../node_modules/jose/dist/webapi/lib/is_object.js","../../../../node_modules/jose/dist/webapi/lib/check_key_length.js","../../../../node_modules/jose/dist/webapi/lib/jwk_to_key.js","../../../../node_modules/jose/dist/webapi/key/import.js","../../../../node_modules/jose/dist/webapi/lib/validate_crit.js","../../../../node_modules/jose/dist/webapi/lib/validate_algorithms.js","../../../../node_modules/jose/dist/webapi/lib/is_jwk.js","../../../../node_modules/jose/dist/webapi/lib/normalize_key.js","../../../../node_modules/jose/dist/webapi/lib/check_key_type.js","../../../../node_modules/jose/dist/webapi/lib/subtle_dsa.js","../../../../node_modules/jose/dist/webapi/lib/get_sign_verify_key.js","../../../../node_modules/jose/dist/webapi/lib/verify.js","../../../../node_modules/jose/dist/webapi/jws/flattened/verify.js","../../../../node_modules/jose/dist/webapi/jws/compact/verify.js","../../../../node_modules/jose/dist/webapi/lib/jwt_claims_set.js","../../../../node_modules/jose/dist/webapi/jwt/verify.js","../../src/constants.ts","../../src/rest-client.ts","../../src/errors.ts","../../src/key-validation.ts","../../src/server/ai.ts","../../src/server/kv.ts","../../src/server/streams.ts"],"sourcesContent":["/**\n * Sylphx Server SDK\n *\n * Server-side operations using REST API for type safety.\n * Uses Secret Key for authentication - NEVER expose this to client-side.\n *\n * @example\n * ```typescript\n * import { createServerClient, verifyWebhook } from '@sylphx/sdk/server'\n *\n * const client = createServerClient({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * // REST API calls\n * const { data: plans } = await client.GET('/billing/plans')\n * const { data: user } = await client.GET('/user/profile')\n * ```\n */\n\nimport { importJWK, type JWTPayload, jwtVerify } from 'jose'\nimport { JWK_CACHE_TTL_MS, WEBHOOK_CLOCK_SKEW_MS, WEBHOOK_MAX_AGE_MS } from '../constants'\nimport {\n\tcreateDynamicRestClient,\n\tcreateRestClient,\n\ttype RestClient,\n\ttype RestClientConfig,\n} from '../rest-client'\nimport type { AccessTokenPayload } from '../types'\n\n// Re-export key validation utilities from SSOT\nexport {\n\t// Environment detection\n\tdetectEnvironment,\n\t// Key type detection\n\tdetectKeyType,\n\t// Types\n\ttype EnvironmentType,\n\t// Cookie namespace\n\tgetCookieNamespace,\n\tisAppId,\n\tisDevelopmentKey,\n\t// Runtime detection\n\tisDevelopmentRuntime,\n\tisProductionKey,\n\tisSecretKey,\n\ttype KeyType,\n\ttype KeyValidationResult,\n\tvalidateAndSanitizeAppId,\n\tvalidateAndSanitizeKey,\n\tvalidateAndSanitizeSecretKey,\n\t// App ID validation\n\tvalidateAppId,\n\t// Generic key validation (auto-detects type)\n\tvalidateKey,\n\t// Secret key validation\n\tvalidateSecretKey,\n} from '../key-validation'\n\n// Internal import for local use (import separately to avoid hoisting issues)\nimport {\n\tdetectEnvironment as _detectEnvironment,\n\tvalidateAndSanitizeAppId,\n\tvalidateAndSanitizeSecretKey,\n} from '../key-validation'\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n// Note: EnvironmentType, detectEnvironment, isDevelopmentKey, isProductionKey\n// are re-exported from '../key-validation' (SSOT)\n\nexport interface ServerConfig {\n\t/**\n\t * Your Secret Key (keep secure, server-only)\n\t *\n\t * The secret key IS the app identity — no separate app ID needed.\n\t * Use environment-specific keys for proper isolation:\n\t * - Development: sk_dev_xxx (relaxed rate limits, test mode)\n\t * - Staging: sk_stg_xxx (test mode, production-like settings)\n\t * - Production: sk_prod_xxx (strict settings, live data)\n\t */\n\tsecretKey: string\n\t/** Platform URL (defaults to https://sylphx.com) */\n\tplatformUrl?: string\n\t/** Optional cache TTL in seconds. Default: 60 */\n\trevalidate?: number\n}\n\n// ============================================================================\n// Server Client\n// ============================================================================\n\n/**\n * Create a Server Client for platform operations.\n *\n * Uses REST API for type-safe API calls.\n * The secret key identifies the app — no separate app ID needed.\n *\n * @example\n * ```typescript\n * const client = createServerClient({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * // Billing\n * const { data: plans } = await client.GET('/billing/plans')\n * const { data: subscription } = await client.GET('/billing/subscription')\n *\n * // Analytics\n * await client.POST('/analytics/track', {\n * body: { events: [{ event: 'purchase', properties: { amount: 99 } }] }\n * })\n * ```\n */\nexport function createServerClient(config: ServerConfig): RestClient {\n\t// Validate and sanitize secret key using SSOT\n\tconst secretKey = validateAndSanitizeSecretKey(config.secretKey)\n\n\treturn createRestClient({\n\t\tsecretKey,\n\t\tplatformUrl: config.platformUrl?.trim(),\n\t})\n}\n\n/**\n * Create a Server Client with user context (access token)\n */\nexport function createAuthenticatedServerClient(\n\tconfig: ServerConfig,\n\taccessToken: string,\n): RestClient {\n\treturn createDynamicRestClient({\n\t\tsecretKey: config.secretKey,\n\t\tplatformUrl: config.platformUrl,\n\t\tgetAccessToken: () => accessToken,\n\t})\n}\n\n// ============================================================================\n// JWT Verification\n// ============================================================================\n\n/** JWKS Response structure */\ninterface JwksResponse {\n\tkeys: JsonWebKey[]\n}\n\n/** Type guard to validate JWKS response */\nfunction isJwksResponse(data: unknown): data is JwksResponse {\n\treturn (\n\t\ttypeof data === 'object' &&\n\t\tdata !== null &&\n\t\t'keys' in data &&\n\t\tArray.isArray((data as JwksResponse).keys)\n\t)\n}\n\n/** Type guard to validate AccessTokenPayload */\nfunction isAccessTokenPayload(payload: JWTPayload): payload is JWTPayload & AccessTokenPayload {\n\treturn (\n\t\ttypeof payload.sub === 'string' &&\n\t\ttypeof payload.email === 'string' &&\n\t\ttypeof payload.app_id === 'string' &&\n\t\ttypeof payload.iat === 'number' &&\n\t\ttypeof payload.exp === 'number'\n\t)\n}\n\n// Cache for JWKS\nlet jwksCache: { keys: JsonWebKey[]; expiresAt: number } | null = null\n\n/**\n * Fetch JWKS from the platform\n */\nexport async function getJwks(platformUrl = DEFAULT_PLATFORM_URL): Promise<JsonWebKey[]> {\n\tconst now = Date.now()\n\n\tif (jwksCache && jwksCache.expiresAt > now) {\n\t\treturn jwksCache.keys\n\t}\n\n\tconst response = await fetch(`${platformUrl}/api/v1/auth/.well-known/jwks.json`)\n\tif (!response.ok) {\n\t\tthrow new Error('Failed to fetch JWKS')\n\t}\n\n\tconst data: unknown = await response.json()\n\tif (!isJwksResponse(data)) {\n\t\tthrow new Error('Invalid JWKS response format')\n\t}\n\n\tjwksCache = {\n\t\tkeys: data.keys,\n\t\texpiresAt: now + JWK_CACHE_TTL_MS, // Cache for 1 hour\n\t}\n\n\treturn data.keys\n}\n\n/**\n * Verify an access token from the platform\n */\nexport async function verifyAccessToken(\n\ttoken: string,\n\toptions: {\n\t\tsecretKey?: string\n\t\tplatformUrl?: string\n\t},\n): Promise<AccessTokenPayload> {\n\tconst platformUrl = options.platformUrl || DEFAULT_PLATFORM_URL\n\tconst keys = await getJwks(platformUrl)\n\n\tif (!keys.length) {\n\t\tthrow new Error('No keys in JWKS')\n\t}\n\n\t// Try each key until one works.\n\t// Audience validation is handled by the platform when tokens are issued —\n\t// the SDK verifies cryptographic signature and issuer only.\n\tlet lastError: Error | null = null\n\tfor (const key of keys) {\n\t\ttry {\n\t\t\tconst jwk = await importJWK(key, 'RS256')\n\t\t\tconst { payload } = await jwtVerify(token, jwk, {\n\t\t\t\tissuer: platformUrl,\n\t\t\t})\n\n\t\t\t// Validate payload structure at runtime\n\t\t\tif (!isAccessTokenPayload(payload)) {\n\t\t\t\tthrow new Error('Invalid token payload structure')\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsub: payload.sub,\n\t\t\t\temail: payload.email,\n\t\t\t\tname: payload.name,\n\t\t\t\tpicture: payload.picture,\n\t\t\t\temail_verified: payload.email_verified,\n\t\t\t\tapp_id: payload.app_id,\n\t\t\t\trole: payload.role,\n\t\t\t\tiat: payload.iat,\n\t\t\t\texp: payload.exp,\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlastError = err as Error\n\t\t}\n\t}\n\n\tthrow lastError || new Error('Token verification failed')\n}\n\n// ============================================================================\n// Webhook Signature Verification\n// ============================================================================\n\nexport interface WebhookPayload {\n\tevent: string\n\tdata: unknown\n\ttimestamp: number\n\tid: string\n}\n\nexport interface WebhookVerifyResult {\n\tvalid: boolean\n\tpayload?: WebhookPayload\n\terror?: string\n}\n\nexport interface WebhookVerifyOptions {\n\t/** Maximum age of webhook in milliseconds (default: 5 minutes) */\n\tmaxAge?: number\n\t/** Allow clock skew in milliseconds (default: 30 seconds) */\n\tclockSkew?: number\n}\n\n/**\n * Verify webhook signature from Sylphx Platform\n *\n * The platform sends `X-Webhook-Signature` in `t={unix_seconds},v1={hmac_hex}`\n * format. This function accepts either:\n * - The raw header value (auto-parsed)\n * - Pre-extracted `signature` + `timestamp` strings\n *\n * @example\n * ```typescript\n * import { verifyWebhook } from '@sylphx/sdk/server'\n *\n * export async function POST(request: Request) {\n * const body = await request.text()\n * const result = await verifyWebhook({\n * payload: body,\n * signatureHeader: request.headers.get('x-webhook-signature'),\n * secret: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * if (!result.valid) {\n * return new Response('Invalid signature', { status: 401 })\n * }\n *\n * console.log('Received webhook:', result.payload)\n * }\n * ```\n */\nexport async function verifyWebhook(options: {\n\tpayload: string\n\t/** Raw X-Webhook-Signature header value: \"t={seconds},v1={hex}\" */\n\tsignatureHeader?: string | null\n\t/** Pre-extracted HMAC hex (if parsing header yourself) */\n\tsignature?: string | null\n\t/** Pre-extracted timestamp in unix seconds (if parsing header yourself) */\n\ttimestamp?: string | null\n\tsecret: string\n\tverifyOptions?: WebhookVerifyOptions\n}): Promise<WebhookVerifyResult> {\n\tconst { payload, secret, verifyOptions = {} } = options\n\tconst { maxAge = WEBHOOK_MAX_AGE_MS, clockSkew = WEBHOOK_CLOCK_SKEW_MS } = verifyOptions\n\n\t// Parse the combined header format: \"t={seconds},v1={hex}\"\n\tlet signatureHex = options.signature ?? null\n\tlet timestampStr = options.timestamp ?? null\n\n\tif (options.signatureHeader) {\n\t\tconst tMatch = options.signatureHeader.match(/t=(\\d+)/)\n\t\tconst vMatch = options.signatureHeader.match(/v1=([a-f0-9]+)/)\n\t\tif (tMatch) timestampStr = tMatch[1]\n\t\tif (vMatch) signatureHex = vMatch[1]\n\t}\n\n\tif (!signatureHex) {\n\t\treturn { valid: false, error: 'Missing signature' }\n\t}\n\tif (!timestampStr) {\n\t\treturn { valid: false, error: 'Missing timestamp' }\n\t}\n\n\tconst webhookTimeSeconds = Number.parseInt(timestampStr, 10)\n\tif (Number.isNaN(webhookTimeSeconds)) {\n\t\treturn { valid: false, error: 'Invalid timestamp format' }\n\t}\n\n\t// Convert seconds → milliseconds for comparison with Date.now()\n\tconst webhookTimeMs = webhookTimeSeconds * 1000\n\tconst now = Date.now()\n\tconst age = now - webhookTimeMs\n\n\tif (age > maxAge) {\n\t\treturn { valid: false, error: `Webhook too old: ${age}ms` }\n\t}\n\n\tif (age < -clockSkew) {\n\t\treturn { valid: false, error: 'Webhook timestamp is in the future' }\n\t}\n\n\t// Reconstruct the signed payload: \"{seconds}.{body}\"\n\tconst signedPayload = `${timestampStr}.${payload}`\n\n\ttry {\n\t\tconst expectedSignature = await computeHmacSha256(signedPayload, secret)\n\n\t\tif (!timingSafeEqual(signatureHex, expectedSignature)) {\n\t\t\treturn { valid: false, error: 'Invalid signature' }\n\t\t}\n\n\t\tconst parsedPayload = JSON.parse(payload) as WebhookPayload\n\t\treturn { valid: true, payload: parsedPayload }\n\t} catch (error) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: error instanceof Error ? error.message : 'Verification failed',\n\t\t}\n\t}\n}\n\nasync function computeHmacSha256(message: string, secret: string): Promise<string> {\n\tconst encoder = new TextEncoder()\n\tconst keyData = encoder.encode(secret)\n\tconst messageData = encoder.encode(message)\n\n\tconst cryptoKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tkeyData,\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign'],\n\t)\n\n\tconst signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData)\n\treturn Buffer.from(signature).toString('hex')\n}\n\nfunction timingSafeEqual(a: string, b: string): boolean {\n\t// Compare against b if lengths match, otherwise compare a against itself.\n\t// This prevents timing side-channel leaks: the loop always runs a.length\n\t// iterations regardless of whether lengths match, so an attacker cannot\n\t// infer b's length from response time.\n\tconst target = a.length === b.length ? b : a\n\tlet result = a.length ^ b.length // Non-zero if lengths differ\n\tfor (let i = 0; i < a.length; i++) {\n\t\tresult |= a.charCodeAt(i) ^ target.charCodeAt(i)\n\t}\n\treturn result === 0\n}\n\n/**\n * Create a webhook handler with automatic verification\n *\n * @example\n * ```typescript\n * import { createWebhookHandler } from '@sylphx/sdk/server'\n *\n * const handler = createWebhookHandler({\n * secret: process.env.SYLPHX_SECRET_KEY!,\n * handlers: {\n * 'user.created': async (data) => {\n * console.log('New user:', data)\n * },\n * 'subscription.updated': async (data) => {\n * console.log('Subscription changed:', data)\n * },\n * },\n * })\n *\n * export { handler as POST }\n * ```\n */\nexport function createWebhookHandler(config: {\n\tsecret: string\n\thandlers: Record<string, (data: unknown) => Promise<void> | void>\n\tverifyOptions?: WebhookVerifyOptions\n}): (request: Request) => Promise<Response> {\n\treturn async (request: Request) => {\n\t\tconst signatureHeader = request.headers.get('x-webhook-signature')\n\t\tconst body = await request.text()\n\n\t\tconst result = await verifyWebhook({\n\t\t\tpayload: body,\n\t\t\tsignatureHeader,\n\t\t\tsecret: config.secret,\n\t\t\tverifyOptions: config.verifyOptions,\n\t\t})\n\n\t\tif (!result.valid) {\n\t\t\treturn new Response(JSON.stringify({ error: result.error }), {\n\t\t\t\tstatus: 401,\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t})\n\t\t}\n\n\t\tif (!result.payload) {\n\t\t\treturn new Response(JSON.stringify({ error: 'Missing payload' }), {\n\t\t\t\tstatus: 400,\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t})\n\t\t}\n\n\t\tconst { event, data } = result.payload\n\t\tconst handler = config.handlers[event]\n\n\t\tif (!handler) {\n\t\t\treturn new Response(JSON.stringify({ received: true, handled: false }), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t})\n\t\t}\n\n\t\ttry {\n\t\t\tawait handler(data)\n\t\t\treturn new Response(JSON.stringify({ received: true, handled: true }), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t})\n\t\t} catch (error) {\n\t\t\treturn new Response(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\terror: 'Handler failed',\n\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Unknown error',\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t}\n}\n\n// Re-export types\nexport type { RestClient, RestClientConfig as ServerClientConfig }\n\n// ============================================================================\n// Server-Side Data Fetching — Shared Infrastructure\n// ============================================================================\n\nimport { DEFAULT_PLATFORM_URL, SDK_API_PATH } from '../constants'\n\n/** Common options for authenticated SDK fetch — secret key identifies the app */\ninterface AuthenticatedFetchOptions {\n\t/** Secret key for authentication (sk_dev_xxx, sk_stg_xxx, sk_prod_xxx) */\n\tsecretKey: string\n\t/** Platform URL (defaults to https://sylphx.com) */\n\tplatformUrl?: string\n\t/** Optional cache TTL in seconds. Default: 60 */\n\trevalidate?: number\n}\n\n/**\n * Options for public endpoints that only need an App ID (public key).\n * The App ID IS the app identity — no separate key needed.\n */\ninterface PublicFetchOptions {\n\t/** App ID (app_dev_xxx, app_stg_xxx, app_prod_xxx) — identifies the app */\n\tappId: string\n\t/** Platform URL (defaults to https://sylphx.com) */\n\tplatformUrl?: string\n\t/** Optional cache TTL in seconds. Default: 60 */\n\trevalidate?: number\n}\n\n/**\n * Fetch config data with NO CACHE.\n *\n * Config data (OAuth providers, plans, flags) must reflect admin changes immediately.\n * Using `cache: 'no-store'` ensures every request hits the origin.\n *\n * The API endpoint itself returns Cache-Control headers for CDN caching (60s),\n * but the Next.js Data Cache is bypassed to ensure fresh data on each SSR.\n *\n * Trade-off: Slightly higher latency per request, but config is always fresh.\n * This is the industry standard (Clerk, Auth0, Firebase) for auth config.\n */\nasync function cachedFetch<T>(params: {\n\turl: string\n\theaders?: Record<string, string>\n\tfallback: T\n\tlabel: string\n\trevalidate?: number\n}): Promise<T> {\n\tconst { url, headers, fallback, label, revalidate = 60 } = params\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\theaders,\n\t\t\t// @ts-expect-error - Next.js extended fetch option\n\t\t\tnext: { revalidate }, // Next.js Data Cache with TTL\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(`[Sylphx] Failed to fetch ${label}:`, response.status)\n\t\t\treturn fallback\n\t\t}\n\n\t\tconst data = await response.json()\n\t\treturn (data as T) ?? fallback\n\t} catch (error) {\n\t\tconsole.warn(`[Sylphx] Failed to fetch ${label}:`, error)\n\t\treturn fallback\n\t}\n}\n\n/**\n * Sanitize options using SSOT key validation\n * Validates secretKey format and trims platformUrl\n */\nfunction sanitizeOptions<T extends AuthenticatedFetchOptions>(options: T): T {\n\treturn {\n\t\t...options,\n\t\tsecretKey: validateAndSanitizeSecretKey(options.secretKey),\n\t\tplatformUrl: (options.platformUrl ?? DEFAULT_PLATFORM_URL).trim(),\n\t}\n}\n\n/** Build authenticated headers for SDK API calls — secret key identifies the app */\nfunction sdkHeaders(secretKey: string): Record<string, string> {\n\treturn { 'x-app-secret': secretKey }\n}\n\n// ============================================================================\n// OAuth Providers (Server-Side)\n// ============================================================================\n\nimport type { OAuthProvider } from '@sylphx/ui'\nexport type { OAuthProvider }\n\n/** OAuth provider with display name */\nexport interface OAuthProviderInfo {\n\tid: OAuthProvider\n\tname: string\n}\n\n/**\n * Get enabled OAuth providers for an app (server-side)\n *\n * The App ID identifies the app via `X-App-Id` header.\n *\n * @example\n * ```tsx\n * const providers = await getOAuthProviders({\n * appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,\n * })\n * ```\n */\nexport async function getOAuthProviders(options: PublicFetchOptions): Promise<OAuthProvider[]> {\n\tconst data = await fetchOAuthProviders(options)\n\treturn (data.providers || []).map((p) => p.id)\n}\n\n/**\n * Get enabled OAuth providers with full info (server-side)\n */\nexport async function getOAuthProvidersWithInfo(\n\toptions: PublicFetchOptions,\n): Promise<OAuthProviderInfo[]> {\n\tconst data = await fetchOAuthProviders(options)\n\treturn data.providers || []\n}\n\n/** Shared fetch for OAuth providers — App ID header identifies the app */\nasync function fetchOAuthProviders(\n\toptions: PublicFetchOptions,\n): Promise<{ providers: OAuthProviderInfo[] }> {\n\tconst baseURL = (options.platformUrl ?? DEFAULT_PLATFORM_URL).trim()\n\t// Validate and sanitize App ID - logs warning if key contains whitespace\n\tconst appId = validateAndSanitizeAppId(options.appId)\n\n\treturn cachedFetch<{ providers: OAuthProviderInfo[] }>({\n\t\turl: `${baseURL}/api/auth/providers`,\n\t\theaders: { 'X-App-Id': appId },\n\t\tfallback: { providers: [] },\n\t\tlabel: 'OAuth providers',\n\t})\n}\n\n// ============================================================================\n// Plans (Server-Side)\n// ============================================================================\n\nimport type { Plan } from '../billing'\nexport type { Plan }\n\n/**\n * Get subscription plans for an app (server-side)\n *\n * Note: Prefer using `getAppConfig()` which fetches all config in parallel.\n * This function is used internally by `getAppConfig()`.\n */\nexport async function getPlans(options: AuthenticatedFetchOptions): Promise<Plan[]> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\treturn cachedFetch<Plan[]>({\n\t\turl: `${platformUrl}${SDK_API_PATH}/billing/plans`,\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: [],\n\t\tlabel: 'plans',\n\t})\n}\n\n// ============================================================================\n// Consent Types (Server-Side)\n// ============================================================================\n\nimport type { ConsentType } from '../consent'\nexport type { ConsentType }\n\n/**\n * Get consent types for an app (server-side)\n *\n * Note: Prefer using `getAppConfig()` which fetches all config in parallel.\n * This function is used internally by `getAppConfig()`.\n */\nexport async function getConsentTypes(options: AuthenticatedFetchOptions): Promise<ConsentType[]> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\treturn cachedFetch<ConsentType[]>({\n\t\turl: `${platformUrl}${SDK_API_PATH}/consent/types`,\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: [],\n\t\tlabel: 'consent types',\n\t})\n}\n\n// ============================================================================\n// Feature Flags (Server-Side)\n// ============================================================================\n\n/** Feature flag definition for SSR */\nexport interface FeatureFlagDefinition {\n\tkey: string\n\tname: string\n\tdescription: string | null\n\tenabled: boolean\n\trolloutPercentage: number\n\ttargetPremiumOnly: boolean\n\ttargetAdminOnly: boolean\n}\n\n/**\n * Get feature flag definitions for an app (server-side)\n *\n * Returns flag definitions. Evaluation (rollout, targeting) happens\n * client-side using the LocalEvaluator with user context.\n *\n * @example\n * ```tsx\n * import { getFeatureFlags } from '@sylphx/sdk/server'\n *\n * export default async function RootLayout({ children }) {\n * const flags = await getFeatureFlags({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n * return <FeatureFlagsProvider initialFlags={flags}>{children}</FeatureFlagsProvider>\n * }\n * ```\n */\nexport async function getFeatureFlags(\n\toptions: AuthenticatedFetchOptions,\n): Promise<FeatureFlagDefinition[]> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\treturn cachedFetch<FeatureFlagDefinition[]>({\n\t\turl: `${platformUrl}${SDK_API_PATH}/flags`,\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: [],\n\t\tlabel: 'feature flags',\n\t})\n}\n\n// ============================================================================\n// App Metadata (Server-Side)\n// ============================================================================\n\n/** App metadata returned by /api/sdk/app */\nexport interface AppMetadata {\n\tid: string\n\tname: string\n\tslug: string\n}\n\n/**\n * Get app metadata (server-side)\n *\n * @internal Used by getAppConfig() - rarely called directly\n */\nexport async function getAppMetadata(options: AuthenticatedFetchOptions): Promise<AppMetadata> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\treturn cachedFetch<AppMetadata>({\n\t\turl: `${platformUrl}${SDK_API_PATH}/app`,\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: { id: '', name: '', slug: '' },\n\t\tlabel: 'app metadata',\n\t})\n}\n\n// ============================================================================\n// AppConfig — Server-First Configuration\n// ============================================================================\n// The recommended way to initialize the SDK. Fetches all config data in parallel\n// from Server Components, then passes it to SylphxProvider as a required prop.\n\nimport type { AppConfig, OAuthProviderInfo as OAuthProviderInfoType } from '../types'\nexport type { AppConfig }\n\n/**\n * Options for getAppConfig()\n */\nexport interface GetAppConfigOptions {\n\t/** Secret key for authenticated endpoints (plans, flags, consent types) */\n\tsecretKey: string\n\t/** App ID for public endpoints (OAuth providers) - identifies your app */\n\tappId: string\n\t/** Platform URL (defaults to https://sylphx.com) */\n\tplatformUrl?: string\n\t/** Optional cache TTL in seconds. Default: 60 */\n\trevalidate?: number\n}\n\n/**\n * Get complete app configuration for the SDK (server-side)\n *\n * This is the **recommended** way to initialize the Sylphx SDK. It fetches all\n * configuration data in a single call from a Server Component, eliminating the\n * need for client-side config fetching and the associated loading states.\n *\n * Returns:\n * - plans: Subscription plans for billing\n * - consentTypes: GDPR/CCPA consent configuration\n * - oauthProviders: Enabled OAuth providers for auth\n * - featureFlags: Feature flag definitions for client-side evaluation\n * - app: App metadata (id, name, slug)\n * - fetchedAt: ISO timestamp for cache debugging\n *\n * @example\n * ```tsx\n * // app/layout.tsx (Server Component)\n * import { getAppConfig } from '@sylphx/sdk/server'\n *\n * export default async function RootLayout({ children }) {\n * const config = await getAppConfig({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,\n * })\n *\n * return (\n * <html>\n * <body>\n * <SylphxProvider\n * config={config}\n * appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}\n * >\n * {children}\n * </SylphxProvider>\n * </body>\n * </html>\n * )\n * }\n * ```\n */\nexport async function getAppConfig(options: GetAppConfigOptions): Promise<AppConfig> {\n\tconst { secretKey, appId, platformUrl } = options\n\n\t// Fetch all config data in parallel for optimal performance\n\tconst [plans, consentTypes, oauthProviders, featureFlags, app] = await Promise.all([\n\t\tgetPlans({ secretKey, platformUrl }),\n\t\tgetConsentTypes({ secretKey, platformUrl }),\n\t\tgetOAuthProvidersWithInfo({ appId, platformUrl }),\n\t\tgetFeatureFlags({ secretKey, platformUrl }),\n\t\tgetAppMetadata({ secretKey, platformUrl }),\n\t])\n\n\treturn {\n\t\tplans,\n\t\tconsentTypes,\n\t\toauthProviders: oauthProviders as OAuthProviderInfoType[],\n\t\tfeatureFlags,\n\t\tapp,\n\t\tfetchedAt: new Date().toISOString(),\n\t}\n}\n\n// ============================================================================\n// Referral Leaderboard (Server-Side)\n// ============================================================================\n\n/** Referral leaderboard entry */\nexport interface ReferralLeaderboardEntry {\n\trank: number\n\tuserId: string\n\t/** Masked username for privacy */\n\tname: string\n\t/** Number of successful referrals */\n\treferrals: number\n\tisCurrentUser: boolean\n}\n\n/** Referral leaderboard result */\nexport interface ReferralLeaderboardResult {\n\tentries: ReferralLeaderboardEntry[]\n\ttotal: number\n\tperiod: 'all' | 'month' | 'week'\n}\n\n/**\n * Get referral leaderboard for an app (server-side)\n *\n * @example\n * ```tsx\n * import { getReferralLeaderboard } from '@sylphx/sdk/server'\n *\n * export default async function ReferralsPage() {\n * const leaderboard = await getReferralLeaderboard({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * limit: 10,\n * period: 'month',\n * })\n * return <ReferralLeaderboard initialData={leaderboard} />\n * }\n * ```\n */\nexport async function getReferralLeaderboard(\n\toptions: AuthenticatedFetchOptions & {\n\t\tlimit?: number\n\t\tperiod?: 'all' | 'month' | 'week'\n\t},\n): Promise<ReferralLeaderboardResult> {\n\tconst {\n\t\tsecretKey,\n\t\tplatformUrl = DEFAULT_PLATFORM_URL,\n\t\tlimit = 10,\n\t\tperiod = 'all',\n\t} = sanitizeOptions(options)\n\n\tconst url = new URL(`${platformUrl}${SDK_API_PATH}/referrals/leaderboard`)\n\turl.searchParams.set('limit', String(limit))\n\turl.searchParams.set('period', period)\n\n\treturn cachedFetch<ReferralLeaderboardResult>({\n\t\turl: url.toString(),\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: { entries: [], total: 0, period },\n\t\tlabel: 'referral leaderboard',\n\t})\n}\n\n// ============================================================================\n// Engagement Leaderboard (Server-Side)\n// ============================================================================\n\n/** Engagement leaderboard entry */\nexport interface EngagementLeaderboardEntry {\n\trank: number\n\tuserId: string\n\tname: string\n\tscore: number\n\tisCurrentUser: boolean\n}\n\n/** Engagement leaderboard result */\nexport interface EngagementLeaderboardResult {\n\tleaderboardId: string\n\tentries: EngagementLeaderboardEntry[]\n\tperiod: string\n\tresetTime: string | null\n\tuserEntry: EngagementLeaderboardEntry | null\n}\n\n/**\n * Get engagement leaderboard for an app (server-side)\n *\n * @example\n * ```tsx\n * import { getEngagementLeaderboard } from '@sylphx/sdk/server'\n *\n * export default async function LeaderboardPage() {\n * const leaderboard = await getEngagementLeaderboard({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * leaderboardId: 'high-scores',\n * })\n * return <Leaderboard initialData={leaderboard} />\n * }\n * ```\n */\nexport async function getEngagementLeaderboard(\n\toptions: AuthenticatedFetchOptions & {\n\t\tleaderboardId: string\n\t\tlimit?: number\n\t},\n): Promise<EngagementLeaderboardResult> {\n\tconst {\n\t\tsecretKey,\n\t\tleaderboardId,\n\t\tplatformUrl = DEFAULT_PLATFORM_URL,\n\t\tlimit = 10,\n\t} = sanitizeOptions(options)\n\n\tconst url = new URL(\n\t\t`${platformUrl}${SDK_API_PATH}/engagement/leaderboards/${encodeURIComponent(leaderboardId)}`,\n\t)\n\turl.searchParams.set('limit', String(limit))\n\n\treturn cachedFetch<EngagementLeaderboardResult>({\n\t\turl: url.toString(),\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: {\n\t\t\tleaderboardId,\n\t\t\tentries: [],\n\t\t\tperiod: 'all',\n\t\t\tresetTime: null,\n\t\t\tuserEntry: null,\n\t\t},\n\t\tlabel: 'engagement leaderboard',\n\t})\n}\n\n// ============================================================================\n// Database Connection (Server-Side)\n// ============================================================================\n\n/** Database connection info returned by Platform */\nexport interface DatabaseConnectionInfo {\n\tconnectionString: string\n\tdatabaseName: string\n\troleName: string | null\n\tstatus: 'provisioning' | 'ready' | 'suspended' | 'failed' | 'deleted'\n}\n\n/** Database status info */\nexport interface DatabaseStatusInfo {\n\tstatus: 'provisioning' | 'ready' | 'suspended' | 'failed' | 'deleted' | 'not_provisioned'\n\tregion: string | null\n\tpgVersion: number | null\n\tdatabaseName: string | null\n}\n\n/**\n * Get database connection string from Platform (server-side)\n *\n * Use this when your app's database is provisioned by the Sylphx Platform.\n * The connection string is securely stored on Platform and retrieved at startup.\n *\n * **Note:** This requires NEON_API_KEY and PLATFORM_ENCRYPTION_KEY to be\n * configured on the Platform, and your app's database to be provisioned.\n *\n * @example\n * ```typescript\n * import { getDatabaseConnection } from '@sylphx/sdk/server'\n *\n * // In your database initialization\n * const dbInfo = await getDatabaseConnection({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * if (dbInfo) {\n * const pool = new Pool({ connectionString: dbInfo.connectionString })\n * }\n * ```\n */\nexport async function getDatabaseConnection(\n\toptions: AuthenticatedFetchOptions,\n): Promise<DatabaseConnectionInfo | null> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\ttry {\n\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/database/connection-string`, {\n\t\t\theaders: sdkHeaders(secretKey),\n\t\t\tcache: 'no-store', // Always fetch fresh connection string\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\t// 404 means database not provisioned - return null\n\t\t\tif (response.status === 404) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// 412 means database not ready (provisioning, suspended, failed)\n\t\t\tif (response.status === 412) {\n\t\t\t\tconsole.warn('[Sylphx] Database not ready:', await response.text())\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconsole.warn('[Sylphx] Failed to fetch database connection:', response.status)\n\t\t\treturn null\n\t\t}\n\n\t\treturn (await response.json()) as DatabaseConnectionInfo\n\t} catch (error) {\n\t\tconsole.warn('[Sylphx] Failed to fetch database connection:', error)\n\t\treturn null\n\t}\n}\n\n/**\n * Get database status from Platform (server-side)\n *\n * Use this to check if your app's database is provisioned and ready.\n *\n * @example\n * ```typescript\n * import { getDatabaseStatus } from '@sylphx/sdk/server'\n *\n * const status = await getDatabaseStatus({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * if (status?.status === 'ready') {\n * // Database is ready to use\n * }\n * ```\n */\nexport async function getDatabaseStatus(\n\toptions: AuthenticatedFetchOptions,\n): Promise<DatabaseStatusInfo> {\n\tconst { secretKey, platformUrl = DEFAULT_PLATFORM_URL } = sanitizeOptions(options)\n\n\treturn cachedFetch<DatabaseStatusInfo>({\n\t\turl: `${platformUrl}${SDK_API_PATH}/database/status`,\n\t\theaders: sdkHeaders(secretKey),\n\t\tfallback: {\n\t\t\tstatus: 'not_provisioned',\n\t\t\tregion: null,\n\t\t\tpgVersion: null,\n\t\t\tdatabaseName: null,\n\t\t},\n\t\tlabel: 'database status',\n\t})\n}\n\nexport type {\n\tAIClient,\n\tAIClientOptions,\n\tChatCompletionChunk,\n\tChatCompletionOptions,\n\tChatCompletionResponse,\n\tChatCompletionStreamOptions,\n\tChatMessage,\n\tEmbeddingOptions,\n\tEmbeddingResponse,\n\tModelInfo,\n\tModelsResponse,\n} from './ai'\n// AI Client\nexport { createAI, getAI } from './ai'\nexport type {\n\tKvClient,\n\tKvClientOptions,\n\tKvRateLimitResult,\n\tKvSetOptions,\n\tKvZMember,\n} from './kv'\n// KV (Key-Value Store)\nexport { createKv, getKv } from './kv'\nexport type {\n\tChannelHelper,\n\tStreamHistoryOptions,\n\tStreamMessage,\n\tStreamsClient,\n\tStreamsClientOptions,\n} from './streams'\n// Streams (Real-time Pub/Sub)\nexport { createStreams, getStreams } from './streams'\n","export const encoder = new TextEncoder();\nexport const decoder = new TextDecoder();\nconst MAX_INT32 = 2 ** 32;\nexport function concat(...buffers) {\n const size = buffers.reduce((acc, { length }) => acc + length, 0);\n const buf = new Uint8Array(size);\n let i = 0;\n for (const buffer of buffers) {\n buf.set(buffer, i);\n i += buffer.length;\n }\n return buf;\n}\nfunction writeUInt32BE(buf, value, offset) {\n if (value < 0 || value >= MAX_INT32) {\n throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);\n }\n buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset);\n}\nexport function uint64be(value) {\n const high = Math.floor(value / MAX_INT32);\n const low = value % MAX_INT32;\n const buf = new Uint8Array(8);\n writeUInt32BE(buf, high, 0);\n writeUInt32BE(buf, low, 4);\n return buf;\n}\nexport function uint32be(value) {\n const buf = new Uint8Array(4);\n writeUInt32BE(buf, value);\n return buf;\n}\nexport function encode(string) {\n const bytes = new Uint8Array(string.length);\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code > 127) {\n throw new TypeError('non-ASCII string encountered in encode()');\n }\n bytes[i] = code;\n }\n return bytes;\n}\n","export function encodeBase64(input) {\n if (Uint8Array.prototype.toBase64) {\n return input.toBase64();\n }\n const CHUNK_SIZE = 0x8000;\n const arr = [];\n for (let i = 0; i < input.length; i += CHUNK_SIZE) {\n arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(arr.join(''));\n}\nexport function decodeBase64(encoded) {\n if (Uint8Array.fromBase64) {\n return Uint8Array.fromBase64(encoded);\n }\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n","import { encoder, decoder } from '../lib/buffer_utils.js';\nimport { encodeBase64, decodeBase64 } from '../lib/base64.js';\nexport function decode(input) {\n if (Uint8Array.fromBase64) {\n return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {\n alphabet: 'base64url',\n });\n }\n let encoded = input;\n if (encoded instanceof Uint8Array) {\n encoded = decoder.decode(encoded);\n }\n encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');\n try {\n return decodeBase64(encoded);\n }\n catch {\n throw new TypeError('The input to be decoded is not correctly encoded.');\n }\n}\nexport function encode(input) {\n let unencoded = input;\n if (typeof unencoded === 'string') {\n unencoded = encoder.encode(unencoded);\n }\n if (Uint8Array.prototype.toBase64) {\n return unencoded.toBase64({ alphabet: 'base64url', omitPadding: true });\n }\n return encodeBase64(unencoded).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n","export class JOSEError extends Error {\n static code = 'ERR_JOSE_GENERIC';\n code = 'ERR_JOSE_GENERIC';\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class JWTClaimValidationFailed extends JOSEError {\n static code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JWTExpired extends JOSEError {\n static code = 'ERR_JWT_EXPIRED';\n code = 'ERR_JWT_EXPIRED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JOSEAlgNotAllowed extends JOSEError {\n static code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n}\nexport class JOSENotSupported extends JOSEError {\n static code = 'ERR_JOSE_NOT_SUPPORTED';\n code = 'ERR_JOSE_NOT_SUPPORTED';\n}\nexport class JWEDecryptionFailed extends JOSEError {\n static code = 'ERR_JWE_DECRYPTION_FAILED';\n code = 'ERR_JWE_DECRYPTION_FAILED';\n constructor(message = 'decryption operation failed', options) {\n super(message, options);\n }\n}\nexport class JWEInvalid extends JOSEError {\n static code = 'ERR_JWE_INVALID';\n code = 'ERR_JWE_INVALID';\n}\nexport class JWSInvalid extends JOSEError {\n static code = 'ERR_JWS_INVALID';\n code = 'ERR_JWS_INVALID';\n}\nexport class JWTInvalid extends JOSEError {\n static code = 'ERR_JWT_INVALID';\n code = 'ERR_JWT_INVALID';\n}\nexport class JWKInvalid extends JOSEError {\n static code = 'ERR_JWK_INVALID';\n code = 'ERR_JWK_INVALID';\n}\nexport class JWKSInvalid extends JOSEError {\n static code = 'ERR_JWKS_INVALID';\n code = 'ERR_JWKS_INVALID';\n}\nexport class JWKSNoMatchingKey extends JOSEError {\n static code = 'ERR_JWKS_NO_MATCHING_KEY';\n code = 'ERR_JWKS_NO_MATCHING_KEY';\n constructor(message = 'no applicable key found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSMultipleMatchingKeys extends JOSEError {\n [Symbol.asyncIterator];\n static code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n constructor(message = 'multiple matching keys found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSTimeout extends JOSEError {\n static code = 'ERR_JWKS_TIMEOUT';\n code = 'ERR_JWKS_TIMEOUT';\n constructor(message = 'request timed out', options) {\n super(message, options);\n }\n}\nexport class JWSSignatureVerificationFailed extends JOSEError {\n static code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n constructor(message = 'signature verification failed', options) {\n super(message, options);\n }\n}\n","const unusable = (name, prop = 'algorithm.name') => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);\nconst isAlgorithm = (algorithm, name) => algorithm.name === name;\nfunction getHashLength(hash) {\n return parseInt(hash.name.slice(4), 10);\n}\nfunction getNamedCurve(alg) {\n switch (alg) {\n case 'ES256':\n return 'P-256';\n case 'ES384':\n return 'P-384';\n case 'ES512':\n return 'P-521';\n default:\n throw new Error('unreachable');\n }\n}\nfunction checkUsage(key, usage) {\n if (usage && !key.usages.includes(usage)) {\n throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);\n }\n}\nexport function checkSigCryptoKey(key, alg, usage) {\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512': {\n if (!isAlgorithm(key.algorithm, 'HMAC'))\n throw unusable('HMAC');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'RS256':\n case 'RS384':\n case 'RS512': {\n if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))\n throw unusable('RSASSA-PKCS1-v1_5');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'PS256':\n case 'PS384':\n case 'PS512': {\n if (!isAlgorithm(key.algorithm, 'RSA-PSS'))\n throw unusable('RSA-PSS');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'Ed25519':\n case 'EdDSA': {\n if (!isAlgorithm(key.algorithm, 'Ed25519'))\n throw unusable('Ed25519');\n break;\n }\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87': {\n if (!isAlgorithm(key.algorithm, alg))\n throw unusable(alg);\n break;\n }\n case 'ES256':\n case 'ES384':\n case 'ES512': {\n if (!isAlgorithm(key.algorithm, 'ECDSA'))\n throw unusable('ECDSA');\n const expected = getNamedCurve(alg);\n const actual = key.algorithm.namedCurve;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.namedCurve');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usage);\n}\nexport function checkEncCryptoKey(key, alg, usage) {\n switch (alg) {\n case 'A128GCM':\n case 'A192GCM':\n case 'A256GCM': {\n if (!isAlgorithm(key.algorithm, 'AES-GCM'))\n throw unusable('AES-GCM');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'A128KW':\n case 'A192KW':\n case 'A256KW': {\n if (!isAlgorithm(key.algorithm, 'AES-KW'))\n throw unusable('AES-KW');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'ECDH': {\n switch (key.algorithm.name) {\n case 'ECDH':\n case 'X25519':\n break;\n default:\n throw unusable('ECDH or X25519');\n }\n break;\n }\n case 'PBES2-HS256+A128KW':\n case 'PBES2-HS384+A192KW':\n case 'PBES2-HS512+A256KW':\n if (!isAlgorithm(key.algorithm, 'PBKDF2'))\n throw unusable('PBKDF2');\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512': {\n if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))\n throw unusable('RSA-OAEP');\n const expected = parseInt(alg.slice(9), 10) || 1;\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usage);\n}\n","function message(msg, actual, ...types) {\n types = types.filter(Boolean);\n if (types.length > 2) {\n const last = types.pop();\n msg += `one of type ${types.join(', ')}, or ${last}.`;\n }\n else if (types.length === 2) {\n msg += `one of type ${types[0]} or ${types[1]}.`;\n }\n else {\n msg += `of type ${types[0]}.`;\n }\n if (actual == null) {\n msg += ` Received ${actual}`;\n }\n else if (typeof actual === 'function' && actual.name) {\n msg += ` Received function ${actual.name}`;\n }\n else if (typeof actual === 'object' && actual != null) {\n if (actual.constructor?.name) {\n msg += ` Received an instance of ${actual.constructor.name}`;\n }\n }\n return msg;\n}\nexport const invalidKeyInput = (actual, ...types) => message('Key must be ', actual, ...types);\nexport const withAlg = (alg, actual, ...types) => message(`Key for the ${alg} algorithm must be `, actual, ...types);\n","export function assertCryptoKey(key) {\n if (!isCryptoKey(key)) {\n throw new Error('CryptoKey instance expected');\n }\n}\nexport const isCryptoKey = (key) => {\n if (key?.[Symbol.toStringTag] === 'CryptoKey')\n return true;\n try {\n return key instanceof CryptoKey;\n }\n catch {\n return false;\n }\n};\nexport const isKeyObject = (key) => key?.[Symbol.toStringTag] === 'KeyObject';\nexport const isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);\n","export function isDisjoint(...headers) {\n const sources = headers.filter(Boolean);\n if (sources.length === 0 || sources.length === 1) {\n return true;\n }\n let acc;\n for (const header of sources) {\n const parameters = Object.keys(header);\n if (!acc || acc.size === 0) {\n acc = new Set(parameters);\n continue;\n }\n for (const parameter of parameters) {\n if (acc.has(parameter)) {\n return false;\n }\n acc.add(parameter);\n }\n }\n return true;\n}\n","const isObjectLike = (value) => typeof value === 'object' && value !== null;\nexport function isObject(input) {\n if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {\n return false;\n }\n if (Object.getPrototypeOf(input) === null) {\n return true;\n }\n let proto = input;\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n return Object.getPrototypeOf(input) === proto;\n}\n","export function checkKeyLength(alg, key) {\n if (alg.startsWith('RS') || alg.startsWith('PS')) {\n const { modulusLength } = key.algorithm;\n if (typeof modulusLength !== 'number' || modulusLength < 2048) {\n throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);\n }\n }\n}\n","import { JOSENotSupported } from '../util/errors.js';\nfunction subtleMapping(jwk) {\n let algorithm;\n let keyUsages;\n switch (jwk.kty) {\n case 'AKP': {\n switch (jwk.alg) {\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n algorithm = { name: jwk.alg };\n keyUsages = jwk.priv ? ['sign'] : ['verify'];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'RSA': {\n switch (jwk.alg) {\n case 'PS256':\n case 'PS384':\n case 'PS512':\n algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'RS256':\n case 'RS384':\n case 'RS512':\n algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512':\n algorithm = {\n name: 'RSA-OAEP',\n hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`,\n };\n keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'EC': {\n switch (jwk.alg) {\n case 'ES256':\n algorithm = { name: 'ECDSA', namedCurve: 'P-256' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ES384':\n algorithm = { name: 'ECDSA', namedCurve: 'P-384' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ES512':\n algorithm = { name: 'ECDSA', namedCurve: 'P-521' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n algorithm = { name: 'ECDH', namedCurve: jwk.crv };\n keyUsages = jwk.d ? ['deriveBits'] : [];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'OKP': {\n switch (jwk.alg) {\n case 'Ed25519':\n case 'EdDSA':\n algorithm = { name: 'Ed25519' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n algorithm = { name: jwk.crv };\n keyUsages = jwk.d ? ['deriveBits'] : [];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"kty\" (Key Type) Parameter value');\n }\n return { algorithm, keyUsages };\n}\nexport async function jwkToKey(jwk) {\n if (!jwk.alg) {\n throw new TypeError('\"alg\" argument is required when \"jwk.alg\" is not present');\n }\n const { algorithm, keyUsages } = subtleMapping(jwk);\n const keyData = { ...jwk };\n if (keyData.kty !== 'AKP') {\n delete keyData.alg;\n }\n delete keyData.use;\n return crypto.subtle.importKey('jwk', keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);\n}\n","import { decode as decodeBase64URL } from '../util/base64url.js';\nimport { fromSPKI, fromPKCS8, fromX509 } from '../lib/asn1.js';\nimport { jwkToKey } from '../lib/jwk_to_key.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport { isObject } from '../lib/is_object.js';\nexport async function importSPKI(spki, alg, options) {\n if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {\n throw new TypeError('\"spki\" must be SPKI formatted string');\n }\n return fromSPKI(spki, alg, options);\n}\nexport async function importX509(x509, alg, options) {\n if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {\n throw new TypeError('\"x509\" must be X.509 formatted string');\n }\n return fromX509(x509, alg, options);\n}\nexport async function importPKCS8(pkcs8, alg, options) {\n if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {\n throw new TypeError('\"pkcs8\" must be PKCS#8 formatted string');\n }\n return fromPKCS8(pkcs8, alg, options);\n}\nexport async function importJWK(jwk, alg, options) {\n if (!isObject(jwk)) {\n throw new TypeError('JWK must be an object');\n }\n let ext;\n alg ??= jwk.alg;\n ext ??= options?.extractable ?? jwk.ext;\n switch (jwk.kty) {\n case 'oct':\n if (typeof jwk.k !== 'string' || !jwk.k) {\n throw new TypeError('missing \"k\" (Key Value) Parameter value');\n }\n return decodeBase64URL(jwk.k);\n case 'RSA':\n if ('oth' in jwk && jwk.oth !== undefined) {\n throw new JOSENotSupported('RSA JWK \"oth\" (Other Primes Info) Parameter value is not supported');\n }\n return jwkToKey({ ...jwk, alg, ext });\n case 'AKP': {\n if (typeof jwk.alg !== 'string' || !jwk.alg) {\n throw new TypeError('missing \"alg\" (Algorithm) Parameter value');\n }\n if (alg !== undefined && alg !== jwk.alg) {\n throw new TypeError('JWK alg and alg option value mismatch');\n }\n return jwkToKey({ ...jwk, ext });\n }\n case 'EC':\n case 'OKP':\n return jwkToKey({ ...jwk, alg, ext });\n default:\n throw new JOSENotSupported('Unsupported \"kty\" (Key Type) Parameter value');\n }\n}\n","import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';\nexport function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {\n if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be integrity protected');\n }\n if (!protectedHeader || protectedHeader.crit === undefined) {\n return new Set();\n }\n if (!Array.isArray(protectedHeader.crit) ||\n protectedHeader.crit.length === 0 ||\n protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');\n }\n let recognized;\n if (recognizedOption !== undefined) {\n recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);\n }\n else {\n recognized = recognizedDefault;\n }\n for (const parameter of protectedHeader.crit) {\n if (!recognized.has(parameter)) {\n throw new JOSENotSupported(`Extension Header Parameter \"${parameter}\" is not recognized`);\n }\n if (joseHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" is missing`);\n }\n if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" MUST be integrity protected`);\n }\n }\n return new Set(protectedHeader.crit);\n}\n","export function validateAlgorithms(option, algorithms) {\n if (algorithms !== undefined &&\n (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {\n throw new TypeError(`\"${option}\" option must be an array of strings`);\n }\n if (!algorithms) {\n return undefined;\n }\n return new Set(algorithms);\n}\n","import { isObject } from './is_object.js';\nexport const isJWK = (key) => isObject(key) && typeof key.kty === 'string';\nexport const isPrivateJWK = (key) => key.kty !== 'oct' &&\n ((key.kty === 'AKP' && typeof key.priv === 'string') || typeof key.d === 'string');\nexport const isPublicJWK = (key) => key.kty !== 'oct' && key.d === undefined && key.priv === undefined;\nexport const isSecretJWK = (key) => key.kty === 'oct' && typeof key.k === 'string';\n","import { isJWK } from './is_jwk.js';\nimport { decode } from '../util/base64url.js';\nimport { jwkToKey } from './jwk_to_key.js';\nimport { isCryptoKey, isKeyObject } from './is_key_like.js';\nlet cache;\nconst handleJWK = async (key, jwk, alg, freeze = false) => {\n cache ||= new WeakMap();\n let cached = cache.get(key);\n if (cached?.[alg]) {\n return cached[alg];\n }\n const cryptoKey = await jwkToKey({ ...jwk, alg });\n if (freeze)\n Object.freeze(key);\n if (!cached) {\n cache.set(key, { [alg]: cryptoKey });\n }\n else {\n cached[alg] = cryptoKey;\n }\n return cryptoKey;\n};\nconst handleKeyObject = (keyObject, alg) => {\n cache ||= new WeakMap();\n let cached = cache.get(keyObject);\n if (cached?.[alg]) {\n return cached[alg];\n }\n const isPublic = keyObject.type === 'public';\n const extractable = isPublic ? true : false;\n let cryptoKey;\n if (keyObject.asymmetricKeyType === 'x25519') {\n switch (alg) {\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n break;\n default:\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ['deriveBits']);\n }\n if (keyObject.asymmetricKeyType === 'ed25519') {\n if (alg !== 'EdDSA' && alg !== 'Ed25519') {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [\n isPublic ? 'verify' : 'sign',\n ]);\n }\n switch (keyObject.asymmetricKeyType) {\n case 'ml-dsa-44':\n case 'ml-dsa-65':\n case 'ml-dsa-87': {\n if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [\n isPublic ? 'verify' : 'sign',\n ]);\n }\n }\n if (keyObject.asymmetricKeyType === 'rsa') {\n let hash;\n switch (alg) {\n case 'RSA-OAEP':\n hash = 'SHA-1';\n break;\n case 'RS256':\n case 'PS256':\n case 'RSA-OAEP-256':\n hash = 'SHA-256';\n break;\n case 'RS384':\n case 'PS384':\n case 'RSA-OAEP-384':\n hash = 'SHA-384';\n break;\n case 'RS512':\n case 'PS512':\n case 'RSA-OAEP-512':\n hash = 'SHA-512';\n break;\n default:\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (alg.startsWith('RSA-OAEP')) {\n return keyObject.toCryptoKey({\n name: 'RSA-OAEP',\n hash,\n }, extractable, isPublic ? ['encrypt'] : ['decrypt']);\n }\n cryptoKey = keyObject.toCryptoKey({\n name: alg.startsWith('PS') ? 'RSA-PSS' : 'RSASSA-PKCS1-v1_5',\n hash,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (keyObject.asymmetricKeyType === 'ec') {\n const nist = new Map([\n ['prime256v1', 'P-256'],\n ['secp384r1', 'P-384'],\n ['secp521r1', 'P-521'],\n ]);\n const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);\n if (!namedCurve) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (alg === 'ES256' && namedCurve === 'P-256') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg === 'ES384' && namedCurve === 'P-384') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg === 'ES512' && namedCurve === 'P-521') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg.startsWith('ECDH-ES')) {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDH',\n namedCurve,\n }, extractable, isPublic ? [] : ['deriveBits']);\n }\n }\n if (!cryptoKey) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (!cached) {\n cache.set(keyObject, { [alg]: cryptoKey });\n }\n else {\n cached[alg] = cryptoKey;\n }\n return cryptoKey;\n};\nexport async function normalizeKey(key, alg) {\n if (key instanceof Uint8Array) {\n return key;\n }\n if (isCryptoKey(key)) {\n return key;\n }\n if (isKeyObject(key)) {\n if (key.type === 'secret') {\n return key.export();\n }\n if ('toCryptoKey' in key && typeof key.toCryptoKey === 'function') {\n try {\n return handleKeyObject(key, alg);\n }\n catch (err) {\n if (err instanceof TypeError) {\n throw err;\n }\n }\n }\n let jwk = key.export({ format: 'jwk' });\n return handleJWK(key, jwk, alg);\n }\n if (isJWK(key)) {\n if (key.k) {\n return decode(key.k);\n }\n return handleJWK(key, key, alg, true);\n }\n throw new Error('unreachable');\n}\n","import { withAlg as invalidKeyInput } from './invalid_key_input.js';\nimport { isKeyLike } from './is_key_like.js';\nimport * as jwk from './is_jwk.js';\nconst tag = (key) => key?.[Symbol.toStringTag];\nconst jwkMatchesOp = (alg, key, usage) => {\n if (key.use !== undefined) {\n let expected;\n switch (usage) {\n case 'sign':\n case 'verify':\n expected = 'sig';\n break;\n case 'encrypt':\n case 'decrypt':\n expected = 'enc';\n break;\n }\n if (key.use !== expected) {\n throw new TypeError(`Invalid key for this operation, its \"use\" must be \"${expected}\" when present`);\n }\n }\n if (key.alg !== undefined && key.alg !== alg) {\n throw new TypeError(`Invalid key for this operation, its \"alg\" must be \"${alg}\" when present`);\n }\n if (Array.isArray(key.key_ops)) {\n let expectedKeyOp;\n switch (true) {\n case usage === 'sign' || usage === 'verify':\n case alg === 'dir':\n case alg.includes('CBC-HS'):\n expectedKeyOp = usage;\n break;\n case alg.startsWith('PBES2'):\n expectedKeyOp = 'deriveBits';\n break;\n case /^A\\d{3}(?:GCM)?(?:KW)?$/.test(alg):\n if (!alg.includes('GCM') && alg.endsWith('KW')) {\n expectedKeyOp = usage === 'encrypt' ? 'wrapKey' : 'unwrapKey';\n }\n else {\n expectedKeyOp = usage;\n }\n break;\n case usage === 'encrypt' && alg.startsWith('RSA'):\n expectedKeyOp = 'wrapKey';\n break;\n case usage === 'decrypt':\n expectedKeyOp = alg.startsWith('RSA') ? 'unwrapKey' : 'deriveBits';\n break;\n }\n if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {\n throw new TypeError(`Invalid key for this operation, its \"key_ops\" must include \"${expectedKeyOp}\" when present`);\n }\n }\n return true;\n};\nconst symmetricTypeCheck = (alg, key, usage) => {\n if (key instanceof Uint8Array)\n return;\n if (jwk.isJWK(key)) {\n if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present`);\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));\n }\n if (key.type !== 'secret') {\n throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type \"secret\"`);\n }\n};\nconst asymmetricTypeCheck = (alg, key, usage) => {\n if (jwk.isJWK(key)) {\n switch (usage) {\n case 'decrypt':\n case 'sign':\n if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation must be a private JWK`);\n case 'encrypt':\n case 'verify':\n if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation must be a public JWK`);\n }\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));\n }\n if (key.type === 'secret') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type \"secret\"`);\n }\n if (key.type === 'public') {\n switch (usage) {\n case 'sign':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type \"private\"`);\n case 'decrypt':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type \"private\"`);\n }\n }\n if (key.type === 'private') {\n switch (usage) {\n case 'verify':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type \"public\"`);\n case 'encrypt':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type \"public\"`);\n }\n }\n};\nexport function checkKeyType(alg, key, usage) {\n switch (alg.substring(0, 2)) {\n case 'A1':\n case 'A2':\n case 'di':\n case 'HS':\n case 'PB':\n symmetricTypeCheck(alg, key, usage);\n break;\n default:\n asymmetricTypeCheck(alg, key, usage);\n }\n}\n","import { JOSENotSupported } from '../util/errors.js';\nexport function subtleAlgorithm(alg, algorithm) {\n const hash = `SHA-${alg.slice(-3)}`;\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512':\n return { hash, name: 'HMAC' };\n case 'PS256':\n case 'PS384':\n case 'PS512':\n return { hash, name: 'RSA-PSS', saltLength: parseInt(alg.slice(-3), 10) >> 3 };\n case 'RS256':\n case 'RS384':\n case 'RS512':\n return { hash, name: 'RSASSA-PKCS1-v1_5' };\n case 'ES256':\n case 'ES384':\n case 'ES512':\n return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve };\n case 'Ed25519':\n case 'EdDSA':\n return { name: 'Ed25519' };\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return { name: alg };\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n","import { checkSigCryptoKey } from './crypto_key.js';\nimport { invalidKeyInput } from './invalid_key_input.js';\nexport async function getSigKey(alg, key, usage) {\n if (key instanceof Uint8Array) {\n if (!alg.startsWith('HS')) {\n throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));\n }\n return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]);\n }\n checkSigCryptoKey(key, alg, usage);\n return key;\n}\n","import { subtleAlgorithm } from './subtle_dsa.js';\nimport { checkKeyLength } from './check_key_length.js';\nimport { getSigKey } from './get_sign_verify_key.js';\nexport async function verify(alg, key, signature, data) {\n const cryptoKey = await getSigKey(alg, key, 'verify');\n checkKeyLength(alg, cryptoKey);\n const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);\n try {\n return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);\n }\n catch {\n return false;\n }\n}\n","import { decode as b64u } from '../../util/base64url.js';\nimport { verify } from '../../lib/verify.js';\nimport { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';\nimport { concat, encoder, decoder, encode } from '../../lib/buffer_utils.js';\nimport { isDisjoint } from '../../lib/is_disjoint.js';\nimport { isObject } from '../../lib/is_object.js';\nimport { checkKeyType } from '../../lib/check_key_type.js';\nimport { validateCrit } from '../../lib/validate_crit.js';\nimport { validateAlgorithms } from '../../lib/validate_algorithms.js';\nimport { normalizeKey } from '../../lib/normalize_key.js';\nexport async function flattenedVerify(jws, key, options) {\n if (!isObject(jws)) {\n throw new JWSInvalid('Flattened JWS must be an object');\n }\n if (jws.protected === undefined && jws.header === undefined) {\n throw new JWSInvalid('Flattened JWS must have either of the \"protected\" or \"header\" members');\n }\n if (jws.protected !== undefined && typeof jws.protected !== 'string') {\n throw new JWSInvalid('JWS Protected Header incorrect type');\n }\n if (jws.payload === undefined) {\n throw new JWSInvalid('JWS Payload missing');\n }\n if (typeof jws.signature !== 'string') {\n throw new JWSInvalid('JWS Signature missing or incorrect type');\n }\n if (jws.header !== undefined && !isObject(jws.header)) {\n throw new JWSInvalid('JWS Unprotected Header incorrect type');\n }\n let parsedProt = {};\n if (jws.protected) {\n try {\n const protectedHeader = b64u(jws.protected);\n parsedProt = JSON.parse(decoder.decode(protectedHeader));\n }\n catch {\n throw new JWSInvalid('JWS Protected Header is invalid');\n }\n }\n if (!isDisjoint(parsedProt, jws.header)) {\n throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');\n }\n const joseHeader = {\n ...parsedProt,\n ...jws.header,\n };\n const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, parsedProt, joseHeader);\n let b64 = true;\n if (extensions.has('b64')) {\n b64 = parsedProt.b64;\n if (typeof b64 !== 'boolean') {\n throw new JWSInvalid('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');\n }\n }\n const { alg } = joseHeader;\n if (typeof alg !== 'string' || !alg) {\n throw new JWSInvalid('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');\n }\n const algorithms = options && validateAlgorithms('algorithms', options.algorithms);\n if (algorithms && !algorithms.has(alg)) {\n throw new JOSEAlgNotAllowed('\"alg\" (Algorithm) Header Parameter value not allowed');\n }\n if (b64) {\n if (typeof jws.payload !== 'string') {\n throw new JWSInvalid('JWS Payload must be a string');\n }\n }\n else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {\n throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');\n }\n let resolvedKey = false;\n if (typeof key === 'function') {\n key = await key(parsedProt, jws);\n resolvedKey = true;\n }\n checkKeyType(alg, key, 'verify');\n const data = concat(jws.protected !== undefined ? encode(jws.protected) : new Uint8Array(), encode('.'), typeof jws.payload === 'string'\n ? b64\n ? encode(jws.payload)\n : encoder.encode(jws.payload)\n : jws.payload);\n let signature;\n try {\n signature = b64u(jws.signature);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the signature');\n }\n const k = await normalizeKey(key, alg);\n const verified = await verify(alg, k, signature, data);\n if (!verified) {\n throw new JWSSignatureVerificationFailed();\n }\n let payload;\n if (b64) {\n try {\n payload = b64u(jws.payload);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the payload');\n }\n }\n else if (typeof jws.payload === 'string') {\n payload = encoder.encode(jws.payload);\n }\n else {\n payload = jws.payload;\n }\n const result = { payload };\n if (jws.protected !== undefined) {\n result.protectedHeader = parsedProt;\n }\n if (jws.header !== undefined) {\n result.unprotectedHeader = jws.header;\n }\n if (resolvedKey) {\n return { ...result, key: k };\n }\n return result;\n}\n","import { flattenedVerify } from '../flattened/verify.js';\nimport { JWSInvalid } from '../../util/errors.js';\nimport { decoder } from '../../lib/buffer_utils.js';\nexport async function compactVerify(jws, key, options) {\n if (jws instanceof Uint8Array) {\n jws = decoder.decode(jws);\n }\n if (typeof jws !== 'string') {\n throw new JWSInvalid('Compact JWS must be a string or Uint8Array');\n }\n const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');\n if (length !== 3) {\n throw new JWSInvalid('Invalid Compact JWS');\n }\n const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);\n const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n","import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';\nimport { encoder, decoder } from './buffer_utils.js';\nimport { isObject } from './is_object.js';\nconst epoch = (date) => Math.floor(date.getTime() / 1000);\nconst minute = 60;\nconst hour = minute * 60;\nconst day = hour * 24;\nconst week = day * 7;\nconst year = day * 365.25;\nconst REGEX = /^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;\nexport function secs(str) {\n const matched = REGEX.exec(str);\n if (!matched || (matched[4] && matched[1])) {\n throw new TypeError('Invalid time period format');\n }\n const value = parseFloat(matched[2]);\n const unit = matched[3].toLowerCase();\n let numericDate;\n switch (unit) {\n case 'sec':\n case 'secs':\n case 'second':\n case 'seconds':\n case 's':\n numericDate = Math.round(value);\n break;\n case 'minute':\n case 'minutes':\n case 'min':\n case 'mins':\n case 'm':\n numericDate = Math.round(value * minute);\n break;\n case 'hour':\n case 'hours':\n case 'hr':\n case 'hrs':\n case 'h':\n numericDate = Math.round(value * hour);\n break;\n case 'day':\n case 'days':\n case 'd':\n numericDate = Math.round(value * day);\n break;\n case 'week':\n case 'weeks':\n case 'w':\n numericDate = Math.round(value * week);\n break;\n default:\n numericDate = Math.round(value * year);\n break;\n }\n if (matched[1] === '-' || matched[4] === 'ago') {\n return -numericDate;\n }\n return numericDate;\n}\nfunction validateInput(label, input) {\n if (!Number.isFinite(input)) {\n throw new TypeError(`Invalid ${label} input`);\n }\n return input;\n}\nconst normalizeTyp = (value) => {\n if (value.includes('/')) {\n return value.toLowerCase();\n }\n return `application/${value.toLowerCase()}`;\n};\nconst checkAudiencePresence = (audPayload, audOption) => {\n if (typeof audPayload === 'string') {\n return audOption.includes(audPayload);\n }\n if (Array.isArray(audPayload)) {\n return audOption.some(Set.prototype.has.bind(new Set(audPayload)));\n }\n return false;\n};\nexport function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {\n let payload;\n try {\n payload = JSON.parse(decoder.decode(encodedPayload));\n }\n catch {\n }\n if (!isObject(payload)) {\n throw new JWTInvalid('JWT Claims Set must be a top-level JSON object');\n }\n const { typ } = options;\n if (typ &&\n (typeof protectedHeader.typ !== 'string' ||\n normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {\n throw new JWTClaimValidationFailed('unexpected \"typ\" JWT header value', payload, 'typ', 'check_failed');\n }\n const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;\n const presenceCheck = [...requiredClaims];\n if (maxTokenAge !== undefined)\n presenceCheck.push('iat');\n if (audience !== undefined)\n presenceCheck.push('aud');\n if (subject !== undefined)\n presenceCheck.push('sub');\n if (issuer !== undefined)\n presenceCheck.push('iss');\n for (const claim of new Set(presenceCheck.reverse())) {\n if (!(claim in payload)) {\n throw new JWTClaimValidationFailed(`missing required \"${claim}\" claim`, payload, claim, 'missing');\n }\n }\n if (issuer &&\n !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {\n throw new JWTClaimValidationFailed('unexpected \"iss\" claim value', payload, 'iss', 'check_failed');\n }\n if (subject && payload.sub !== subject) {\n throw new JWTClaimValidationFailed('unexpected \"sub\" claim value', payload, 'sub', 'check_failed');\n }\n if (audience &&\n !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {\n throw new JWTClaimValidationFailed('unexpected \"aud\" claim value', payload, 'aud', 'check_failed');\n }\n let tolerance;\n switch (typeof options.clockTolerance) {\n case 'string':\n tolerance = secs(options.clockTolerance);\n break;\n case 'number':\n tolerance = options.clockTolerance;\n break;\n case 'undefined':\n tolerance = 0;\n break;\n default:\n throw new TypeError('Invalid clockTolerance option type');\n }\n const { currentDate } = options;\n const now = epoch(currentDate || new Date());\n if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {\n throw new JWTClaimValidationFailed('\"iat\" claim must be a number', payload, 'iat', 'invalid');\n }\n if (payload.nbf !== undefined) {\n if (typeof payload.nbf !== 'number') {\n throw new JWTClaimValidationFailed('\"nbf\" claim must be a number', payload, 'nbf', 'invalid');\n }\n if (payload.nbf > now + tolerance) {\n throw new JWTClaimValidationFailed('\"nbf\" claim timestamp check failed', payload, 'nbf', 'check_failed');\n }\n }\n if (payload.exp !== undefined) {\n if (typeof payload.exp !== 'number') {\n throw new JWTClaimValidationFailed('\"exp\" claim must be a number', payload, 'exp', 'invalid');\n }\n if (payload.exp <= now - tolerance) {\n throw new JWTExpired('\"exp\" claim timestamp check failed', payload, 'exp', 'check_failed');\n }\n }\n if (maxTokenAge) {\n const age = now - payload.iat;\n const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);\n if (age - tolerance > max) {\n throw new JWTExpired('\"iat\" claim timestamp check failed (too far in the past)', payload, 'iat', 'check_failed');\n }\n if (age < 0 - tolerance) {\n throw new JWTClaimValidationFailed('\"iat\" claim timestamp check failed (it should be in the past)', payload, 'iat', 'check_failed');\n }\n }\n return payload;\n}\nexport class JWTClaimsBuilder {\n #payload;\n constructor(payload) {\n if (!isObject(payload)) {\n throw new TypeError('JWT Claims Set MUST be an object');\n }\n this.#payload = structuredClone(payload);\n }\n data() {\n return encoder.encode(JSON.stringify(this.#payload));\n }\n get iss() {\n return this.#payload.iss;\n }\n set iss(value) {\n this.#payload.iss = value;\n }\n get sub() {\n return this.#payload.sub;\n }\n set sub(value) {\n this.#payload.sub = value;\n }\n get aud() {\n return this.#payload.aud;\n }\n set aud(value) {\n this.#payload.aud = value;\n }\n set jti(value) {\n this.#payload.jti = value;\n }\n set nbf(value) {\n if (typeof value === 'number') {\n this.#payload.nbf = validateInput('setNotBefore', value);\n }\n else if (value instanceof Date) {\n this.#payload.nbf = validateInput('setNotBefore', epoch(value));\n }\n else {\n this.#payload.nbf = epoch(new Date()) + secs(value);\n }\n }\n set exp(value) {\n if (typeof value === 'number') {\n this.#payload.exp = validateInput('setExpirationTime', value);\n }\n else if (value instanceof Date) {\n this.#payload.exp = validateInput('setExpirationTime', epoch(value));\n }\n else {\n this.#payload.exp = epoch(new Date()) + secs(value);\n }\n }\n set iat(value) {\n if (value === undefined) {\n this.#payload.iat = epoch(new Date());\n }\n else if (value instanceof Date) {\n this.#payload.iat = validateInput('setIssuedAt', epoch(value));\n }\n else if (typeof value === 'string') {\n this.#payload.iat = validateInput('setIssuedAt', epoch(new Date()) + secs(value));\n }\n else {\n this.#payload.iat = validateInput('setIssuedAt', value);\n }\n }\n}\n","import { compactVerify } from '../jws/compact/verify.js';\nimport { validateClaimsSet } from '../lib/jwt_claims_set.js';\nimport { JWTInvalid } from '../util/errors.js';\nexport async function jwtVerify(jwt, key, options) {\n const verified = await compactVerify(jwt, key, options);\n if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {\n throw new JWTInvalid('JWTs MUST NOT use unencoded payload');\n }\n const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);\n const result = { payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n","/**\n * SDK Constants — Single Source of Truth\n *\n * Shared constants used across the SDK. Centralizing these\n * prevents magic number duplication and makes changes easier.\n *\n * IMPORTANT: All time-based constants should be used consistently\n * across the SDK. Never hardcode magic numbers like 30000, 5 * 60 * 1000, etc.\n */\n\n// =============================================================================\n// API Configuration\n// =============================================================================\n\n/** Default platform URL */\nexport const DEFAULT_PLATFORM_URL = 'https://sylphx.com'\n\n/**\n * Canonical environment variable name for the platform URL.\n *\n * SDK modules MUST read from this env var (with SYLPHX_URL as legacy fallback).\n * Centralizing the name prevents the same env var being spelled differently\n * across kv.ts, streams.ts, ai.ts, middleware.ts, and server.ts.\n */\nexport const ENV_PLATFORM_URL = 'SYLPHX_PLATFORM_URL'\n\n/**\n * Legacy environment variable name for the platform URL.\n *\n * Supported as a fallback for older deployments that set SYLPHX_URL.\n * New projects should use SYLPHX_PLATFORM_URL.\n */\nexport const ENV_PLATFORM_URL_LEGACY = 'SYLPHX_URL'\n\n/**\n * Canonical environment variable name for the secret key.\n *\n * All server-side SDK modules read from this env var by default.\n */\nexport const ENV_SECRET_KEY = 'SYLPHX_SECRET_KEY'\n\n/**\n * Resolve the platform URL from environment variables.\n *\n * Priority: explicit value > SYLPHX_PLATFORM_URL > SYLPHX_URL (legacy) > default\n */\nexport function resolvePlatformUrl(explicit?: string): string {\n\treturn (\n\t\texplicit ||\n\t\tprocess.env[ENV_PLATFORM_URL] ||\n\t\tprocess.env[ENV_PLATFORM_URL_LEGACY] ||\n\t\tDEFAULT_PLATFORM_URL\n\t).trim()\n}\n\n/**\n * Resolve the secret key from environment variables.\n *\n * Returns the raw value before validation. Callers should pass the result\n * through `validateAndSanitizeSecretKey()`.\n */\nexport function resolveSecretKey(explicit?: string): string | undefined {\n\treturn explicit || process.env[ENV_SECRET_KEY]\n}\n\n/** @deprecated No longer used for path construction. Use SDK_API_PATH directly. */\nexport const SDK_API_VERSION = 'v1'\n\n/**\n * SDK API base path — legacy path served from main Next.js app.\n *\n * Used when `platformUrl` is set to `https://sylphx.com` (default).\n * Points to the runtime Hono app mounted at /api/app/v1 (via Next.js catch-all).\n *\n * @deprecated Prefer project `ref`-based URL: https://{ref}.api.sylphx.com/v1\n */\nexport const SDK_API_PATH = `/api/app/v1`\n\n/**\n * SDK API path for new subdomain-based SDK server.\n *\n * Used when `ref` is provided to `createConfig`.\n * The full base becomes: https://{ref}.api.sylphx.com + SDK_API_PATH_NEW\n */\nexport const SDK_API_PATH_NEW = `/v1`\n\n/**\n * Default SDK API host for new subdomain-based SDK server.\n * The full URL is built as: https://{ref}.api.sylphx.com/v1\n */\nexport const DEFAULT_SDK_API_HOST = 'api.sylphx.com'\n\n/**\n * Default auth route prefix\n *\n * Used for OAuth callbacks and signout routes.\n * Must match the middleware's authPrefix config.\n */\nexport const DEFAULT_AUTH_PREFIX = '/auth'\n\n/**\n * SDK package version\n *\n * Sent in X-SDK-Version header for debugging and analytics.\n * Update this when releasing new SDK versions.\n */\nexport const SDK_VERSION = '0.1.0'\n\n/**\n * SDK platform identifier\n *\n * Sent in X-SDK-Platform header to identify the runtime environment.\n */\nexport const SDK_PLATFORM =\n\ttypeof window !== 'undefined'\n\t\t? 'browser'\n\t\t: typeof process !== 'undefined' && process.versions?.node\n\t\t\t? 'node'\n\t\t\t: 'unknown'\n\n// =============================================================================\n// Timeouts & Durations\n// =============================================================================\n\n/** Default request timeout in milliseconds (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000\n\n/**\n * Token expiry buffer in milliseconds (30 seconds)\n *\n * Refresh tokens this many milliseconds BEFORE they expire\n * to account for network latency and clock skew.\n */\nexport const TOKEN_EXPIRY_BUFFER_MS = 30_000\n\n/**\n * Session token lifetime in seconds (5 minutes)\n *\n * Matches Clerk's short-lived access token pattern.\n * Used for cookie maxAge and React Query staleTime.\n */\nexport const SESSION_TOKEN_LIFETIME_SECONDS = 5 * 60\n\n/** Session token lifetime in milliseconds (for React Query staleTime) */\nexport const SESSION_TOKEN_LIFETIME_MS = SESSION_TOKEN_LIFETIME_SECONDS * 1000\n\n/**\n * Refresh token lifetime in seconds (30 days)\n *\n * Long-lived token for silent refresh.\n */\nexport const REFRESH_TOKEN_LIFETIME_SECONDS = 30 * 24 * 60 * 60\n\n// =============================================================================\n// Feature Flags Cache\n// =============================================================================\n\n/**\n * Feature flags cache TTL in milliseconds (5 minutes)\n *\n * How long to cache flags before fetching fresh values.\n * Matches LaunchDarkly's default streaming connection behavior.\n */\nexport const FLAGS_CACHE_TTL_MS = 5 * 60 * 1000\n\n/**\n * Feature flags stale-while-revalidate window in milliseconds (1 minute)\n *\n * Allow serving stale flags while fetching fresh values.\n */\nexport const FLAGS_STALE_WHILE_REVALIDATE_MS = 60 * 1000\n\n// =============================================================================\n// Retry & Backoff\n// =============================================================================\n\n/** Maximum retry delay for exponential backoff (30 seconds) */\nexport const MAX_RETRY_DELAY_MS = 30_000\n\n/** Base retry delay for exponential backoff (1 second) */\nexport const BASE_RETRY_DELAY_MS = 1_000\n\n/** Maximum number of retries for network requests */\nexport const MAX_RETRIES = 3\n\n// =============================================================================\n// Analytics\n// =============================================================================\n\n/**\n * Analytics session timeout in milliseconds (30 minutes)\n *\n * After this much inactivity, a new session is started.\n */\nexport const ANALYTICS_SESSION_TIMEOUT_MS = 30 * 60 * 1000\n\n// =============================================================================\n// Webhooks\n// =============================================================================\n\n/**\n * Maximum age for webhook signature validation (5 minutes)\n *\n * Reject webhooks with timestamps older than this.\n */\nexport const WEBHOOK_MAX_AGE_MS = 5 * 60 * 1000\n\n/**\n * Clock skew allowance for webhook validation (30 seconds)\n *\n * Allow timestamps this far in the future.\n */\nexport const WEBHOOK_CLOCK_SKEW_MS = 30 * 1000\n\n// =============================================================================\n// PKCE (OAuth)\n// =============================================================================\n\n/**\n * PKCE code verifier TTL in milliseconds (10 minutes)\n *\n * How long the code verifier is stored during OAuth flow.\n */\nexport const PKCE_CODE_TTL_MS = 10 * 60 * 1000\n\n// =============================================================================\n// Jobs\n// =============================================================================\n\n/**\n * Job dead-letter queue retention in milliseconds (7 days)\n */\nexport const JOBS_DLQ_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000\n\n// =============================================================================\n// Session Replay\n// =============================================================================\n\n/**\n * Maximum session replay recording duration in milliseconds (60 minutes)\n */\nexport const SESSION_REPLAY_MAX_DURATION_MS = 60 * 60 * 1000\n\n/**\n * Session replay upload interval in milliseconds (5 seconds)\n */\nexport const SESSION_REPLAY_UPLOAD_INTERVAL_MS = 5_000\n\n/**\n * Session replay scroll event throttle interval (150 ms)\n */\nexport const SESSION_REPLAY_SCROLL_THROTTLE_MS = 150\n\n/**\n * Session replay media time update throttle interval (800 ms)\n */\nexport const SESSION_REPLAY_MEDIA_THROTTLE_MS = 800\n\n/**\n * Session replay rage click detection window (1 second)\n */\nexport const SESSION_REPLAY_RAGE_CLICK_WINDOW_MS = 1_000\n\n/**\n * Session replay dead click detection timeout (500 ms)\n */\nexport const SESSION_REPLAY_DEAD_CLICK_TIMEOUT_MS = 500\n\n/**\n * Session replay scroll heat detection window (2 seconds)\n */\nexport const SESSION_REPLAY_SCROLL_HEAT_WINDOW_MS = 2_000\n\n/**\n * Session replay status check interval (5 seconds)\n */\nexport const SESSION_REPLAY_STATUS_CHECK_MS = 5_000\n\n// =============================================================================\n// Analytics (Extended)\n// =============================================================================\n\n/**\n * Analytics event flush interval in milliseconds (5 seconds)\n */\nexport const ANALYTICS_FLUSH_INTERVAL_MS = 5_000\n\n/**\n * Analytics maximum text length for autocapture (100 characters)\n */\nexport const ANALYTICS_MAX_TEXT_LENGTH = 100\n\n/**\n * Analytics flush timeout in milliseconds (1 second)\n */\nexport const ANALYTICS_FLUSH_TIMEOUT_MS = 1_000\n\n/**\n * Analytics interval check in milliseconds (1 second)\n */\nexport const ANALYTICS_INTERVAL_CHECK_MS = 1_000\n\n/**\n * Analytics retry base delay in milliseconds (1 second)\n * Exponential backoff: delay = base * 2^retries (with jitter)\n */\nexport const ANALYTICS_RETRY_BASE_DELAY_MS = 1_000\n\n/**\n * Analytics retry max delay in milliseconds (30 seconds)\n */\nexport const ANALYTICS_RETRY_MAX_DELAY_MS = 30_000\n\n/**\n * Analytics retry jitter factor (±20%)\n * Prevents thundering herd when multiple clients retry simultaneously\n */\nexport const ANALYTICS_RETRY_JITTER = 0.2\n\n/**\n * Analytics maximum retries before dropping event (Segment pattern: 10)\n */\nexport const ANALYTICS_MAX_RETRIES = 10\n\n// =============================================================================\n// Feature Flags (Extended)\n// =============================================================================\n\n/**\n * Feature flags exposure deduplication window (1 hour)\n *\n * Prevents duplicate exposure events for A/B tests within this window.\n */\nexport const FLAGS_EXPOSURE_DEDUPE_WINDOW_MS = 60 * 60 * 1000\n\n/**\n * Flag stream initial reconnection delay (1 second)\n */\nexport const FLAGS_STREAM_INITIAL_RECONNECT_MS = 1_000\n\n/**\n * Flag stream maximum reconnection delay (30 seconds)\n */\nexport const FLAGS_STREAM_MAX_RECONNECT_MS = 30_000\n\n/**\n * Flag stream heartbeat timeout (45 seconds)\n */\nexport const FLAGS_STREAM_HEARTBEAT_TIMEOUT_MS = 45_000\n\n/**\n * Flag HTTP polling interval fallback (60 seconds)\n */\nexport const FLAGS_HTTP_POLLING_INTERVAL_MS = 60_000\n\n// =============================================================================\n// Jobs (Extended)\n// =============================================================================\n\n/**\n * Default retry delay sequence for exponential backoff (ms)\n */\nexport const DEFAULT_RETRY_DELAYS_MS = [1_000, 5_000, 15_000, 30_000, 60_000] as const\n\n/**\n * Default job timeout in milliseconds (60 seconds)\n */\nexport const JOB_DEFAULT_TIMEOUT_MS = 60_000\n\n/**\n * Default job status polling interval (2 seconds)\n */\nexport const JOB_POLL_INTERVAL_MS = 2_000\n\n// =============================================================================\n// Storage Keys & Prefixes\n// =============================================================================\n\n/**\n * Storage key prefix for SDK data\n */\nexport const STORAGE_KEY_PREFIX = 'sylphx_'\n\n/**\n * localStorage key for cached feature flags\n */\nexport const FLAGS_CACHE_KEY = 'sylphx_feature_flags'\n\n/**\n * localStorage key for feature flags cache timestamp\n */\nexport const FLAGS_CACHE_TIMESTAMP_KEY = 'sylphx_feature_flags_ts'\n\n/**\n * localStorage key for feature flags overrides\n */\nexport const FLAGS_OVERRIDES_KEY = 'sylphx_feature_flags_overrides'\n\n/**\n * localStorage key for active organization\n */\nexport const ORG_STORAGE_KEY = 'sylphx_active_org'\n\n/**\n * BroadcastChannel name for cross-tab org sync\n */\nexport const ORG_BROADCAST_CHANNEL = 'sylphx_org_sync'\n\n/**\n * Storage prefix for PKCE verifiers\n */\nexport const PKCE_STORAGE_PREFIX = 'sylphx_pkce_'\n\n/**\n * Test key for checking storage availability\n */\nexport const STORAGE_TEST_KEY = '__sylphx_test__'\n\n/**\n * Cookie/storage name for analytics sessions\n */\nexport const ANALYTICS_SESSION_KEY = 'sylphx_session'\n\n/**\n * Default storage key for flags persistence\n */\nexport const FLAGS_STORAGE_KEY = 'sylphx_flags'\n\n// =============================================================================\n// Click ID & Attribution\n// =============================================================================\n\n/**\n * Click ID attribution window in milliseconds (90 days)\n *\n * How long click IDs are stored for conversion attribution.\n */\nexport const CLICK_ID_EXPIRY_MS = 90 * 24 * 60 * 60 * 1000\n\n// =============================================================================\n// React Query Stale Times\n// =============================================================================\n\n/**\n * React Query staleTime for frequently-changing data (1 minute)\n *\n * Use for: real-time metrics, live feeds, active sessions\n */\nexport const STALE_TIME_FREQUENT_MS = 60 * 1_000\n\n/**\n * React Query staleTime for moderately-changing data (2 minutes)\n *\n * Use for: subscriptions, user profiles, preferences\n */\nexport const STALE_TIME_MODERATE_MS = 2 * 60 * 1_000\n\n/**\n * React Query staleTime for stable/config data (5 minutes)\n *\n * Use for: plans, feature flags, app config\n */\nexport const STALE_TIME_STABLE_MS = 5 * 60 * 1_000\n\n/**\n * React Query staleTime for webhook stats (30 seconds)\n */\nexport const STALE_TIME_STATS_MS = 30 * 1_000\n\n// =============================================================================\n// UI Component Timeouts\n// =============================================================================\n\n/**\n * Copy-to-clipboard feedback display duration (2 seconds)\n */\nexport const UI_COPY_FEEDBACK_MS = 2_000\n\n/**\n * Form success message display duration (3 seconds)\n */\nexport const UI_FORM_SUCCESS_MS = 3_000\n\n/**\n * General notification display duration (5 seconds)\n */\nexport const UI_NOTIFICATION_MS = 5_000\n\n/**\n * Prompt auto-show delay (3 seconds)\n */\nexport const UI_PROMPT_DELAY_MS = 3_000\n\n/**\n * Redirect delay after action (3 seconds)\n */\nexport const UI_REDIRECT_DELAY_MS = 3_000\n\n/**\n * Animation out duration (200 ms)\n */\nexport const UI_ANIMATION_OUT_MS = 200\n\n/**\n * Animation in duration (300 ms)\n */\nexport const UI_ANIMATION_IN_MS = 300\n\n// =============================================================================\n// Email & Verification\n// =============================================================================\n\n/**\n * Email resend cooldown tick interval (1 second)\n */\nexport const EMAIL_RESEND_COOLDOWN_TICK_MS = 1_000\n\n/**\n * New user detection threshold (1 minute)\n *\n * Users created within this window are considered \"new\" for signup tracking.\n */\nexport const NEW_USER_THRESHOLD_MS = 60 * 1_000\n\n// =============================================================================\n// Web Vitals Thresholds\n// =============================================================================\n\n/**\n * FCP (First Contentful Paint) \"good\" threshold (1800 ms)\n */\nexport const WEB_VITALS_FCP_GOOD_MS = 1_800\n\n/**\n * FCP (First Contentful Paint) \"poor\" threshold (3000 ms)\n */\nexport const WEB_VITALS_FCP_POOR_MS = 3_000\n\n// =============================================================================\n// Storage Sizes\n// =============================================================================\n\n/**\n * Multipart upload threshold (5 MB)\n *\n * Files larger than this use multipart upload for better reliability.\n */\nexport const STORAGE_MULTIPART_THRESHOLD_BYTES = 5 * 1024 * 1024\n\n/**\n * Default max file size for uploads (5 MB)\n */\nexport const STORAGE_DEFAULT_MAX_SIZE_BYTES = 5 * 1024 * 1024\n\n/**\n * Avatar max file size (2 MB)\n */\nexport const STORAGE_AVATAR_MAX_SIZE_BYTES = 2 * 1024 * 1024\n\n/**\n * Large file max size for file uploads (10 MB)\n */\nexport const STORAGE_LARGE_MAX_SIZE_BYTES = 10 * 1024 * 1024\n\n// =============================================================================\n// Cache TTLs\n// =============================================================================\n\n/**\n * JWK cache TTL (1 hour)\n */\nexport const JWK_CACHE_TTL_MS = 60 * 60 * 1000\n\n// =============================================================================\n// Analytics Event Tracking\n// =============================================================================\n\n/**\n * Max tracked event IDs to keep in memory\n */\nexport const ANALYTICS_MAX_TRACKED_EVENT_IDS = 1000\n\n/**\n * Number of event IDs to keep after cleanup\n */\nexport const ANALYTICS_TRACKED_IDS_KEEP = 500\n\n/**\n * Analytics queue limit before force flush\n */\nexport const ANALYTICS_QUEUE_LIMIT = 100\n\n// =============================================================================\n// Session Replay (Extended)\n// =============================================================================\n\n/**\n * Session replay check interval (1 second)\n */\nexport const SESSION_REPLAY_CHECK_INTERVAL_MS = 1_000\n\n/**\n * Success feedback delay for invite/account actions (1.5 seconds)\n */\nexport const UI_SUCCESS_REDIRECT_MS = 1_500\n\n// =============================================================================\n// String Truncation Limits\n// =============================================================================\n\n/**\n * Max message length for logging (1000 chars)\n */\nexport const LOG_MESSAGE_MAX_LENGTH = 1_000\n\n/**\n * Max DOM snapshot length for debugging (1000 chars)\n */\nexport const DOM_SNAPSHOT_MAX_LENGTH = 1_000\n\n/**\n * Max stack trace length for error tracking (500 chars)\n */\nexport const STACK_TRACE_MAX_LENGTH = 500\n\n/**\n * Google Consent Mode wait for update timeout (500 ms)\n */\nexport const CONSENT_WAIT_FOR_UPDATE_MS = 500\n\n// =============================================================================\n// Time Unit Conversions\n// =============================================================================\n\n/** Milliseconds per minute (60,000) */\nexport const MS_PER_MINUTE = 60_000\n\n/** Milliseconds per hour (3,600,000) */\nexport const MS_PER_HOUR = 3_600_000\n\n/** Milliseconds per day (86,400,000) */\nexport const MS_PER_DAY = 86_400_000\n\n/** Seconds per minute (60) */\nexport const SECONDS_PER_MINUTE = 60\n\n/** Seconds per hour (3,600) */\nexport const SECONDS_PER_HOUR = 3_600\n\n// =============================================================================\n// Z-Index Values\n// =============================================================================\n\n/** Z-index for modal overlays (9999) */\nexport const Z_INDEX_OVERLAY = 9999\n\n/** Z-index for critical overlays like feature gates (99999) */\nexport const Z_INDEX_CRITICAL_OVERLAY = 99999\n\n// =============================================================================\n// API Key Expiry (seconds)\n// =============================================================================\n\n/** API key expiry: 1 day (86,400 seconds) */\nexport const API_KEY_EXPIRY_1_DAY = 86_400\n\n/** API key expiry: 7 days (604,800 seconds) */\nexport const API_KEY_EXPIRY_7_DAYS = 604_800\n\n/** API key expiry: 30 days (2,592,000 seconds) */\nexport const API_KEY_EXPIRY_30_DAYS = 2_592_000\n\n/** API key expiry: 90 days (7,776,000 seconds) */\nexport const API_KEY_EXPIRY_90_DAYS = 7_776_000\n\n/** API key expiry: 1 year (31,536,000 seconds) */\nexport const API_KEY_EXPIRY_1_YEAR = 31_536_000\n\n// =============================================================================\n// Web Vitals Thresholds (Google standards)\n// =============================================================================\n\n/** LCP (Largest Contentful Paint) \"good\" threshold (2500 ms) */\nexport const WEB_VITALS_LCP_GOOD_MS = 2_500\n\n/** LCP (Largest Contentful Paint) \"poor\" threshold (4000 ms) */\nexport const WEB_VITALS_LCP_POOR_MS = 4_000\n\n/** INP (Interaction to Next Paint) \"good\" threshold (200 ms) */\nexport const WEB_VITALS_INP_GOOD_MS = 200\n\n/** INP (Interaction to Next Paint) \"poor\" threshold (500 ms) */\nexport const WEB_VITALS_INP_POOR_MS = 500\n\n/** TTFB (Time to First Byte) \"good\" threshold (800 ms) */\nexport const WEB_VITALS_TTFB_GOOD_MS = 800\n\n/** TTFB (Time to First Byte) \"poor\" threshold (1800 ms) */\nexport const WEB_VITALS_TTFB_POOR_MS = 1_800\n\n// =============================================================================\n// Security\n// =============================================================================\n\n/** Minimum password length (NIST SP 800-63B recommends 12+) */\nexport const MIN_PASSWORD_LENGTH = 12\n\n// =============================================================================\n// AI\n// =============================================================================\n\n/** Default context window for AI models (4096 tokens) */\nexport const DEFAULT_CONTEXT_WINDOW = 4_096\n\n// =============================================================================\n// Circuit Breaker (AWS/Resilience4j pattern)\n// =============================================================================\n\n/**\n * Circuit breaker failure threshold\n *\n * Number of failures in the window before circuit opens.\n */\nexport const CIRCUIT_BREAKER_FAILURE_THRESHOLD = 5\n\n/**\n * Circuit breaker failure window in milliseconds (10 seconds)\n *\n * Time window for counting failures.\n */\nexport const CIRCUIT_BREAKER_WINDOW_MS = 10_000\n\n/**\n * Circuit breaker open duration in milliseconds (30 seconds)\n *\n * How long the circuit stays open before allowing a test request.\n */\nexport const CIRCUIT_BREAKER_OPEN_DURATION_MS = 30_000\n\n// =============================================================================\n// ETag Cache (HTTP conditional requests)\n// =============================================================================\n\n/**\n * Maximum ETag cache entries\n *\n * LRU eviction when exceeded.\n */\nexport const ETAG_CACHE_MAX_ENTRIES = 100\n\n/**\n * ETag cache TTL in milliseconds (5 minutes)\n *\n * How long cached responses are valid.\n */\nexport const ETAG_CACHE_TTL_MS = 5 * 60 * 1000\n","/**\n * REST Client for Sylphx Platform\n *\n * Type-safe REST API client using openapi-fetch with full type inference\n * from OpenAPI specification. No tRPC dependencies.\n *\n * @example\n * ```typescript\n * import { createRestClient } from '@sylphx/sdk'\n *\n * const client = createRestClient({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * // Full type inference from OpenAPI\n * const { data: user } = await client.GET('/auth/me')\n * const { data: plans } = await client.GET('/billing/plans')\n * const { data: result } = await client.POST('/auth/login', {\n * body: { email, password }\n * })\n * ```\n */\n\nimport createClient, { type Middleware } from \"openapi-fetch\";\nimport {\n\tBASE_RETRY_DELAY_MS,\n\tCIRCUIT_BREAKER_FAILURE_THRESHOLD,\n\tCIRCUIT_BREAKER_OPEN_DURATION_MS,\n\tCIRCUIT_BREAKER_WINDOW_MS,\n\tDEFAULT_PLATFORM_URL,\n\tDEFAULT_TIMEOUT_MS,\n\tETAG_CACHE_MAX_ENTRIES,\n\tETAG_CACHE_TTL_MS,\n\tMAX_RETRY_DELAY_MS,\n\tSDK_API_PATH,\n\tSDK_PLATFORM,\n\tSDK_VERSION,\n} from \"./constants\";\nimport { exponentialBackoff, isRetryableError } from \"./errors\";\nimport type { paths } from \"./generated/api\";\nimport { validateAndSanitizeSecretKey } from \"./key-validation\";\n\n// Re-export types for consumers\nexport type { paths };\n\n/**\n * Retry configuration for automatic request retries\n */\nexport interface RetryConfig {\n\t/** Maximum number of retries (default: 3) */\n\tmaxRetries?: number;\n\t/** Base delay in milliseconds (default: 1000) */\n\tbaseDelay?: number;\n\t/** Maximum delay in milliseconds (default: 30000) */\n\tmaxDelay?: number;\n\t/** Custom function to determine if error is retryable */\n\tshouldRetry?: (status: number, attempt: number) => boolean;\n\t/** Request timeout in milliseconds (default: 30000) */\n\ttimeout?: number;\n}\n\n/**\n * Request deduplication configuration\n */\nexport interface DeduplicationConfig {\n\t/** Enable request deduplication (default: true) */\n\tenabled?: boolean;\n\t/** HTTP methods to deduplicate (default: ['GET']) */\n\tmethods?: (\"GET\" | \"POST\" | \"PUT\" | \"DELETE\")[];\n}\n\n/**\n * Circuit breaker configuration (AWS/Resilience4j pattern)\n *\n * Prevents cascade failures by fast-failing when service is unhealthy.\n * States: CLOSED (normal) → OPEN (failing) → HALF_OPEN (testing)\n */\nexport interface CircuitBreakerConfig {\n\t/** Enable circuit breaker (default: true) */\n\tenabled?: boolean;\n\t/** Number of failures before opening circuit (default: 5) */\n\tfailureThreshold?: number;\n\t/** Time window for counting failures in ms (default: 10000) */\n\twindowMs?: number;\n\t/** How long circuit stays open in ms (default: 30000) */\n\topenDurationMs?: number;\n\t/** Custom function to determine if response is a failure */\n\tisFailure?: (status: number) => boolean;\n}\n\n/**\n * ETag/Conditional request configuration (HTTP caching pattern)\n *\n * Enables HTTP conditional requests with If-None-Match header\n * to avoid re-downloading unchanged data (saves bandwidth).\n */\nexport interface ETagConfig {\n\t/** Enable ETag caching (default: true for GET requests) */\n\tenabled?: boolean;\n\t/** Maximum cache entries (default: 100) */\n\tmaxEntries?: number;\n\t/** Cache TTL in milliseconds (default: 5 minutes) */\n\tttlMs?: number;\n}\n\n/**\n * Configuration for the REST client\n *\n * The app key identifies the app — no separate app ID needed.\n */\nexport interface RestClientConfig {\n\t/**\n\t * Your app key — identifies the app and environment.\n\t *\n\t * Accepts either:\n\t * - Secret key (sk_dev_, sk_stg_, sk_prod_) — full access, server-side only\n\t * - Publishable key (app_dev_, app_stg_, app_prod_) — limited access, safe for client\n\t */\n\tsecretKey: string;\n\t/** Platform URL (default: https://sylphx.com) */\n\tplatformUrl?: string;\n\t/** Retry configuration (default: 3 retries with exponential backoff) */\n\tretry?: RetryConfig | false;\n\t/**\n\t * Request deduplication configuration (default: enabled for GET)\n\t *\n\t * Prevents duplicate concurrent requests for the same resource.\n\t * When multiple components request the same data simultaneously,\n\t * only one API call is made and the result is shared.\n\t */\n\tdeduplication?: DeduplicationConfig | false;\n\t/**\n\t * Circuit breaker configuration (default: enabled)\n\t *\n\t * Prevents cascade failures by fast-failing when service is unhealthy.\n\t * Opens after 5 failures in 10s, stays open for 30s, then allows test request.\n\t */\n\tcircuitBreaker?: CircuitBreakerConfig | false;\n\t/**\n\t * ETag caching configuration (default: enabled for GET)\n\t *\n\t * Uses HTTP conditional requests to avoid re-downloading unchanged data.\n\t * Saves bandwidth by returning 304 Not Modified when content hasn't changed.\n\t */\n\tetag?: ETagConfig | false;\n}\n\n/**\n * Dynamic configuration that can change at runtime (e.g., access token)\n */\nexport interface RestDynamicConfig {\n\t/** Your secret key (sk_* or app_*) — identifies the app */\n\tsecretKey?: string;\n\t/** Platform URL (default: https://sylphx.com) */\n\tplatformUrl?: string;\n\t/** Get the current access token (called on each request) */\n\tgetAccessToken?: () => string | null | undefined;\n\t/** Retry configuration (default: 3 retries with exponential backoff) */\n\tretry?: RetryConfig | false;\n\t/** Request deduplication configuration (default: enabled for GET) */\n\tdeduplication?: DeduplicationConfig | false;\n\t/** Circuit breaker configuration (default: enabled) */\n\tcircuitBreaker?: CircuitBreakerConfig | false;\n\t/** ETag caching configuration (default: enabled for GET) */\n\tetag?: ETagConfig | false;\n}\n\n/**\n * Create auth middleware that adds app credentials, access token, and SDK headers\n */\nfunction createAuthMiddleware(config: RestDynamicConfig): Middleware {\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\t// Add SDK identification headers for debugging and analytics\n\t\t\trequest.headers.set(\"X-SDK-Version\", SDK_VERSION);\n\t\t\trequest.headers.set(\"X-SDK-Platform\", SDK_PLATFORM);\n\n\t\t\t// Add secret key if provided — identifies the app\n\t\t\tif (config.secretKey) {\n\t\t\t\trequest.headers.set(\"x-app-secret\", config.secretKey);\n\t\t\t}\n\n\t\t\t// Add access token if available\n\t\t\tconst token = config.getAccessToken?.();\n\t\t\tif (token) {\n\t\t\t\trequest.headers.set(\"Authorization\", `Bearer ${token}`);\n\t\t\t}\n\n\t\t\treturn request;\n\t\t},\n\t};\n}\n\n/**\n * Check if a status code is retryable\n */\nfunction isRetryableStatus(status: number): boolean {\n\treturn status >= 500 || status === 429;\n}\n\n// ============================================================================\n// Request Deduplication (React Query/SWR pattern)\n// ============================================================================\n\n/**\n * In-flight request tracking for deduplication\n *\n * When the same request is made multiple times concurrently,\n * we return the existing promise instead of making a new request.\n * This prevents duplicate API calls and improves efficiency.\n */\nconst inFlightRequests = new Map<string, Promise<Response>>();\n\n/**\n * Generate a unique key for a request (for deduplication)\n */\nasync function getRequestKey(request: Request): Promise<string> {\n\tconst body = request.body ? await request.clone().text() : \"\";\n\treturn `${request.method}:${request.url}:${body}`;\n}\n\n/**\n * Create request deduplication middleware (React Query/SWR pattern)\n *\n * Features:\n * - Deduplicates concurrent identical requests\n * - Only applies to GET requests by default (safe to dedupe)\n * - POST/PUT/DELETE are always executed (mutations must run)\n * - Cleans up in-flight tracking after completion\n *\n * @param config - Whether to enable deduplication (default: GET only)\n */\nfunction createDeduplicationMiddleware(\n\tconfig: {\n\t\tenabled?: boolean;\n\t\tmethods?: (\"GET\" | \"POST\" | \"PUT\" | \"DELETE\")[];\n\t} = {},\n): Middleware {\n\tconst { enabled = true, methods = [\"GET\"] } = config;\n\n\tif (!enabled) {\n\t\treturn {\n\t\t\tasync onRequest({ request }) {\n\t\t\t\treturn request;\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\t// Only dedupe specified methods (default: GET only)\n\t\t\tif (!methods.includes(request.method as \"GET\")) {\n\t\t\t\treturn request;\n\t\t\t}\n\n\t\t\tconst key = await getRequestKey(request);\n\n\t\t\t// Check if there's an in-flight request\n\t\t\tconst existing = inFlightRequests.get(key);\n\t\t\tif (existing) {\n\t\t\t\t// Return a new Request that will be handled specially in onResponse\n\t\t\t\tconst deduped = request.clone();\n\t\t\t\t(deduped as unknown as { _dedupKey: string })._dedupKey = key;\n\t\t\t\treturn deduped;\n\t\t\t}\n\t\t\t// Mark request key (so onResponse knows to track it)\n\t\t\t(request as unknown as { _dedupKey: string })._dedupKey = key;\n\t\t\treturn request;\n\t\t},\n\t\tasync onResponse({ request, response }) {\n\t\t\tconst key = (request as unknown as { _dedupKey?: string })._dedupKey;\n\t\t\tif (!key) return response;\n\n\t\t\t// If there's already an in-flight request, wait for it\n\t\t\tconst existing = inFlightRequests.get(key);\n\t\t\tif (existing && inFlightRequests.get(key) !== undefined) {\n\t\t\t\t// Another request is in flight, clone its response\n\t\t\t\tconst cachedResponse = await existing;\n\t\t\t\treturn cachedResponse.clone();\n\t\t\t}\n\n\t\t\t// This is the first request, track it\n\t\t\tconst responsePromise = Promise.resolve(response.clone());\n\t\t\tinFlightRequests.set(key, responsePromise);\n\n\t\t\t// Clean up after response is consumed\n\t\t\tresponsePromise.finally(() => {\n\t\t\t\t// Small delay to allow concurrent requests to find the cached response\n\t\t\t\tsetTimeout(() => inFlightRequests.delete(key), 100);\n\t\t\t});\n\n\t\t\treturn response;\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Circuit Breaker (AWS/Resilience4j pattern)\n// ============================================================================\n\n/**\n * Circuit breaker state machine\n *\n * CLOSED: Normal operation, requests pass through\n * OPEN: Service unhealthy, all requests fast-fail\n * HALF_OPEN: Testing recovery, allows one request\n */\nexport type CircuitState = \"CLOSED\" | \"OPEN\" | \"HALF_OPEN\";\n\n/**\n * Error thrown when circuit is open\n */\nexport class CircuitBreakerOpenError extends Error {\n\treadonly remainingMs: number;\n\n\tconstructor(remainingMs: number) {\n\t\tsuper(\n\t\t\t`Circuit breaker is open. Retry after ${Math.ceil(remainingMs / 1000)}s`,\n\t\t);\n\t\tthis.name = \"CircuitBreakerOpenError\";\n\t\tthis.remainingMs = remainingMs;\n\t}\n}\n\n/**\n * Circuit breaker instance with state management\n */\ninterface CircuitBreaker {\n\tstate: CircuitState;\n\tfailures: number[];\n\topenedAt: number | null;\n\tconfig: Required<CircuitBreakerConfig>;\n}\n\n/**\n * Global circuit breaker instance (shared across requests)\n */\nlet circuitBreaker: CircuitBreaker | null = null;\n\n/**\n * Get or create the circuit breaker instance\n */\nfunction getCircuitBreaker(config: CircuitBreakerConfig = {}): CircuitBreaker {\n\tif (!circuitBreaker) {\n\t\tcircuitBreaker = {\n\t\t\tstate: \"CLOSED\",\n\t\t\tfailures: [],\n\t\t\topenedAt: null,\n\t\t\tconfig: {\n\t\t\t\tenabled: config.enabled ?? true,\n\t\t\t\tfailureThreshold:\n\t\t\t\t\tconfig.failureThreshold ?? CIRCUIT_BREAKER_FAILURE_THRESHOLD,\n\t\t\t\twindowMs: config.windowMs ?? CIRCUIT_BREAKER_WINDOW_MS,\n\t\t\t\topenDurationMs:\n\t\t\t\t\tconfig.openDurationMs ?? CIRCUIT_BREAKER_OPEN_DURATION_MS,\n\t\t\t\tisFailure:\n\t\t\t\t\tconfig.isFailure ?? ((status) => status >= 500 || status === 429),\n\t\t\t},\n\t\t};\n\t}\n\treturn circuitBreaker;\n}\n\n/**\n * Record a failure and potentially open the circuit\n */\nfunction recordFailure(cb: CircuitBreaker): void {\n\tconst now = Date.now();\n\n\t// Remove old failures outside the window\n\tcb.failures = cb.failures.filter((t) => now - t < cb.config.windowMs);\n\n\t// Add new failure\n\tcb.failures.push(now);\n\n\t// Check if threshold exceeded\n\tif (cb.failures.length >= cb.config.failureThreshold) {\n\t\tcb.state = \"OPEN\";\n\t\tcb.openedAt = now;\n\t}\n}\n\n/**\n * Record a success and potentially close the circuit\n */\nfunction recordSuccess(cb: CircuitBreaker): void {\n\tif (cb.state === \"HALF_OPEN\") {\n\t\t// Test request succeeded, close the circuit\n\t\tcb.state = \"CLOSED\";\n\t\tcb.failures = [];\n\t\tcb.openedAt = null;\n\t}\n}\n\n/**\n * Check if circuit should allow request\n */\nfunction shouldAllowRequest(cb: CircuitBreaker): {\n\tallowed: boolean;\n\tremainingMs?: number;\n} {\n\tconst now = Date.now();\n\n\tswitch (cb.state) {\n\t\tcase \"CLOSED\":\n\t\t\treturn { allowed: true };\n\n\t\tcase \"OPEN\": {\n\t\t\tconst elapsed = now - (cb.openedAt ?? now);\n\t\t\tif (elapsed >= cb.config.openDurationMs) {\n\t\t\t\t// Timeout expired, transition to half-open\n\t\t\t\tcb.state = \"HALF_OPEN\";\n\t\t\t\treturn { allowed: true };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\tremainingMs: cb.config.openDurationMs - elapsed,\n\t\t\t};\n\t\t}\n\n\t\tcase \"HALF_OPEN\":\n\t\t\t// Only allow one test request at a time\n\t\t\t// In production, you'd use a flag to track if test is in progress\n\t\t\treturn { allowed: true };\n\n\t\tdefault:\n\t\t\treturn { allowed: true };\n\t}\n}\n\n/**\n * Create circuit breaker middleware (AWS/Resilience4j pattern)\n *\n * Features:\n * - Fast-fails when service is unhealthy (prevents cascade failures)\n * - Auto-recovery with half-open state for testing\n * - Configurable failure threshold and timeout\n * - Only counts server errors (5xx) and rate limits (429)\n */\nfunction createCircuitBreakerMiddleware(\n\tconfig: CircuitBreakerConfig | false | undefined,\n): Middleware {\n\tif (config === false) {\n\t\treturn {\n\t\t\tasync onRequest({ request }) {\n\t\t\t\treturn request;\n\t\t\t},\n\t\t};\n\t}\n\n\tconst cb = getCircuitBreaker(config ?? {});\n\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\tif (!cb.config.enabled) {\n\t\t\t\treturn request;\n\t\t\t}\n\n\t\t\tconst check = shouldAllowRequest(cb);\n\t\t\tif (!check.allowed) {\n\t\t\t\tthrow new CircuitBreakerOpenError(check.remainingMs!);\n\t\t\t}\n\n\t\t\treturn request;\n\t\t},\n\t\tasync onResponse({ response }) {\n\t\t\tif (!cb.config.enabled) {\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tif (cb.config.isFailure(response.status)) {\n\t\t\t\trecordFailure(cb);\n\t\t\t} else {\n\t\t\t\trecordSuccess(cb);\n\t\t\t}\n\n\t\t\treturn response;\n\t\t},\n\t};\n}\n\n/**\n * Reset circuit breaker state (for testing)\n */\nexport function resetCircuitBreaker(): void {\n\tcircuitBreaker = null;\n}\n\n/**\n * Get current circuit breaker state (for monitoring)\n */\nexport function getCircuitBreakerState(): {\n\tstate: CircuitState;\n\tfailures: number;\n\topenedAt: number | null;\n} | null {\n\tif (!circuitBreaker) return null;\n\treturn {\n\t\tstate: circuitBreaker.state,\n\t\tfailures: circuitBreaker.failures.length,\n\t\topenedAt: circuitBreaker.openedAt,\n\t};\n}\n\n// ============================================================================\n// ETag Cache (HTTP conditional requests)\n// ============================================================================\n\n/**\n * Cached response entry with ETag\n */\ninterface ETagCacheEntry {\n\tetag: string;\n\tbody: string;\n\ttimestamp: number;\n}\n\n/**\n * ETag cache with LRU eviction\n */\nconst etagCache = new Map<string, ETagCacheEntry>();\n\n/**\n * Generate cache key for request\n */\nfunction getETagCacheKey(request: Request): string {\n\treturn `${request.method}:${request.url}`;\n}\n\n/**\n * Evict oldest entries when cache is full\n */\nfunction evictOldEntries(maxEntries: number, ttlMs: number): void {\n\tconst now = Date.now();\n\n\t// First, remove expired entries\n\tfor (const [key, entry] of etagCache) {\n\t\tif (now - entry.timestamp > ttlMs) {\n\t\t\tetagCache.delete(key);\n\t\t}\n\t}\n\n\t// If still over limit, remove oldest entries (LRU)\n\tif (etagCache.size > maxEntries) {\n\t\tconst entries = Array.from(etagCache.entries());\n\t\tentries.sort((a, b) => a[1].timestamp - b[1].timestamp);\n\n\t\tconst toRemove = entries.slice(0, entries.length - maxEntries);\n\t\tfor (const [key] of toRemove) {\n\t\t\tetagCache.delete(key);\n\t\t}\n\t}\n}\n\n/**\n * Create ETag middleware for HTTP conditional requests\n *\n * Features:\n * - Caches responses with ETag headers\n * - Sends If-None-Match on subsequent requests\n * - Returns cached response on 304 Not Modified\n * - LRU eviction when cache is full\n * - TTL-based expiration\n */\nfunction createETagMiddleware(\n\tconfig: ETagConfig | false | undefined,\n): Middleware {\n\tif (config === false) {\n\t\treturn {\n\t\t\tasync onRequest({ request }) {\n\t\t\t\treturn request;\n\t\t\t},\n\t\t};\n\t}\n\n\tconst {\n\t\tenabled = true,\n\t\tmaxEntries = ETAG_CACHE_MAX_ENTRIES,\n\t\tttlMs = ETAG_CACHE_TTL_MS,\n\t} = config ?? {};\n\n\tif (!enabled) {\n\t\treturn {\n\t\t\tasync onRequest({ request }) {\n\t\t\t\treturn request;\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\t// Only cache GET requests\n\t\t\tif (request.method !== \"GET\") {\n\t\t\t\treturn request;\n\t\t\t}\n\n\t\t\tconst cacheKey = getETagCacheKey(request);\n\t\t\tconst cached = etagCache.get(cacheKey);\n\n\t\t\tif (cached) {\n\t\t\t\t// Check TTL\n\t\t\t\tif (Date.now() - cached.timestamp > ttlMs) {\n\t\t\t\t\tetagCache.delete(cacheKey);\n\t\t\t\t} else {\n\t\t\t\t\t// Add If-None-Match header\n\t\t\t\t\trequest.headers.set(\"If-None-Match\", cached.etag);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn request;\n\t\t},\n\t\tasync onResponse({ request, response }) {\n\t\t\t// Only cache GET requests\n\t\t\tif (request.method !== \"GET\") {\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tconst cacheKey = getETagCacheKey(request);\n\n\t\t\t// Handle 304 Not Modified\n\t\t\tif (response.status === 304) {\n\t\t\t\tconst cached = etagCache.get(cacheKey);\n\t\t\t\tif (cached) {\n\t\t\t\t\t// Update timestamp (LRU)\n\t\t\t\t\tcached.timestamp = Date.now();\n\n\t\t\t\t\t// Return cached response with original body\n\t\t\t\t\treturn new Response(cached.body, {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\theaders: response.headers,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// No cache, return original response\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\t// Cache successful responses with ETag\n\t\t\tif (response.ok) {\n\t\t\t\tconst etag = response.headers.get(\"ETag\");\n\t\t\t\tif (etag) {\n\t\t\t\t\t// Clone response to read body (can only read once)\n\t\t\t\t\tconst cloned = response.clone();\n\t\t\t\t\tconst body = await cloned.text();\n\n\t\t\t\t\t// Evict old entries if needed\n\t\t\t\t\tevictOldEntries(maxEntries, ttlMs);\n\n\t\t\t\t\t// Cache the response\n\t\t\t\t\tetagCache.set(cacheKey, {\n\t\t\t\t\t\tetag,\n\t\t\t\t\t\tbody,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn response;\n\t\t},\n\t};\n}\n\n/**\n * Clear ETag cache (for testing)\n */\nexport function clearETagCache(): void {\n\tetagCache.clear();\n}\n\n/**\n * Get ETag cache stats (for monitoring)\n */\nexport function getETagCacheStats(): { size: number; entries: string[] } {\n\treturn {\n\t\tsize: etagCache.size,\n\t\tentries: Array.from(etagCache.keys()),\n\t};\n}\n\n// ============================================================================\n// Retry Middleware\n// ============================================================================\n\n/**\n * Create retry middleware with exponential backoff and timeout\n *\n * Features:\n * - Request timeout (default 30s) prevents infinite hangs\n * - Exponential backoff with jitter for retries\n * - Respects Retry-After header for rate limiting\n * - Stores original body for proper request reconstruction on retry\n */\nfunction createRetryMiddleware(\n\tretryConfig: RetryConfig | false | undefined,\n): Middleware {\n\tif (retryConfig === false) {\n\t\t// No-op middleware - just passes through\n\t\treturn {\n\t\t\tasync onResponse({ response }) {\n\t\t\t\treturn response;\n\t\t\t},\n\t\t};\n\t}\n\n\tconst {\n\t\tmaxRetries = 3,\n\t\tbaseDelay = BASE_RETRY_DELAY_MS,\n\t\tmaxDelay = MAX_RETRY_DELAY_MS,\n\t\tshouldRetry = isRetryableStatus,\n\t\ttimeout = DEFAULT_TIMEOUT_MS,\n\t} = retryConfig ?? {};\n\n\t// Store original body for retries (body can only be read once from Request)\n\tlet originalBody: string | null = null;\n\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\t// Store body for potential retries before it gets consumed\n\t\t\tif (request.body) {\n\t\t\t\toriginalBody = await request.clone().text();\n\t\t\t} else {\n\t\t\t\toriginalBody = null;\n\t\t\t}\n\n\t\t\t// Add timeout if not already set\n\t\t\tif (!request.signal) {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tsetTimeout(() => controller.abort(), timeout);\n\t\t\t\treturn new Request(request.url, {\n\t\t\t\t\tmethod: request.method,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tbody: originalBody,\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn request;\n\t\t},\n\t\tasync onResponse({ response, request }) {\n\t\t\tlet attempt = 0;\n\t\t\tlet currentResponse = response;\n\n\t\t\t// Check if we need to retry using the shouldRetry callback\n\t\t\twhile (\n\t\t\t\tattempt < maxRetries &&\n\t\t\t\tshouldRetry(currentResponse.status, attempt)\n\t\t\t) {\n\t\t\t\tconst retryAfter = currentResponse.headers.get(\"Retry-After\");\n\t\t\t\tconst delay = retryAfter\n\t\t\t\t\t? Number.parseInt(retryAfter, 10) * 1000\n\t\t\t\t\t: exponentialBackoff(attempt, baseDelay, maxDelay);\n\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\tattempt++;\n\n\t\t\t\t// Create timeout for retry\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tconst timeoutId = setTimeout(() => controller.abort(), timeout);\n\n\t\t\t\ttry {\n\t\t\t\t\t// Reconstruct request with stored body and new signal\n\t\t\t\t\tconst retryRequest = new Request(request.url, {\n\t\t\t\t\t\tmethod: request.method,\n\t\t\t\t\t\theaders: request.headers,\n\t\t\t\t\t\tbody: originalBody,\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst newResponse = await fetch(retryRequest);\n\t\t\t\t\tclearTimeout(timeoutId);\n\n\t\t\t\t\t// If successful or non-retryable client error, return\n\t\t\t\t\tif (newResponse.ok || !shouldRetry(newResponse.status, attempt)) {\n\t\t\t\t\t\treturn newResponse;\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrentResponse = newResponse;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t\t// On network/timeout error during retry, continue to next attempt\n\t\t\t\t\tif (attempt >= maxRetries) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn currentResponse;\n\t\t},\n\t};\n}\n\n/**\n * Create a type-safe REST API client\n *\n * Uses openapi-fetch with full type inference from OpenAPI specification.\n * All endpoints, inputs, and outputs are automatically typed.\n * Includes automatic retry with exponential backoff for transient failures.\n *\n * @example\n * ```typescript\n * const client = createRestClient({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * })\n *\n * // GET requests\n * const { data: user } = await client.GET('/auth/me')\n * const { data: plans } = await client.GET('/billing/plans')\n *\n * // POST requests\n * const { data: result } = await client.POST('/auth/login', {\n * body: { email: 'test@example.com', password: 'secret' }\n * })\n * ```\n */\n/**\n * Validate and sanitize REST client configuration (SSOT helper)\n */\nfunction validateClientConfig(config: {\n\tsecretKey?: string;\n\tplatformUrl?: string;\n}) {\n\treturn {\n\t\tsecretKey: validateAndSanitizeSecretKey(config.secretKey),\n\t\tbaseUrl: (config.platformUrl || DEFAULT_PLATFORM_URL).trim(),\n\t};\n}\n\nexport function createRestClient(config: RestClientConfig) {\n\tconst { secretKey, baseUrl } = validateClientConfig(config);\n\n\tconst client = createClient<paths>({\n\t\tbaseUrl: `${baseUrl}${SDK_API_PATH}`,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"x-app-secret\": secretKey,\n\t\t},\n\t});\n\n\t// Add deduplication middleware first (before other middleware)\n\tif (config.deduplication !== false) {\n\t\tclient.use(createDeduplicationMiddleware(config.deduplication));\n\t}\n\n\t// Add circuit breaker middleware (before retry)\n\tif (config.circuitBreaker !== false) {\n\t\tclient.use(createCircuitBreakerMiddleware(config.circuitBreaker));\n\t}\n\n\t// Add ETag caching middleware (before retry, for HTTP conditional requests)\n\tif (config.etag !== false) {\n\t\tclient.use(createETagMiddleware(config.etag));\n\t}\n\n\t// Add retry middleware (last, so it can retry after circuit allows)\n\tclient.use(createRetryMiddleware(config.retry));\n\n\treturn client;\n}\n\n/**\n * Create a dynamic REST client with runtime token injection\n *\n * Use this when you need to inject an access token that may change.\n * Tokens should be read from HttpOnly cookies via a server endpoint,\n * never from localStorage (XSS vulnerability).\n *\n * @example\n * ```typescript\n * // Server-side usage\n * const client = createDynamicRestClient({\n * secretKey: process.env.SYLPHX_SECRET_KEY!,\n * getAccessToken: async () => (await cookies()).get('session')?.value,\n * })\n * ```\n */\nexport function createDynamicRestClient(config: RestDynamicConfig) {\n\tconst { secretKey, baseUrl } = validateClientConfig(config);\n\n\t// Create validated config for middleware\n\tconst validatedConfig: RestDynamicConfig = {\n\t\t...config,\n\t\tsecretKey,\n\t\tplatformUrl: baseUrl,\n\t};\n\n\tconst client = createClient<paths>({\n\t\tbaseUrl: `${baseUrl}${SDK_API_PATH}`,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t});\n\n\t// Add deduplication middleware first (before other middleware)\n\tif (config.deduplication !== false) {\n\t\tclient.use(createDeduplicationMiddleware(config.deduplication));\n\t}\n\n\t// Add auth middleware (runs on each request)\n\tclient.use(createAuthMiddleware(validatedConfig));\n\n\t// Add circuit breaker middleware (before retry)\n\tif (config.circuitBreaker !== false) {\n\t\tclient.use(createCircuitBreakerMiddleware(config.circuitBreaker));\n\t}\n\n\t// Add ETag caching middleware (before retry, for HTTP conditional requests)\n\tif (config.etag !== false) {\n\t\tclient.use(createETagMiddleware(config.etag));\n\t}\n\n\t// Add retry middleware (last, so it can retry after circuit allows)\n\tclient.use(createRetryMiddleware(config.retry));\n\n\treturn client;\n}\n\n/**\n * Type for the REST client instance\n */\nexport type RestClient = ReturnType<typeof createRestClient>;\nexport type DynamicRestClient = ReturnType<typeof createDynamicRestClient>;\n\n/**\n * Check if a REST response has an error\n */\nexport function hasError<T, E>(response: { data?: T; error?: E }): response is {\n\tdata: undefined;\n\terror: E;\n} {\n\treturn response.error !== undefined;\n}\n\n/**\n * Extract error message from REST error response\n */\nexport function getRestErrorMessage(error: unknown): string {\n\tif (error && typeof error === \"object\" && \"error\" in error) {\n\t\tconst err = error as { error?: { message?: string } };\n\t\treturn err.error?.message ?? \"An unknown error occurred\";\n\t}\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\treturn \"An unknown error occurred\";\n}\n","/**\n * Sylphx SDK Error Classes\n *\n * Typed error classes for better error handling and debugging.\n * Compatible with tRPC error codes and provides rich context.\n *\n * @example\n * ```typescript\n * import { SylphxError, isRetryableError, getErrorMessage } from '@sylphx/sdk'\n *\n * try {\n * await sylphx.auth.login.mutate({ email, password })\n * } catch (error) {\n * if (error instanceof SylphxError) {\n * console.log(error.code) // 'UNAUTHORIZED'\n * console.log(error.isRetryable) // false\n * }\n * if (isRetryableError(error)) {\n * // Safe to retry\n * }\n * }\n * ```\n */\n\nimport {\n\tBASE_RETRY_DELAY_MS,\n\tDEFAULT_TIMEOUT_MS,\n\tMAX_RETRY_DELAY_MS,\n} from \"./constants\";\n\n// ============================================================================\n// Error Codes (aligned with tRPC and HTTP semantics)\n// ============================================================================\n\nexport type SylphxErrorCode =\n\t// Client errors (4xx)\n\t| \"BAD_REQUEST\" // 400 - Invalid input\n\t| \"UNAUTHORIZED\" // 401 - Not authenticated\n\t| \"FORBIDDEN\" // 403 - Not authorized\n\t| \"NOT_FOUND\" // 404 - Resource not found\n\t| \"CONFLICT\" // 409 - Resource conflict (e.g., duplicate)\n\t| \"PAYLOAD_TOO_LARGE\" // 413 - Request too large\n\t| \"UNPROCESSABLE_ENTITY\" // 422 - Validation failed\n\t| \"TOO_MANY_REQUESTS\" // 429 - Rate limited\n\t// Server errors (5xx)\n\t| \"INTERNAL_SERVER_ERROR\" // 500 - Server error\n\t| \"NOT_IMPLEMENTED\" // 501 - Feature not available\n\t| \"BAD_GATEWAY\" // 502 - Upstream error\n\t| \"SERVICE_UNAVAILABLE\" // 503 - Temporarily unavailable\n\t| \"GATEWAY_TIMEOUT\" // 504 - Upstream timeout\n\t// Network/Client errors\n\t| \"NETWORK_ERROR\" // Network failure\n\t| \"TIMEOUT\" // Request timeout\n\t| \"ABORTED\" // Request aborted\n\t// SDK-specific\n\t| \"PARSE_ERROR\" // JSON/response parse error\n\t| \"UNKNOWN\"; // Unknown error\n\n/**\n * HTTP status code mapping for error codes\n */\nexport const ERROR_CODE_STATUS: Record<SylphxErrorCode, number> = {\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tCONFLICT: 409,\n\tPAYLOAD_TOO_LARGE: 413,\n\tUNPROCESSABLE_ENTITY: 422,\n\tTOO_MANY_REQUESTS: 429,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tNETWORK_ERROR: 0,\n\tTIMEOUT: 0,\n\tABORTED: 0,\n\tPARSE_ERROR: 0,\n\tUNKNOWN: 0,\n};\n\n/**\n * Retryable error codes (safe to retry automatically)\n */\nexport const RETRYABLE_CODES: Set<SylphxErrorCode> = new Set([\n\t\"NETWORK_ERROR\",\n\t\"TIMEOUT\",\n\t\"BAD_GATEWAY\",\n\t\"SERVICE_UNAVAILABLE\",\n\t\"GATEWAY_TIMEOUT\",\n\t\"TOO_MANY_REQUESTS\", // With backoff\n\t\"INTERNAL_SERVER_ERROR\", // Sometimes transient\n]);\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport interface SylphxErrorOptions {\n\t/** Error code for programmatic handling */\n\tcode?: SylphxErrorCode;\n\t/** HTTP status code (inferred from code if not provided) */\n\tstatus?: number;\n\t/** Additional context data */\n\tdata?: Record<string, unknown>;\n\t/** Original error that caused this */\n\tcause?: Error;\n\t/** Retry-After header value (seconds) for rate limiting */\n\tretryAfter?: number;\n}\n\n/**\n * Base error class for all Sylphx SDK errors\n *\n * @example\n * ```typescript\n * throw new SylphxError('Invalid email format', {\n * code: 'BAD_REQUEST',\n * data: { field: 'email' }\n * })\n * ```\n */\nexport class SylphxError extends Error {\n\t/** Error code for programmatic handling */\n\treadonly code: SylphxErrorCode;\n\n\t/** HTTP status code */\n\treadonly status: number;\n\n\t/** Additional context data */\n\treadonly data?: Record<string, unknown>;\n\n\t/** Whether this error is safe to retry */\n\treadonly isRetryable: boolean;\n\n\t/** Retry-After value in seconds (for rate limiting) */\n\treadonly retryAfter?: number;\n\n\t/** Timestamp when error occurred */\n\treadonly timestamp: Date;\n\n\tconstructor(message: string, options: SylphxErrorOptions = {}) {\n\t\tsuper(message, { cause: options.cause });\n\t\tthis.name = \"SylphxError\";\n\t\tthis.code = options.code ?? \"UNKNOWN\";\n\t\tthis.status = options.status ?? ERROR_CODE_STATUS[this.code];\n\t\tthis.data = options.data;\n\t\tthis.isRetryable = RETRYABLE_CODES.has(this.code);\n\t\tthis.retryAfter = options.retryAfter;\n\t\tthis.timestamp = new Date();\n\n\t\t// Maintain proper stack trace in V8\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, SylphxError);\n\t\t}\n\t}\n\n\t/**\n\t * Convert to JSON-serializable object\n\t */\n\ttoJSON(): Record<string, unknown> {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tmessage: this.message,\n\t\t\tcode: this.code,\n\t\t\tstatus: this.status,\n\t\t\tdata: this.data,\n\t\t\tisRetryable: this.isRetryable,\n\t\t\tretryAfter: this.retryAfter,\n\t\t\ttimestamp: this.timestamp.toISOString(),\n\t\t};\n\t}\n}\n\n/**\n * Network-related errors (no response received)\n */\nexport class NetworkError extends SylphxError {\n\tconstructor(\n\t\tmessage = \"Network request failed\",\n\t\toptions?: Omit<SylphxErrorOptions, \"code\">,\n\t) {\n\t\tsuper(message, { ...options, code: \"NETWORK_ERROR\" });\n\t\tthis.name = \"NetworkError\";\n\t}\n}\n\n/**\n * Request timeout errors\n */\nexport class TimeoutError extends SylphxError {\n\t/** Timeout duration in milliseconds */\n\treadonly timeout: number;\n\n\tconstructor(timeout: number, options?: Omit<SylphxErrorOptions, \"code\">) {\n\t\tsuper(`Request timed out after ${timeout}ms`, {\n\t\t\t...options,\n\t\t\tcode: \"TIMEOUT\",\n\t\t});\n\t\tthis.name = \"TimeoutError\";\n\t\tthis.timeout = timeout;\n\t}\n}\n\n/**\n * Authentication errors (401)\n */\nexport class AuthenticationError extends SylphxError {\n\tconstructor(\n\t\tmessage = \"Authentication required\",\n\t\toptions?: Omit<SylphxErrorOptions, \"code\">,\n\t) {\n\t\tsuper(message, { ...options, code: \"UNAUTHORIZED\" });\n\t\tthis.name = \"AuthenticationError\";\n\t}\n}\n\n/**\n * Authorization errors (403)\n */\nexport class AuthorizationError extends SylphxError {\n\tconstructor(\n\t\tmessage = \"Permission denied\",\n\t\toptions?: Omit<SylphxErrorOptions, \"code\">,\n\t) {\n\t\tsuper(message, { ...options, code: \"FORBIDDEN\" });\n\t\tthis.name = \"AuthorizationError\";\n\t}\n}\n\n/**\n * Validation errors (422)\n */\nexport class ValidationError extends SylphxError {\n\t/** Field-specific errors */\n\treadonly fieldErrors?: Record<string, string[]>;\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: Omit<SylphxErrorOptions, \"code\"> & {\n\t\t\tfieldErrors?: Record<string, string[]>;\n\t\t},\n\t) {\n\t\tsuper(message, { ...options, code: \"UNPROCESSABLE_ENTITY\" });\n\t\tthis.name = \"ValidationError\";\n\t\tthis.fieldErrors = options?.fieldErrors;\n\t}\n\n\t/**\n\t * Get error message for a specific field\n\t */\n\tgetFieldError(field: string): string | undefined {\n\t\treturn this.fieldErrors?.[field]?.[0];\n\t}\n}\n\n/**\n * Rate limit metadata (Stripe SDK pattern)\n */\nexport interface RateLimitInfo {\n\t/** Maximum requests allowed in window */\n\tlimit?: number;\n\t/** Remaining requests in current window */\n\tremaining?: number;\n\t/** Unix timestamp (seconds) when limit resets */\n\tresetAt?: number;\n\t/** Seconds until limit resets (Retry-After header) */\n\tretryAfter?: number;\n}\n\n/**\n * Rate limit errors (429)\n *\n * Provides full rate limit metadata for consumer apps to implement\n * proper backoff UI (countdown timers, retry buttons, etc.)\n *\n * @example\n * ```typescript\n * try {\n * await sendEmail(config, options)\n * } catch (error) {\n * if (error instanceof RateLimitError) {\n * const waitSeconds = error.retryAfter ?? 60\n * console.log(`Rate limited. Retry after ${waitSeconds}s`)\n * console.log(`Remaining: ${error.remaining}/${error.limit}`)\n * console.log(`Resets at: ${new Date(error.resetAt! * 1000)}`)\n * }\n * }\n * ```\n */\nexport class RateLimitError extends SylphxError {\n\t/** Maximum requests allowed in window */\n\treadonly limit?: number;\n\n\t/** Remaining requests in current window */\n\treadonly remaining?: number;\n\n\t/** Unix timestamp (seconds) when limit resets */\n\treadonly resetAt?: number;\n\n\tconstructor(\n\t\tmessage = \"Too many requests\",\n\t\toptions?: Omit<SylphxErrorOptions, \"code\"> & RateLimitInfo,\n\t) {\n\t\tsuper(message, { ...options, code: \"TOO_MANY_REQUESTS\" });\n\t\tthis.name = \"RateLimitError\";\n\t\tthis.limit = options?.limit;\n\t\tthis.remaining = options?.remaining;\n\t\tthis.resetAt = options?.resetAt;\n\t}\n\n\t/**\n\t * Get Date when rate limit resets\n\t */\n\tgetResetDate(): Date | undefined {\n\t\treturn this.resetAt ? new Date(this.resetAt * 1000) : undefined;\n\t}\n\n\t/**\n\t * Get human-readable retry message\n\t */\n\tgetRetryMessage(): string {\n\t\tif (this.retryAfter) {\n\t\t\treturn `Please retry after ${this.retryAfter} seconds`;\n\t\t}\n\t\tif (this.resetAt) {\n\t\t\tconst seconds = Math.max(0, this.resetAt - Math.floor(Date.now() / 1000));\n\t\t\treturn `Rate limit resets in ${seconds} seconds`;\n\t\t}\n\t\treturn \"Please wait before retrying\";\n\t}\n}\n\n/**\n * Resource not found errors (404)\n */\nexport class NotFoundError extends SylphxError {\n\t/** Type of resource that wasn't found */\n\treadonly resourceType?: string;\n\n\t/** ID of the resource that wasn't found */\n\treadonly resourceId?: string;\n\n\tconstructor(\n\t\tmessage = \"Resource not found\",\n\t\toptions?: Omit<SylphxErrorOptions, \"code\"> & {\n\t\t\tresourceType?: string;\n\t\t\tresourceId?: string;\n\t\t},\n\t) {\n\t\tsuper(message, { ...options, code: \"NOT_FOUND\" });\n\t\tthis.name = \"NotFoundError\";\n\t\tthis.resourceType = options?.resourceType;\n\t\tthis.resourceId = options?.resourceId;\n\t}\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Check if an error is a Sylphx SDK error\n */\nexport function isSylphxError(error: unknown): error is SylphxError {\n\treturn error instanceof SylphxError;\n}\n\n/**\n * Check if an error is safe to retry\n */\nexport function isRetryableError(error: unknown): boolean {\n\tif (error instanceof SylphxError) {\n\t\treturn error.isRetryable;\n\t}\n\n\t// Check for network errors\n\tif (error instanceof Error) {\n\t\tconst message = error.message.toLowerCase();\n\t\tconst name = error.name.toLowerCase();\n\n\t\t// Network errors\n\t\tif (name === \"typeerror\" && message.includes(\"fetch\")) return true;\n\t\tif (name === \"networkerror\") return true;\n\n\t\t// Timeout patterns\n\t\tif (message.includes(\"timeout\")) return true;\n\t\tif (message.includes(\"timed out\")) return true;\n\n\t\t// Connection errors\n\t\tif (message.includes(\"econnrefused\")) return true;\n\t\tif (message.includes(\"econnreset\")) return true;\n\t\tif (message.includes(\"socket\")) return true;\n\n\t\t// Server errors that might be transient\n\t\tif (message.includes(\"502\")) return true;\n\t\tif (message.includes(\"503\")) return true;\n\t\tif (message.includes(\"504\")) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Extract error message from any error type\n */\nexport function getErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\tif (typeof error === \"string\") {\n\t\treturn error;\n\t}\n\treturn \"An unknown error occurred\";\n}\n\n/**\n * Get error code from any error type\n */\nexport function getErrorCode(error: unknown): SylphxErrorCode {\n\tif (error instanceof SylphxError) {\n\t\treturn error.code;\n\t}\n\treturn \"UNKNOWN\";\n}\n\n/**\n * Convert any error to SylphxError\n */\nexport function toSylphxError(error: unknown): SylphxError {\n\tif (error instanceof SylphxError) {\n\t\treturn error;\n\t}\n\n\tif (error instanceof Error) {\n\t\t// Try to infer error type from message/name\n\t\tconst message = error.message.toLowerCase();\n\t\tconst name = error.name.toLowerCase();\n\n\t\t// Network errors\n\t\tif (name === \"typeerror\" && message.includes(\"fetch\")) {\n\t\t\treturn new NetworkError(error.message, { cause: error });\n\t\t}\n\t\tif (name === \"aborterror\" || message.includes(\"aborted\")) {\n\t\t\treturn new SylphxError(error.message, { code: \"ABORTED\", cause: error });\n\t\t}\n\n\t\t// Timeout\n\t\tif (message.includes(\"timeout\")) {\n\t\t\treturn new TimeoutError(DEFAULT_TIMEOUT_MS, { cause: error });\n\t\t}\n\n\t\t// HTTP status codes in message\n\t\tif (message.includes(\"401\") || message.includes(\"unauthorized\")) {\n\t\t\treturn new AuthenticationError(error.message, { cause: error });\n\t\t}\n\t\tif (message.includes(\"403\") || message.includes(\"forbidden\")) {\n\t\t\treturn new AuthorizationError(error.message, { cause: error });\n\t\t}\n\t\tif (message.includes(\"404\") || message.includes(\"not found\")) {\n\t\t\treturn new NotFoundError(error.message, { cause: error });\n\t\t}\n\t\tif (message.includes(\"429\") || message.includes(\"rate limit\")) {\n\t\t\treturn new RateLimitError(error.message, { cause: error });\n\t\t}\n\n\t\treturn new SylphxError(error.message, { cause: error });\n\t}\n\n\treturn new SylphxError(getErrorMessage(error));\n}\n\n/**\n * Calculate exponential backoff delay with jitter\n *\n * @param attempt - Retry attempt number (0-indexed)\n * @param baseDelay - Base delay in milliseconds (default: 1000)\n * @param maxDelay - Maximum delay in milliseconds (default: 30000)\n * @returns Delay in milliseconds with jitter\n */\nexport function exponentialBackoff(\n\tattempt: number,\n\tbaseDelay = BASE_RETRY_DELAY_MS,\n\tmaxDelay = MAX_RETRY_DELAY_MS,\n): number {\n\t// Calculate exponential delay: baseDelay * 2^attempt\n\tconst exponentialDelay = baseDelay * Math.pow(2, attempt);\n\n\t// Cap at maxDelay\n\tconst cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n\t// Add jitter (±25% randomness)\n\tconst jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n\n\treturn Math.round(cappedDelay + jitter);\n}\n","/**\n * API Key Validation — Single Source of Truth\n *\n * OAuth 2.0 standard key validation for Sylphx Platform.\n * ALL key validation, sanitization, and environment detection logic lives here.\n *\n * Principles:\n * 1. Fail fast - Invalid input rejected immediately with clear errors\n * 2. Helpful errors - Tell users exactly what's wrong and how to fix it\n * 3. Development warnings - Warn about issues that would fail in production\n * 4. No silent fixes - Transparency over convenience (but warn + continue)\n * 5. Single Source of Truth - All key logic in one place\n *\n * Key Formats (OAuth 2.0 Standard):\n * - App ID: app_(dev|stg|prod)_[identifier] — Public identifier (like OAuth client_id)\n * - Secret Key: sk_(dev|stg|prod)_[identifier] — Server-side only (like OAuth client_secret)\n *\n * Identifier Types:\n * - Customer apps: 32 hex chars\n * - Platform apps: platform_{app-slug} (e.g., platform_sylphx-console)\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Environment type derived from key prefix */\nexport type EnvironmentType = \"development\" | \"staging\" | \"production\";\n\n/** Key type - appId (public) or secret (server) */\nexport type KeyType = \"appId\" | \"secret\";\n\n/** Validation result with clear error information */\nexport interface KeyValidationResult {\n\t/** Whether the key is valid (possibly after sanitization) */\n\tvalid: boolean;\n\t/** The sanitized key to use (only if valid) */\n\tsanitizedKey: string;\n\t/** Detected key type */\n\tkeyType?: KeyType;\n\t/** Detected environment */\n\tenvironment?: EnvironmentType;\n\t/** Error message if invalid */\n\terror?: string;\n\t/** Warning message if key was auto-fixed */\n\twarning?: string;\n\t/** Detected issues for debugging */\n\tissues?: string[];\n}\n\n// =============================================================================\n// Patterns — Strict Format Validation\n// =============================================================================\n\n/**\n * App ID pattern: app_(dev|stg|prod)_[identifier]\n * - Prefix: app_ (application identifier, public)\n * - Environment: dev, stg, or prod (NO typos allowed)\n * - Suffix: alphanumeric with underscores/hyphens (hex for apps, or internal identifiers)\n */\nconst APP_ID_PATTERN = /^app_(dev|stg|prod)_[a-z0-9_-]+$/;\n\n/**\n * Secret key pattern: sk_(dev|stg|prod)_[identifier]\n * - Prefix: sk_ (secret key)\n * - Environment: dev, stg, or prod (NO typos allowed)\n * - Suffix: alphanumeric with underscores/hyphens (hex for apps, or internal identifiers)\n */\nconst SECRET_KEY_PATTERN = /^sk_(dev|stg|prod)_[a-z0-9_-]+$/;\n\n/** Environment prefix to type mapping */\nconst ENV_PREFIX_MAP: Record<string, EnvironmentType> = {\n\tdev: \"development\",\n\tstg: \"staging\",\n\tprod: \"production\",\n};\n\n// =============================================================================\n// Core Validation Functions\n// =============================================================================\n\n/**\n * Detect common issues with a key (whitespace, newlines, etc.)\n */\nfunction detectKeyIssues(key: string): string[] {\n\tconst issues: string[] = [];\n\tif (key !== key.trim()) issues.push(\"whitespace\");\n\tif (key.includes(\"\\n\")) issues.push(\"newline\");\n\tif (key.includes(\"\\r\")) issues.push(\"carriage-return\");\n\tif (key.includes(\" \")) issues.push(\"space\");\n\tif (key !== key.toLowerCase()) issues.push(\"uppercase-chars\");\n\treturn issues;\n}\n\n/**\n * Create a helpful warning message for keys that needed sanitization\n */\nfunction createSanitizationWarning(\n\tkeyType: KeyType,\n\tissues: string[],\n\tenvVarName: string,\n): string {\n\tconst keyTypeName = keyType === \"appId\" ? \"App ID\" : \"Secret Key\";\n\treturn (\n\t\t`[Sylphx] ${keyTypeName} contains ${issues.join(\", \")}. ` +\n\t\t`This is commonly caused by Vercel CLI's 'env pull' command.\\n\\n` +\n\t\t`To fix permanently:\\n` +\n\t\t`1. Go to Vercel Dashboard → Your Project → Settings → Environment Variables\\n` +\n\t\t`2. Edit ${envVarName}\\n` +\n\t\t`3. Remove any trailing whitespace or newline characters\\n` +\n\t\t`4. Redeploy your application\\n\\n` +\n\t\t`The SDK will automatically sanitize the key, but fixing the source is recommended.`\n\t);\n}\n\n/**\n * Create a helpful error message for invalid keys\n */\nfunction createInvalidKeyError(\n\tkeyType: KeyType,\n\tkey: string,\n\tenvVarName: string,\n): string {\n\tconst prefix = keyType === \"appId\" ? \"app\" : \"sk\";\n\tconst maskedKey = key.length > 20 ? `${key.slice(0, 20)}...` : key;\n\tconst formatHint = `${prefix}_(dev|stg|prod)_[identifier]`;\n\tconst keyTypeName = keyType === \"appId\" ? \"App ID\" : \"Secret Key\";\n\n\treturn (\n\t\t`[Sylphx] Invalid ${keyTypeName} format.\\n\\n` +\n\t\t`Expected format: ${formatHint}\\n` +\n\t\t`Received: \"${maskedKey}\"\\n\\n` +\n\t\t`Please check your ${envVarName} environment variable.\\n` +\n\t\t`You can find your keys in the Sylphx Console → API Keys.\\n\\n` +\n\t\t`Common issues:\\n` +\n\t\t`• Key has uppercase characters (must be lowercase)\\n` +\n\t\t`• Key has wrong prefix (App ID: app_, Secret Key: sk_)\\n` +\n\t\t`• Key has invalid environment (must be dev, stg, or prod)\\n` +\n\t\t`• Key was copied with extra whitespace`\n\t);\n}\n\n/**\n * Extract environment from a validated key\n */\nfunction extractEnvironment(key: string): EnvironmentType | undefined {\n\t// Match app_ or sk_ prefix followed by environment\n\tconst match = key.match(/^(?:app|sk)_(dev|stg|prod)_/);\n\tif (!match) return undefined;\n\treturn ENV_PREFIX_MAP[match[1]];\n}\n\n/**\n * Internal: Generic key validation logic for specific key types\n */\nfunction validateKeyForType(\n\tkey: string | undefined | null,\n\tkeyType: KeyType,\n\tpattern: RegExp,\n\tenvVarName: string,\n): KeyValidationResult {\n\tconst keyTypeName = keyType === \"appId\" ? \"App ID\" : \"Secret Key\";\n\n\t// Check if key is provided\n\tif (!key) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tsanitizedKey: \"\",\n\t\t\terror:\n\t\t\t\t`[Sylphx] ${keyTypeName} is required. ` +\n\t\t\t\t`Set ${envVarName} in your environment variables.`,\n\t\t\tissues: [\"missing\"],\n\t\t};\n\t}\n\n\t// Detect issues before validation\n\tconst issues = detectKeyIssues(key);\n\n\t// Check if key matches expected format exactly\n\tif (pattern.test(key)) {\n\t\treturn {\n\t\t\tvalid: true,\n\t\t\tsanitizedKey: key,\n\t\t\tkeyType,\n\t\t\tenvironment: extractEnvironment(key),\n\t\t\tissues: [],\n\t\t};\n\t}\n\n\t// Key doesn't match - try sanitization (trim + lowercase)\n\tconst sanitized = key.trim().toLowerCase();\n\n\tif (pattern.test(sanitized)) {\n\t\t// Sanitization fixes the issue\n\t\treturn {\n\t\t\tvalid: true,\n\t\t\tsanitizedKey: sanitized,\n\t\t\tkeyType,\n\t\t\tenvironment: extractEnvironment(sanitized),\n\t\t\twarning: createSanitizationWarning(keyType, issues, envVarName),\n\t\t\tissues,\n\t\t};\n\t}\n\n\t// Sanitization doesn't fix it - key format is genuinely wrong\n\treturn {\n\t\tvalid: false,\n\t\tsanitizedKey: \"\",\n\t\terror: createInvalidKeyError(keyType, key, envVarName),\n\t\tissues: [...issues, \"invalid-format\"],\n\t};\n}\n\n// =============================================================================\n// Public API — App ID (formerly Publishable Key)\n// =============================================================================\n\n/**\n * Validate an App ID and return detailed results\n *\n * @example\n * ```typescript\n * const result = validateAppId(process.env.NEXT_PUBLIC_SYLPHX_APP_ID)\n * if (!result.valid) {\n * throw new Error(result.error)\n * }\n * if (result.warning) {\n * console.warn(result.warning)\n * }\n * ```\n */\nexport function validateAppId(\n\tkey: string | undefined | null,\n): KeyValidationResult {\n\treturn validateKeyForType(\n\t\tkey,\n\t\t\"appId\",\n\t\tAPP_ID_PATTERN,\n\t\t\"NEXT_PUBLIC_SYLPHX_APP_ID\",\n\t);\n}\n\n/**\n * Validate and sanitize App ID, logging warnings\n *\n * @throws Error if the key is invalid and cannot be sanitized\n * @returns The sanitized App ID\n */\nexport function validateAndSanitizeAppId(\n\tkey: string | undefined | null,\n): string {\n\tconst result = validateAppId(key);\n\n\tif (!result.valid) {\n\t\tthrow new Error(result.error);\n\t}\n\n\tif (result.warning) {\n\t\tconsole.warn(result.warning);\n\t}\n\n\treturn result.sanitizedKey;\n}\n\n// =============================================================================\n// Public API — Secret Keys\n// =============================================================================\n\n/**\n * Validate a secret key and return detailed results\n *\n * @example\n * ```typescript\n * const result = validateSecretKey(process.env.SYLPHX_SECRET_KEY)\n * if (!result.valid) {\n * throw new Error(result.error)\n * }\n * ```\n */\nexport function validateSecretKey(\n\tkey: string | undefined | null,\n): KeyValidationResult {\n\treturn validateKeyForType(\n\t\tkey,\n\t\t\"secret\",\n\t\tSECRET_KEY_PATTERN,\n\t\t\"SYLPHX_SECRET_KEY\",\n\t);\n}\n\n/**\n * Validate and sanitize secret key, logging warnings\n *\n * @throws Error if the key is invalid and cannot be sanitized\n * @returns The sanitized secret key\n */\nexport function validateAndSanitizeSecretKey(\n\tkey: string | undefined | null,\n): string {\n\tconst result = validateSecretKey(key);\n\n\tif (!result.valid) {\n\t\tthrow new Error(result.error);\n\t}\n\n\tif (result.warning) {\n\t\tconsole.warn(result.warning);\n\t}\n\n\treturn result.sanitizedKey;\n}\n\n// =============================================================================\n// Public API — Environment Detection (SSOT)\n// =============================================================================\n\n/**\n * Detect environment type from any key (App ID or Secret Key)\n *\n * @example\n * ```typescript\n * detectEnvironment('sk_dev_abc123') // 'development'\n * detectEnvironment('app_prod_xyz789') // 'production'\n * detectEnvironment('sk_stg_qwe456') // 'staging'\n * ```\n *\n * @throws Error if key format is invalid\n */\nexport function detectEnvironment(key: string): EnvironmentType {\n\t// Validate and sanitize first\n\tconst sanitized = key.trim().toLowerCase();\n\n\t// Check both key types\n\tif (sanitized.startsWith(\"sk_\")) {\n\t\tconst result = validateSecretKey(sanitized);\n\t\tif (!result.valid) {\n\t\t\tthrow new Error(result.error);\n\t\t}\n\t\treturn result.environment!;\n\t}\n\n\tif (sanitized.startsWith(\"app_\")) {\n\t\tconst result = validateAppId(sanitized);\n\t\tif (!result.valid) {\n\t\t\tthrow new Error(result.error);\n\t\t}\n\t\treturn result.environment!;\n\t}\n\n\tthrow new Error(\n\t\t`[Sylphx] Invalid key format. Key must start with 'sk_' (secret) or 'app_' (App ID).`,\n\t);\n}\n\n/**\n * Check if running in development environment based on key\n */\nexport function isDevelopmentKey(key: string): boolean {\n\treturn detectEnvironment(key) === \"development\";\n}\n\n/**\n * Check if running in production environment based on key\n */\nexport function isProductionKey(key: string): boolean {\n\treturn detectEnvironment(key) === \"production\";\n}\n\n// =============================================================================\n// Public API — Cookie Namespace (SSOT)\n// =============================================================================\n\n/**\n * Get the cookie namespace for a given secret key\n *\n * Used by auth middleware to namespace cookies per environment.\n * This prevents dev/staging/prod cookies from conflicting.\n *\n * @example\n * ```typescript\n * getCookieNamespace('sk_dev_abc123') // 'sylphx_dev'\n * getCookieNamespace('sk_prod_xyz789') // 'sylphx_prod'\n * ```\n */\nexport function getCookieNamespace(secretKey: string): string {\n\tconst env = detectEnvironment(secretKey);\n\tconst shortEnv =\n\t\tenv === \"development\" ? \"dev\" : env === \"staging\" ? \"stg\" : \"prod\";\n\treturn `sylphx_${shortEnv}`;\n}\n\n// =============================================================================\n// Public API — Key Type Detection\n// =============================================================================\n\n/**\n * Detect the type of key (App ID or Secret Key)\n *\n * @returns 'appId', 'secret', or null if unknown\n */\nexport function detectKeyType(key: string): KeyType | null {\n\tconst sanitized = key.trim().toLowerCase();\n\tif (sanitized.startsWith(\"app_\")) return \"appId\";\n\tif (sanitized.startsWith(\"sk_\")) return \"secret\";\n\treturn null;\n}\n\n/**\n * Check if a key is an App ID\n */\nexport function isAppId(key: string): boolean {\n\treturn detectKeyType(key) === \"appId\";\n}\n\n/**\n * Check if a key is a secret key\n */\nexport function isSecretKey(key: string): boolean {\n\treturn detectKeyType(key) === \"secret\";\n}\n\n/**\n * Validate any key (auto-detects type)\n *\n * Use this when you accept either App ID or Secret Key.\n * The function auto-detects the key type and validates accordingly.\n *\n * @example\n * ```typescript\n * const result = validateKey(process.env.SYLPHX_SECRET_KEY)\n * if (!result.valid) {\n * throw new Error(result.error)\n * }\n * const sanitizedKey = result.sanitizedKey\n * ```\n */\nexport function validateKey(\n\tkey: string | undefined | null,\n): KeyValidationResult {\n\tconst keyType = key ? detectKeyType(key) : null;\n\n\tif (keyType === \"appId\") {\n\t\treturn validateAppId(key);\n\t}\n\tif (keyType === \"secret\") {\n\t\treturn validateSecretKey(key);\n\t}\n\n\t// Unknown key type - return detailed error\n\treturn {\n\t\tvalid: false,\n\t\tsanitizedKey: \"\",\n\t\terror: key\n\t\t\t? `Invalid key format. Keys must start with 'app_' (App ID) or 'sk_' (Secret Key), followed by environment (dev/stg/prod) and identifier. Got: ${key.slice(0, 20)}...`\n\t\t\t: \"API key is required but was not provided.\",\n\t\tissues: key ? [\"invalid_format\"] : [\"missing\"],\n\t};\n}\n\n/**\n * Validate any key and return sanitized version (throws on error)\n *\n * Use this when you need the key value and want to throw on invalid input.\n */\nexport function validateAndSanitizeKey(key: string | undefined | null): string {\n\tconst result = validateKey(key);\n\tif (!result.valid) {\n\t\tthrow new Error(result.error);\n\t}\n\tif (result.warning) {\n\t\tconsole.warn(`[Sylphx] ${result.warning}`);\n\t}\n\treturn result.sanitizedKey;\n}\n\n// =============================================================================\n// Public API — Runtime Environment Detection\n// =============================================================================\n\n/**\n * Check if we're in development mode (based on NODE_ENV or hostname)\n */\nexport function isDevelopmentRuntime(): boolean {\n\tif (typeof process !== \"undefined\" && process.env) {\n\t\treturn process.env.NODE_ENV === \"development\";\n\t}\n\tif (typeof window !== \"undefined\") {\n\t\treturn (\n\t\t\twindow.location.hostname === \"localhost\" ||\n\t\t\twindow.location.hostname === \"127.0.0.1\"\n\t\t);\n\t}\n\treturn false;\n}\n","/**\n * Server-side AI Client\n *\n * Creates an OpenAI-compatible client configured for Sylphx Platform.\n * Use this in Server Components, API routes, and server actions.\n *\n * @example\n * ```ts\n * import { createAI } from '@sylphx/platform-sdk/server'\n *\n * const ai = createAI()\n *\n * // Chat completion\n * const response = await ai.chat({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{ role: 'user', content: 'Hello!' }],\n * })\n *\n * // Embeddings\n * const embeddings = await ai.embed({\n * model: 'openai/text-embedding-3-small',\n * input: 'Hello world',\n * })\n *\n * // Streaming\n * const stream = await ai.chat({\n * model: 'anthropic/claude-3.5-sonnet',\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * stream: true,\n * })\n *\n * for await (const chunk of stream) {\n * process.stdout.write(chunk.choices[0]?.delta?.content || '')\n * }\n * ```\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport interface AIClientOptions {\n\t/** Secret key for authentication (default: SYLPHX_SECRET_KEY env var) */\n\tsecretKey?: string;\n\t/** Platform URL (default: SYLPHX_PLATFORM_URL env var or https://sylphx.com) */\n\tplatformUrl?: string;\n}\n\n// ChatMessage re-exported from ai.ts (SSOT)\nexport type { ChatMessage } from \"../ai\";\nimport type { ChatMessage } from \"../ai\";\nimport { DEFAULT_PLATFORM_URL } from \"../constants\";\nimport { validateAndSanitizeSecretKey } from \"../key-validation\";\n\nexport interface ChatCompletionOptions {\n\tmodel: string;\n\tmessages: ChatMessage[];\n\ttemperature?: number;\n\tmax_tokens?: number;\n\ttop_p?: number;\n\tfrequency_penalty?: number;\n\tpresence_penalty?: number;\n\tstop?: string | string[];\n\tstream?: false;\n\tuser?: string;\n}\n\nexport interface ChatCompletionStreamOptions\n\textends Omit<ChatCompletionOptions, \"stream\"> {\n\tstream: true;\n}\n\nexport interface ChatCompletionResponse {\n\tid: string;\n\tobject: \"chat.completion\";\n\tcreated: number;\n\tmodel: string;\n\tchoices: Array<{\n\t\tindex: number;\n\t\tmessage: {\n\t\t\trole: \"assistant\";\n\t\t\tcontent: string;\n\t\t};\n\t\tfinish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null;\n\t}>;\n\tusage: {\n\t\tprompt_tokens: number;\n\t\tcompletion_tokens: number;\n\t\ttotal_tokens: number;\n\t};\n}\n\nexport interface ChatCompletionChunk {\n\tid: string;\n\tobject: \"chat.completion.chunk\";\n\tcreated: number;\n\tmodel: string;\n\tchoices: Array<{\n\t\tindex: number;\n\t\tdelta: {\n\t\t\trole?: \"assistant\";\n\t\t\tcontent?: string;\n\t\t};\n\t\tfinish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null;\n\t}>;\n}\n\nexport interface EmbeddingOptions {\n\tmodel: string;\n\tinput: string | string[];\n\tdimensions?: number;\n\tuser?: string;\n}\n\nexport interface EmbeddingResponse {\n\tobject: \"list\";\n\tdata: Array<{\n\t\tobject: \"embedding\";\n\t\tindex: number;\n\t\tembedding: number[];\n\t}>;\n\tmodel: string;\n\tusage: {\n\t\tprompt_tokens: number;\n\t\ttotal_tokens: number;\n\t};\n}\n\nexport interface ModelInfo {\n\tid: string;\n\tname: string;\n\tcontext_length: number;\n\tpricing: {\n\t\tprompt: string;\n\t\tcompletion: string;\n\t};\n\tcapabilities: string[];\n}\n\nexport interface ModelsResponse {\n\tobject: \"list\";\n\tdata: ModelInfo[];\n}\n\n// ============================================\n// AI Client\n// ============================================\n\nexport interface AIClient {\n\t/** Create a chat completion */\n\tchat(options: ChatCompletionOptions): Promise<ChatCompletionResponse>;\n\t/** Create a streaming chat completion */\n\tchat(\n\t\toptions: ChatCompletionStreamOptions,\n\t): Promise<AsyncIterable<ChatCompletionChunk>>;\n\t/** Create embeddings */\n\tembed(options: EmbeddingOptions): Promise<EmbeddingResponse>;\n\t/** List available models */\n\tlistModels(options?: {\n\t\tcapability?: string;\n\t\tsearch?: string;\n\t}): Promise<ModelsResponse>;\n}\n\n/**\n * Create a server-side AI client\n *\n * Uses environment variables by default:\n * - SYLPHX_PLATFORM_URL: Platform URL (default: https://sylphx.com)\n * - SYLPHX_SECRET_KEY: Your app's secret key (sk_dev_xxx, sk_stg_xxx, sk_prod_xxx)\n */\nexport function createAI(options: AIClientOptions = {}): AIClient {\n\tconst baseURL = (\n\t\toptions.platformUrl ||\n\t\tprocess.env.SYLPHX_PLATFORM_URL ||\n\t\tDEFAULT_PLATFORM_URL\n\t).trim();\n\tconst rawApiKey = options.secretKey || process.env.SYLPHX_SECRET_KEY;\n\n\t// Validate and sanitize API key using SSOT\n\tconst apiKey = validateAndSanitizeSecretKey(rawApiKey);\n\n\tconst headers = {\n\t\t\"Content-Type\": \"application/json\",\n\t\tAuthorization: `Bearer ${apiKey}`,\n\t};\n\n\tasync function chat(\n\t\topts: ChatCompletionOptions | ChatCompletionStreamOptions,\n\t): Promise<ChatCompletionResponse | AsyncIterable<ChatCompletionChunk>> {\n\t\tconst response = await fetch(`${baseURL}/api/v1/chat/completions`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(opts),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response\n\t\t\t\t.json()\n\t\t\t\t.catch(() => ({ error: { message: \"Chat failed\" } }));\n\t\t\tthrow new Error(error.error?.message || \"Chat failed\");\n\t\t}\n\n\t\tif (opts.stream) {\n\t\t\t// Return async iterable for streaming\n\t\t\treturn parseSSEStream(response);\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync function embed(opts: EmbeddingOptions): Promise<EmbeddingResponse> {\n\t\tconst response = await fetch(`${baseURL}/api/v1/embeddings`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(opts),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response\n\t\t\t\t.json()\n\t\t\t\t.catch(() => ({ error: { message: \"Embedding failed\" } }));\n\t\t\tthrow new Error(error.error?.message || \"Embedding failed\");\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync function listModels(opts?: {\n\t\tcapability?: string;\n\t\tsearch?: string;\n\t}): Promise<ModelsResponse> {\n\t\tconst params = new URLSearchParams();\n\t\tif (opts?.capability) params.set(\"capability\", opts.capability);\n\t\tif (opts?.search) params.set(\"search\", opts.search);\n\t\tconst query = params.toString();\n\n\t\tconst response = await fetch(\n\t\t\t`${baseURL}/api/v1/models${query ? `?${query}` : \"\"}`,\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\"Failed to fetch models\");\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\treturn {\n\t\tchat: chat as AIClient[\"chat\"],\n\t\tembed,\n\t\tlistModels,\n\t};\n}\n\n// ============================================\n// SSE Stream Parser\n// ============================================\n\nasync function* parseSSEStream(\n\tresponse: Response,\n): AsyncIterable<ChatCompletionChunk> {\n\tconst reader = response.body?.getReader();\n\tif (!reader) {\n\t\tthrow new Error(\"Response body is not readable\");\n\t}\n\n\tconst decoder = new TextDecoder();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\n\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\tfor (const line of lines) {\n\t\t\t\tif (line.startsWith(\"data: \")) {\n\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\tif (data === \"[DONE]\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst chunk = JSON.parse(data) as ChatCompletionChunk;\n\t\t\t\t\t\tyield chunk;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Skip invalid JSON\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultClient: AIClient | null = null;\n\n/**\n * Get the default AI client (singleton)\n * Creates one using environment variables on first call\n */\nexport function getAI(): AIClient {\n\tif (!defaultClient) {\n\t\tdefaultClient = createAI();\n\t}\n\treturn defaultClient;\n}\n","/**\n * Server-side KV (Key-Value Store) Client\n *\n * Creates a client for key-value operations via Upstash Redis.\n * Use this in Server Components, API routes, and server actions.\n *\n * @example\n * ```ts\n * import { createKv } from '@sylphx/sdk/server'\n *\n * const kv = createKv()\n *\n * // Basic operations\n * await kv.set('user:123:profile', { name: 'John' }, { ex: 3600 })\n * const profile = await kv.get('user:123:profile')\n *\n * // Atomic counter\n * const views = await kv.incr('page:home:views')\n *\n * // Rate limiting\n * const { success, remaining } = await kv.ratelimit('api:user123', {\n * limit: 100,\n * window: '1h',\n * })\n * ```\n */\n\nimport {\n\tMAX_RETRIES,\n\tSDK_API_PATH,\n\tSDK_PLATFORM,\n\tSDK_VERSION,\n\tresolvePlatformUrl,\n\tresolveSecretKey,\n} from \"../constants\";\nimport { RateLimitError, SylphxError, exponentialBackoff } from \"../errors\";\nimport type { SylphxErrorCode } from \"../errors\";\nimport { validateAndSanitizeSecretKey } from \"../key-validation\";\nimport type { KvRateLimitResult, KvSetOptions, KvZMember } from \"../kv-types\";\n\n// Re-export shared types for consumer convenience\nexport type { KvSetOptions, KvRateLimitResult, KvZMember } from \"../kv-types\";\n\n// ============================================\n// Types\n// ============================================\n\nexport interface KvClientOptions {\n\t/** Secret key for authentication (default: SYLPHX_SECRET_KEY env var) */\n\tsecretKey?: string;\n\t/** Platform URL (default: SYLPHX_PLATFORM_URL env var or https://sylphx.com) */\n\tplatformUrl?: string;\n}\n\n// ============================================\n// KV Client\n// ============================================\n\nexport interface KvClient {\n\t// ==========================================\n\t// Basic String Operations\n\t// ==========================================\n\n\t/**\n\t * Get a value by key\n\t *\n\t * @param key - Key name\n\t * @returns The value, or null if not found\n\t */\n\tget<T = unknown>(\n\t\tkey: string,\n\t): Promise<{ value: T | null; ttl: number | null }>;\n\n\t/**\n\t * Set a value\n\t *\n\t * @param key - Key name\n\t * @param value - Any JSON-serializable value\n\t * @param options - TTL and conditional options (ex, px, nx, xx)\n\t * @returns Whether the SET was successful\n\t */\n\tset<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\toptions?: KvSetOptions,\n\t): Promise<boolean>;\n\n\t/**\n\t * Delete a key\n\t *\n\t * @param key - Key name\n\t * @returns Number of keys deleted (0 or 1)\n\t */\n\tdel(key: string): Promise<number>;\n\n\t/**\n\t * Check if a key exists\n\t *\n\t * @param key - Key name\n\t * @returns Whether the key exists\n\t */\n\texists(key: string): Promise<boolean>;\n\n\t// ==========================================\n\t// Multiple Key Operations\n\t// ==========================================\n\n\t/**\n\t * Get multiple values\n\t *\n\t * @param keys - Array of keys to get (max 100)\n\t * @returns Map of key -> value (null if not found)\n\t */\n\tmget<T = unknown>(keys: string[]): Promise<Record<string, T | null>>;\n\n\t/**\n\t * Set multiple values\n\t *\n\t * @param entries - Array of { key, value } pairs (max 100)\n\t * @param options - TTL options (ex or px only)\n\t */\n\tmset<T = unknown>(\n\t\tentries: Array<{ key: string; value: T }>,\n\t\toptions?: Pick<KvSetOptions, \"ex\" | \"px\">,\n\t): Promise<void>;\n\n\t// ==========================================\n\t// Counter Operations\n\t// ==========================================\n\n\t/**\n\t * Increment a numeric value atomically\n\t *\n\t * Creates key with value 0 if it does not exist.\n\t *\n\t * @param key - Key name\n\t * @param by - Amount to increment by (default: 1, use negative for decrement)\n\t * @returns The value after increment\n\t */\n\tincr(key: string, by?: number): Promise<number>;\n\n\t// ==========================================\n\t// Expiration\n\t// ==========================================\n\n\t/**\n\t * Set key expiration\n\t *\n\t * @param key - Key name\n\t * @param seconds - TTL in seconds\n\t * @returns Whether the TTL was set (false if key does not exist)\n\t */\n\texpire(key: string, seconds: number): Promise<boolean>;\n\n\t// ==========================================\n\t// Rate Limiting\n\t// ==========================================\n\n\t/**\n\t * Check rate limit using sliding window algorithm\n\t *\n\t * @param key - Rate limit identifier (e.g., \"api:user123\")\n\t * @param options - Limit and window configuration\n\t * @returns Rate limit status\n\t *\n\t * @example\n\t * ```ts\n\t * const { success, remaining, reset } = await kv.ratelimit('api:user123', {\n\t * limit: 100,\n\t * window: '1h',\n\t * })\n\t *\n\t * if (!success) {\n\t * throw new Error('Rate limit exceeded')\n\t * }\n\t * ```\n\t */\n\tratelimit(\n\t\tkey: string,\n\t\toptions: { limit: number; window: string },\n\t): Promise<KvRateLimitResult>;\n\n\t// ==========================================\n\t// Hash Operations\n\t// ==========================================\n\n\t/**\n\t * Set hash fields\n\t *\n\t * @param key - Hash key\n\t * @param fields - Field-value pairs to set\n\t * @returns Number of fields that were created (not updated)\n\t */\n\thset<T = unknown>(key: string, fields: Record<string, T>): Promise<number>;\n\n\t/**\n\t * Get a hash field\n\t *\n\t * @param key - Hash key\n\t * @param field - Field name\n\t * @returns Field value, or null if not found\n\t */\n\thget<T = unknown>(key: string, field: string): Promise<T | null>;\n\n\t/**\n\t * Get all hash fields\n\t *\n\t * @param key - Hash key\n\t * @returns All field-value pairs, or null if key does not exist\n\t */\n\thgetall<T = unknown>(key: string): Promise<Record<string, T> | null>;\n\n\t// ==========================================\n\t// List Operations\n\t// ==========================================\n\n\t/**\n\t * Push values to the left of a list\n\t *\n\t * @param key - List key\n\t * @param values - Values to push\n\t * @returns Length of the list after push\n\t */\n\tlpush<T = unknown>(key: string, ...values: T[]): Promise<number>;\n\n\t/**\n\t * Get a range of elements from a list\n\t *\n\t * @param key - List key\n\t * @param start - Start index (0-based, negative for from end)\n\t * @param stop - Stop index (inclusive, -1 for end)\n\t * @returns Values in the specified range\n\t */\n\tlrange<T = unknown>(key: string, start?: number, stop?: number): Promise<T[]>;\n\n\t// ==========================================\n\t// Sorted Set Operations (Leaderboards)\n\t// ==========================================\n\n\t/**\n\t * Add members with scores to a sorted set\n\t *\n\t * @param key - Sorted set key\n\t * @param members - Score-member pairs\n\t * @returns Number of members added (not updated)\n\t */\n\tzadd(\n\t\tkey: string,\n\t\t...members: Array<{ score: number; member: string }>\n\t): Promise<number>;\n\n\t/**\n\t * Get members from a sorted set by rank range\n\t *\n\t * @param key - Sorted set key\n\t * @param start - Start rank (0-based)\n\t * @param stop - Stop rank (inclusive)\n\t * @param options - Include scores and/or reverse order\n\t * @returns Members in the specified range\n\t */\n\tzrange(\n\t\tkey: string,\n\t\tstart?: number,\n\t\tstop?: number,\n\t\toptions?: { withScores?: boolean; rev?: boolean },\n\t): Promise<KvZMember[]>;\n}\n\n/**\n * Create a server-side KV client\n *\n * Uses environment variables by default:\n * - SYLPHX_PLATFORM_URL: Platform URL (default: https://sylphx.com)\n * - SYLPHX_SECRET_KEY: Your app's secret key (sk_dev_xxx, sk_stg_xxx, sk_prod_xxx)\n */\nexport function createKv(options: KvClientOptions = {}): KvClient {\n\tconst platformUrl = resolvePlatformUrl(options.platformUrl);\n\tconst secretKey = validateAndSanitizeSecretKey(\n\t\tresolveSecretKey(options.secretKey),\n\t);\n\n\tconst headers = {\n\t\t\"Content-Type\": \"application/json\",\n\t\t\"x-app-secret\": secretKey,\n\t\t\"X-SDK-Version\": SDK_VERSION,\n\t\t\"X-SDK-Platform\": SDK_PLATFORM,\n\t};\n\n\t// Helper for API calls with retry logic and SylphxError wrapping\n\tasync function request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tlet lastError: Error | undefined;\n\n\t\tfor (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\t`${platformUrl}${SDK_API_PATH}/kv${path}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tconst errorBody = await response\n\t\t\t\t\t\t.json()\n\t\t\t\t\t\t.catch(() => ({ error: \"Request failed\" }));\n\t\t\t\t\tconst message =\n\t\t\t\t\t\ttypeof errorBody.error === \"string\"\n\t\t\t\t\t\t\t? errorBody.error\n\t\t\t\t\t\t\t: (errorBody.error?.message ?? \"Request failed\");\n\n\t\t\t\t\tif (response.status === 429) {\n\t\t\t\t\t\tconst retryAfter =\n\t\t\t\t\t\t\tNumber(response.headers.get(\"Retry-After\")) || undefined;\n\t\t\t\t\t\tthrow new RateLimitError(message, {\n\t\t\t\t\t\t\tretryAfter,\n\t\t\t\t\t\t\tlimit:\n\t\t\t\t\t\t\t\tNumber(response.headers.get(\"X-RateLimit-Limit\")) || undefined,\n\t\t\t\t\t\t\tremaining:\n\t\t\t\t\t\t\t\tNumber(response.headers.get(\"X-RateLimit-Remaining\")) ||\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst codeMap: Record<number, SylphxErrorCode> = {\n\t\t\t\t\t\t400: \"BAD_REQUEST\",\n\t\t\t\t\t\t401: \"UNAUTHORIZED\",\n\t\t\t\t\t\t403: \"FORBIDDEN\",\n\t\t\t\t\t\t404: \"NOT_FOUND\",\n\t\t\t\t\t\t409: \"CONFLICT\",\n\t\t\t\t\t\t422: \"UNPROCESSABLE_ENTITY\",\n\t\t\t\t\t\t500: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\t\t502: \"BAD_GATEWAY\",\n\t\t\t\t\t\t503: \"SERVICE_UNAVAILABLE\",\n\t\t\t\t\t\t504: \"GATEWAY_TIMEOUT\",\n\t\t\t\t\t};\n\t\t\t\t\tthrow new SylphxError(message, {\n\t\t\t\t\t\tcode: codeMap[response.status] ?? \"UNKNOWN\",\n\t\t\t\t\t\tstatus: response.status,\n\t\t\t\t\t\tdata: errorBody.data,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn response.json() as Promise<T>;\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\n\t\t\t\t// Only auto-retry on server errors (5xx) and network failures.\n\t\t\t\t// Never auto-retry client errors (4xx) including 429 — callers should\n\t\t\t\t// handle rate limits using the RateLimitError.retryAfter value.\n\t\t\t\tconst isServerOrNetworkError =\n\t\t\t\t\terror instanceof SylphxError\n\t\t\t\t\t\t? error.isRetryable && error.code !== \"TOO_MANY_REQUESTS\"\n\t\t\t\t\t\t: error instanceof TypeError; // fetch network errors\n\t\t\t\tif (!isServerOrNetworkError || attempt >= MAX_RETRIES) {\n\t\t\t\t\tthrow error instanceof SylphxError\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new SylphxError(lastError.message, {\n\t\t\t\t\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\t\t\t\t\tcause: lastError,\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tawait new Promise((resolve) =>\n\t\t\t\t\tsetTimeout(resolve, exponentialBackoff(attempt)),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthrow lastError ?? new SylphxError(\"Request failed\", { code: \"UNKNOWN\" });\n\t}\n\n\t// ==========================================\n\t// Implementation\n\t// ==========================================\n\n\tasync function get<T>(\n\t\tkey: string,\n\t): Promise<{ value: T | null; ttl: number | null }> {\n\t\treturn request<{ value: T | null; ttl: number | null }>(\n\t\t\t\"GET\",\n\t\t\t`/${encodeURIComponent(key)}`,\n\t\t);\n\t}\n\n\tasync function set<T>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\toptions?: KvSetOptions,\n\t): Promise<boolean> {\n\t\tconst result = await request<{ success: boolean }>(\"POST\", \"\", {\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\t...options,\n\t\t});\n\t\treturn result.success;\n\t}\n\n\tasync function del(key: string): Promise<number> {\n\t\tconst result = await request<{ deleted: number }>(\n\t\t\t\"DELETE\",\n\t\t\t`/${encodeURIComponent(key)}`,\n\t\t);\n\t\treturn result.deleted;\n\t}\n\n\tasync function exists(key: string): Promise<boolean> {\n\t\tconst result = await request<{ exists: boolean }>(\n\t\t\t\"GET\",\n\t\t\t`/exists/${encodeURIComponent(key)}`,\n\t\t);\n\t\treturn result.exists;\n\t}\n\n\tasync function mget<T>(keys: string[]): Promise<Record<string, T | null>> {\n\t\tconst result = await request<{ values: Record<string, T | null> }>(\n\t\t\t\"POST\",\n\t\t\t\"/mget\",\n\t\t\t{ keys },\n\t\t);\n\t\treturn result.values;\n\t}\n\n\tasync function mset<T>(\n\t\tentries: Array<{ key: string; value: T }>,\n\t\toptions?: Pick<KvSetOptions, \"ex\" | \"px\">,\n\t): Promise<void> {\n\t\tawait request<{ success: boolean }>(\"POST\", \"/mset\", {\n\t\t\tentries,\n\t\t\t...options,\n\t\t});\n\t}\n\n\tasync function incr(key: string, by = 1): Promise<number> {\n\t\tconst result = await request<{ value: number }>(\"POST\", \"/incr\", {\n\t\t\tkey,\n\t\t\tby,\n\t\t});\n\t\treturn result.value;\n\t}\n\n\tasync function expire(key: string, seconds: number): Promise<boolean> {\n\t\tconst result = await request<{ success: boolean }>(\"POST\", \"/expire\", {\n\t\t\tkey,\n\t\t\tseconds,\n\t\t});\n\t\treturn result.success;\n\t}\n\n\tasync function ratelimit(\n\t\tkey: string,\n\t\toptions: { limit: number; window: string },\n\t): Promise<KvRateLimitResult> {\n\t\treturn request<KvRateLimitResult>(\"POST\", \"/ratelimit\", {\n\t\t\tkey,\n\t\t\t...options,\n\t\t});\n\t}\n\n\tasync function hset<T>(\n\t\tkey: string,\n\t\tfields: Record<string, T>,\n\t): Promise<number> {\n\t\tconst result = await request<{ created: number }>(\"POST\", \"/hset\", {\n\t\t\tkey,\n\t\t\tfields,\n\t\t});\n\t\treturn result.created;\n\t}\n\n\tasync function hget<T>(key: string, field: string): Promise<T | null> {\n\t\tconst result = await request<{ value: T | null }>(\"POST\", \"/hget\", {\n\t\t\tkey,\n\t\t\tfield,\n\t\t});\n\t\treturn result.value;\n\t}\n\n\tasync function hgetall<T>(key: string): Promise<Record<string, T> | null> {\n\t\tconst result = await request<{ fields: Record<string, T> | null }>(\n\t\t\t\"POST\",\n\t\t\t\"/hgetall\",\n\t\t\t{ key },\n\t\t);\n\t\treturn result.fields;\n\t}\n\n\tasync function lpush<T>(key: string, ...values: T[]): Promise<number> {\n\t\tconst result = await request<{ length: number }>(\"POST\", \"/lpush\", {\n\t\t\tkey,\n\t\t\tvalues,\n\t\t});\n\t\treturn result.length;\n\t}\n\n\tasync function lrange<T>(key: string, start = 0, stop = -1): Promise<T[]> {\n\t\tconst result = await request<{ values: T[] }>(\"POST\", \"/lrange\", {\n\t\t\tkey,\n\t\t\tstart,\n\t\t\tstop,\n\t\t});\n\t\treturn result.values;\n\t}\n\n\tasync function zadd(\n\t\tkey: string,\n\t\t...members: Array<{ score: number; member: string }>\n\t): Promise<number> {\n\t\tconst result = await request<{ added: number }>(\"POST\", \"/zadd\", {\n\t\t\tkey,\n\t\t\tmembers,\n\t\t});\n\t\treturn result.added;\n\t}\n\n\tasync function zrange(\n\t\tkey: string,\n\t\tstart = 0,\n\t\tstop = 9,\n\t\toptions?: { withScores?: boolean; rev?: boolean },\n\t): Promise<KvZMember[]> {\n\t\tconst result = await request<{ members: KvZMember[] }>(\"POST\", \"/zrange\", {\n\t\t\tkey,\n\t\t\tstart,\n\t\t\tstop,\n\t\t\twithScores: options?.withScores ?? false,\n\t\t\trev: options?.rev ?? false,\n\t\t});\n\t\treturn result.members;\n\t}\n\n\treturn {\n\t\tget,\n\t\tset,\n\t\tdel,\n\t\texists,\n\t\tmget,\n\t\tmset,\n\t\tincr,\n\t\texpire,\n\t\tratelimit,\n\t\thset,\n\t\thget,\n\t\thgetall,\n\t\tlpush,\n\t\tlrange,\n\t\tzadd,\n\t\tzrange,\n\t};\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultClient: KvClient | null = null;\n\n/**\n * Get the default KV client (singleton)\n * Creates one using environment variables on first call\n */\nexport function getKv(): KvClient {\n\tif (!defaultClient) {\n\t\tdefaultClient = createKv();\n\t}\n\treturn defaultClient;\n}\n","/**\n * Server-side Streams Client\n *\n * Creates a client for real-time pub/sub via Redis Streams.\n * Use this in Server Components, API routes, and server actions.\n *\n * @example\n * ```ts\n * import { createStreams } from '@sylphx/sdk/server'\n *\n * const streams = createStreams()\n *\n * // Emit an event\n * const id = await streams.emit('chat:room-1', 'message', {\n * text: 'Hello!',\n * userId: '123',\n * })\n *\n * // Get message history\n * const messages = await streams.history('chat:room-1', { limit: 50 })\n *\n * // Using channel helper\n * const room = streams.channel('chat:room-1')\n * await room.emit('message', { text: 'Hello!' })\n * const history = await room.history({ limit: 50 })\n * ```\n */\n\nimport { DEFAULT_PLATFORM_URL, SDK_API_PATH } from \"../constants\";\nimport { validateAndSanitizeSecretKey } from \"../key-validation\";\nimport type { StreamMessage } from \"../realtime-types\";\n\n// Re-export shared type for consumers who import from server\nexport type { StreamMessage };\n\n// ============================================\n// Types\n// ============================================\n\nexport interface StreamsClientOptions {\n\t/** Secret key for authentication (default: SYLPHX_SECRET_KEY env var) */\n\tsecretKey?: string;\n\t/** Platform URL (default: SYLPHX_PLATFORM_URL env var or https://sylphx.com) */\n\tplatformUrl?: string;\n}\n\n/** Options for fetching stream history */\nexport interface StreamHistoryOptions {\n\t/** Start ID (\"-\" for oldest) */\n\tstart?: string;\n\t/** End ID (\"+\" for newest) */\n\tend?: string;\n\t/** Maximum number of messages (max 1000) */\n\tlimit?: number;\n}\n\n/** Helper for a specific channel */\nexport interface ChannelHelper {\n\t/** Emit an event to this channel */\n\temit<T>(event: string, data: T): Promise<string>;\n\t/** Get message history for this channel */\n\thistory<T>(options?: StreamHistoryOptions): Promise<StreamMessage<T>[]>;\n}\n\n// ============================================\n// Streams Client\n// ============================================\n\nexport interface StreamsClient {\n\t/**\n\t * Emit an event to a channel\n\t *\n\t * @param channel - Channel name (e.g., \"chat:room-1\")\n\t * @param event - Event type (e.g., \"message\")\n\t * @param data - Event data (any JSON-serializable value)\n\t * @returns Stream entry ID\n\t */\n\temit<T>(channel: string, event: string, data: T): Promise<string>;\n\n\t/**\n\t * Get message history for a channel\n\t *\n\t * @param channel - Channel name\n\t * @param options - History options (start, end, limit)\n\t * @returns Array of messages in chronological order\n\t */\n\thistory<T>(\n\t\tchannel: string,\n\t\toptions?: StreamHistoryOptions,\n\t): Promise<StreamMessage<T>[]>;\n\n\t/**\n\t * Get a channel helper for convenient operations\n\t *\n\t * @param channel - Channel name\n\t * @returns Channel helper with emit() and history()\n\t */\n\tchannel(name: string): ChannelHelper;\n}\n\n/**\n * Create a server-side Streams client\n *\n * Uses environment variables by default:\n * - SYLPHX_PLATFORM_URL: Platform URL (default: https://sylphx.com)\n * - SYLPHX_SECRET_KEY: Your app's secret key (sk_dev_xxx, sk_stg_xxx, sk_prod_xxx)\n */\nexport function createStreams(\n\toptions: StreamsClientOptions = {},\n): StreamsClient {\n\tconst baseURL = (\n\t\toptions.platformUrl ||\n\t\tprocess.env.SYLPHX_PLATFORM_URL ||\n\t\tDEFAULT_PLATFORM_URL\n\t).trim();\n\tconst rawApiKey = options.secretKey || process.env.SYLPHX_SECRET_KEY;\n\n\t// Validate and sanitize API key using SSOT\n\tconst apiKey = validateAndSanitizeSecretKey(rawApiKey);\n\n\tconst headers = {\n\t\t\"Content-Type\": \"application/json\",\n\t\t\"x-app-secret\": apiKey,\n\t};\n\n\tasync function emit<T>(\n\t\tchannel: string,\n\t\tevent: string,\n\t\tdata: T,\n\t): Promise<string> {\n\t\tconst response = await fetch(`${baseURL}${SDK_API_PATH}/realtime/emit`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({ channel, event, data }),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response\n\t\t\t\t.json()\n\t\t\t\t.catch(() => ({ error: \"Emit failed\" }));\n\t\t\tthrow new Error(\n\t\t\t\ttypeof error.error === \"string\" ? error.error : \"Emit failed\",\n\t\t\t);\n\t\t}\n\n\t\tconst result = (await response.json()) as { id: string };\n\t\treturn result.id;\n\t}\n\n\tasync function history<T>(\n\t\tchannel: string,\n\t\toptions?: StreamHistoryOptions,\n\t): Promise<StreamMessage<T>[]> {\n\t\tconst response = await fetch(`${baseURL}${SDK_API_PATH}/realtime/history`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tchannel,\n\t\t\t\tstart: options?.start,\n\t\t\t\tend: options?.end,\n\t\t\t\tlimit: options?.limit,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response\n\t\t\t\t.json()\n\t\t\t\t.catch(() => ({ error: \"History fetch failed\" }));\n\t\t\tthrow new Error(\n\t\t\t\ttypeof error.error === \"string\" ? error.error : \"History fetch failed\",\n\t\t\t);\n\t\t}\n\n\t\tconst result = (await response.json()) as { messages: StreamMessage<T>[] };\n\t\treturn result.messages;\n\t}\n\n\tfunction channelHelper(name: string): ChannelHelper {\n\t\treturn {\n\t\t\temit: <T>(event: string, data: T) => emit(name, event, data),\n\t\t\thistory: <T>(options?: StreamHistoryOptions) => history<T>(name, options),\n\t\t};\n\t}\n\n\treturn {\n\t\temit,\n\t\thistory,\n\t\tchannel: channelHelper,\n\t};\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultClient: StreamsClient | null = null;\n\n/**\n * Get the default Streams client (singleton)\n * Creates one using environment variables on first call\n */\nexport function getStreams(): StreamsClient {\n\tif (!defaultClient) {\n\t\tdefaultClient = createStreams();\n\t}\n\treturn defaultClient;\n}\n"],"mappings":"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","names":["message","message","message","message","createClient","decoder","message","options","defaultClient","options","defaultClient","message","encoder"]}
|