@spfn/core 0.2.0-beta.14 → 0.2.0-beta.15

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.
@@ -1,6 +1,6 @@
1
1
  import { Router, RouteDef } from '@spfn/core/route';
2
- import { R as RequestInterceptor, a as ResponseInterceptor, I as InferRouteInput, b as InferRouteOutput, A as ApiConfig } from '../types-DP8nzQcY.js';
3
- export { C as CallOptions, e as CookieOptions, c as RouterInput, d as RouterOutput, f as SetCookie, S as StructuredInput } from '../types-DP8nzQcY.js';
2
+ import { R as RequestInterceptor, a as ResponseInterceptor, I as InferRouteInput, b as InferRouteOutput, A as ApiConfig } from '../types-7Mhoxnnt.js';
3
+ export { C as CallOptions, e as CookieOptions, c as RouterInput, d as RouterOutput, f as SetCookie, S as StructuredInput } from '../types-7Mhoxnnt.js';
4
4
  import '@sinclair/typebox';
5
5
  import '@spfn/core/errors';
6
6
 
@@ -267,7 +267,7 @@ function createApi(config = {}) {
267
267
  const {
268
268
  baseUrl = "/api/rpc",
269
269
  headers: defaultHeaders = {},
270
- timeout = 3e4,
270
+ timeout = env.SERVER_TIMEOUT,
271
271
  fetch: customFetch = fetch,
272
272
  onRequest: globalOnRequest,
273
273
  onResponse: globalOnResponse,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/nextjs/client/debug-logs.ts","../../src/nextjs/client/errors.ts","../../src/nextjs/shared.ts","../../src/nextjs/client/helpers.ts","../../src/nextjs/client/builder.ts","../../src/nextjs/client/core.ts"],"names":["logger","errorRegistry","coreErrorRegistry","headers"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Debug logging utilities for API client\n * Separates debug logging logic from main client code for better maintainability\n */\nimport type { Logger } from '@spfn/core/logger';\n\nexport function logCookieAutoDetection(\n logger: Logger,\n cookies: Array<{ name: string; value: string }>\n): void\n{\n logger.debug('Auto-detected server environment, forwarding cookies', {\n cookieCount: cookies.length,\n cookieNames: cookies.map(c => c.name),\n });\n}\n\nexport function logRequest(\n logger: Logger,\n routeName: string,\n method: string,\n url: string,\n hasBody: boolean\n): void\n{\n logger.debug('→ Request', {\n route: routeName,\n method,\n url,\n hasBody,\n });\n}\n\nexport function logResponse(\n logger: Logger,\n routeName: string,\n status: number,\n hasBody: boolean\n): void\n{\n logger.debug('← Response', {\n route: routeName,\n status,\n hasBody,\n });\n}\n\nexport function logErrorResponse(\n logger: Logger,\n status: number,\n body: any\n): void\n{\n logger.debug('Error response received', {\n status,\n hasBody: !!body,\n bodyType: typeof body,\n hasTypeField: body && typeof body === 'object' && '__type' in body,\n typeValue: body?.__type,\n });\n}\n\nexport function logErrorDeserializationAttempt(\n logger: Logger,\n errorType: string,\n registeredTypes: string[]\n): void\n{\n logger.debug('Attempting error deserialization', {\n errorType,\n hasRegistry: true,\n registeredTypes,\n });\n}\n\nexport function logErrorDeserializationSuccess(\n logger: Logger,\n error: Error | null\n): void\n{\n logger.debug('Error deserialized successfully', {\n errorName: error?.name,\n errorConstructor: error?.constructor.name,\n message: error?.message,\n });\n}\n\nexport function logErrorDeserializationFailure(\n logger: Logger,\n error: unknown\n): void\n{\n logger.debug('Deserialization failed', {\n errorName: error instanceof Error ? error.name : 'unknown',\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n}\n\nexport function logErrorDeserializationSkipped(\n logger: Logger,\n errorRegistry: any,\n body: any\n): void\n{\n const reason = !errorRegistry\n ? 'no registry'\n : !body\n ? 'no body'\n : typeof body !== 'object'\n ? 'body not object'\n : !('__type' in body)\n ? 'no __type field'\n : 'unknown';\n\n logger.debug('Skipping error deserialization', { reason });\n}\n\nexport function logThrowingDeserializedError(\n logger: Logger,\n error: Error\n): void\n{\n logger.debug('Throwing deserialized error', {\n errorName: error.name,\n errorConstructorName: error.constructor.name,\n prototype: Object.getPrototypeOf(error).constructor.name,\n });\n}","// ============================================================================\n// Client Error\n// ============================================================================\n\n/**\n * Typed client error\n */\nexport class ApiError extends Error\n{\n constructor(\n message: string,\n public readonly status: number,\n public readonly url: string,\n public readonly response?: unknown,\n public readonly errorType?: 'http' | 'network' | 'timeout'\n )\n {\n super(message);\n this.name = 'ApiError';\n }\n}","/**\n * Shared utilities for Next.js client and proxy modules\n *\n * Contains common functions used by both client and proxy to avoid code duplication.\n */\n\n/**\n * Build URL with path parameters replaced\n *\n * @example\n * buildUrlWithParams('/users/:id/posts/:postId', { id: '123', postId: '456' })\n * // Returns: '/users/123/posts/456'\n */\nexport function buildUrlWithParams(path: string, params: Record<string, any>): string\n{\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n return url;\n}\n\n/**\n * Build query string from object\n *\n * @example\n * buildQueryString({ page: '1', limit: '10', tags: ['foo', 'bar'] })\n * // Returns: '?page=1&limit=10&tags=foo&tags=bar'\n */\nexport function buildQueryString(query: Record<string, any>): string\n{\n if (Object.keys(query).length === 0)\n {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => searchParams.append(key, String(v)));\n }\n else\n {\n searchParams.append(key, String(value));\n }\n }\n\n return `?${searchParams.toString()}`;\n}\n\n/**\n * Build Cookie header string from cookies object\n *\n * @example\n * buildCookieHeader({ session: 'abc123', theme: 'dark' })\n * // Returns: 'session=abc123; theme=dark'\n */\nexport function buildCookieHeader(cookies: Record<string, string>): string\n{\n return Object.entries(cookies)\n .map(([key, value]) => `${key}=${value}`)\n .join('; ');\n}\n\n/**\n * Parse response body based on content type\n *\n * Handles:\n * - 204 No Content: returns null (no body expected)\n * - application/json: parses JSON body\n * - Other content types: returns raw text\n */\nexport async function parseResponseBody(response: Response): Promise<any>\n{\n // 204 No Content has no body\n if (response.status === 204)\n {\n return null;\n }\n\n const contentType = response.headers.get('content-type');\n\n if (contentType?.includes('application/json'))\n {\n const text = await response.text();\n return text ? JSON.parse(text) : null;\n }\n else\n {\n return await response.text();\n }\n}","import type { Logger } from '@spfn/core/logger';\nimport type { ErrorRegistry } from '@spfn/core/errors';\nimport { ApiError } from './errors';\nimport * as debugLogs from './debug-logs';\n\n// Re-export shared utilities\nexport { buildCookieHeader, parseResponseBody } from '../shared';\n\n/**\n * Auto-detect cookies from Next.js server environment\n * Returns empty object if not in server environment or if cookies are not accessible\n */\nexport async function autoDetectServerCookies(): Promise<Record<string, string>>\n{\n try\n {\n // Next.js cookies() API is only available in server environment\n const { cookies } = await import('next/headers');\n const cookieStore = await cookies();\n const allCookies = cookieStore.getAll();\n\n return Object.fromEntries(\n allCookies.map(cookie => [cookie.name, cookie.value])\n );\n }\n catch (error)\n {\n // Client environment or cookies not accessible\n // Browser automatically sends cookies in client components\n return {};\n }\n}\n\n/**\n * Execute fetch with timeout and abort controller\n */\nexport async function executeFetchWithTimeout(\n url: string,\n init: RequestInit,\n timeout: number,\n customFetch: typeof fetch = fetch\n): Promise<Response>\n{\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try\n {\n const response = await customFetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n return response;\n }\n catch (error)\n {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n\n/**\n * Handle error response with deserialization support\n * Attempts to deserialize custom errors if errorRegistry is provided\n * Falls back to ApiError if deserialization fails or is not available\n */\nexport async function handleErrorResponse(\n response: Response,\n body: any,\n fullUrl: string,\n errorRegistry: ErrorRegistry | undefined,\n debug: boolean,\n logger: Logger\n): Promise<never>\n{\n if (debug)\n {\n debugLogs.logErrorResponse(logger, response.status, body);\n }\n\n // Try to deserialize error if registry is provided\n let deserializedError: Error | null = null;\n\n if (errorRegistry && body && typeof body === 'object' && '__type' in body)\n {\n if (debug)\n {\n debugLogs.logErrorDeserializationAttempt(logger, body.__type, errorRegistry.getRegisteredTypes());\n }\n\n try\n {\n deserializedError = errorRegistry.deserialize(body as any);\n\n if (debug)\n {\n debugLogs.logErrorDeserializationSuccess(logger, deserializedError);\n }\n }\n catch (deserializeError)\n {\n // Deserialization itself failed (type not found, invalid data, etc.)\n if (debug)\n {\n debugLogs.logErrorDeserializationFailure(logger, deserializeError);\n }\n // Fall through to ApiError below\n }\n }\n else if (debug)\n {\n debugLogs.logErrorDeserializationSkipped(logger, errorRegistry, body);\n }\n\n // If deserialization succeeded, throw the deserialized error\n if (deserializedError)\n {\n if (debug)\n {\n debugLogs.logThrowingDeserializedError(logger, deserializedError);\n }\n\n throw deserializedError;\n }\n\n // Fallback to generic ApiError\n if (response.status === 404 && process.env.NODE_ENV !== 'production')\n {\n logger.warn(\n '\\n⚠️ 404 Not Found\\n\\n' +\n 'Check the following:\\n' +\n ' 1. Routes are registered in server.config.ts:\\n' +\n ' → defineServerConfig().routes(appRouter)\\n' +\n ' 2. Delete .spfn cache if you recently added new routes:\\n' +\n ' → rm -rf .spfn\\n'\n );\n }\n\n throw new ApiError(\n body?.message || `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n fullUrl,\n body,\n 'http'\n );\n}","// ============================================================================\n// Route Call Builder (Structured Input API)\n// ============================================================================\n\nimport type { RouteDef, Router } from \"@spfn/core/route\";\nimport type {\n CallOptions,\n InferRouteInput,\n InferRouteOutput,\n RequestInterceptor,\n ResponseInterceptor,\n} from \"./types\";\n\n/**\n * Pick only non-empty fields from StructuredInput\n *\n * This removes fields that are empty objects `{}` from the input type,\n * so users only need to provide fields that are actually defined in the route.\n */\ntype PickNonEmpty<T> = {\n [K in keyof T as T[K] extends Record<string, never> ? never : K]: T[K];\n};\n\n/**\n * Make fields that can be undefined into optional fields\n *\n * When a field is defined as `Type.Optional(Type.Object({...}))`,\n * the resulting type is `T | undefined`. This utility converts such fields\n * into proper optional fields (`field?: T`) so users don't need to pass them.\n */\ntype MakeOptionalIfUndefinable<T> =\n // Required fields (undefined is not assignable)\n { [K in keyof T as undefined extends T[K] ? never : K]: T[K] }\n // Optional fields (undefined is assignable)\n & { [K in keyof T as undefined extends T[K] ? K : never]?: Exclude<T[K], undefined> };\n\n/**\n * Clean structured input - only include fields that have actual schema,\n * and make fields optional if they accept undefined\n */\ntype CleanStructuredInput<TInput> = MakeOptionalIfUndefinable<PickNonEmpty<TInput>>;\n\n/**\n * Check if input has any required fields\n *\n * Returns false if all fields are optional (i.e., {} is assignable to the input type)\n */\ntype HasAnyRequiredFields<TInput> = {} extends CleanStructuredInput<TInput> ? false : true;\n\n/**\n * Route call builder with structured input API\n *\n * Input is structured with explicit params, query, body fields\n * that match the server-side route definition.\n *\n * @example\n * ```typescript\n * // GET /users/:id - params only\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // GET /users/:id?include=posts - params + query\n * const user = await api.getUser.call({\n * params: { id: '1' },\n * query: { include: 'posts' }\n * });\n *\n * // POST /users - body only\n * const user = await api.createUser.call({\n * body: { name: 'John', email: 'john@example.com' }\n * });\n *\n * // PUT /users/:id - params + body\n * const user = await api.updateUser.call({\n * params: { id: '1' },\n * body: { name: 'Jane' }\n * });\n *\n * // With options (headers, cookies, Next.js caching)\n * const user = await api.getUser\n * .headers({ 'X-Custom': 'value' })\n * .fetchOptions({ next: { revalidate: 60 } })\n * .call({ params: { id: '1' } });\n * ```\n */\nexport class RouteCallBuilder<\n TInput,\n TOutput\n>\n{\n private _headers?: Record<string, string>;\n private _cookies?: Record<string, string>;\n private _fetchOptions?: RequestInit;\n private _onRequest?: RequestInterceptor;\n private _onResponse?: ResponseInterceptor;\n\n constructor(\n private readonly executor: (input: any, options: CallOptions) => Promise<TOutput>,\n private readonly routeName: string\n ) {}\n\n /**\n * Clone builder\n */\n private clone(): RouteCallBuilder<TInput, TOutput>\n {\n const builder = new RouteCallBuilder<TInput, TOutput>(\n this.executor,\n this.routeName\n );\n builder._headers = this._headers;\n builder._cookies = this._cookies;\n builder._fetchOptions = this._fetchOptions;\n builder._onRequest = this._onRequest;\n builder._onResponse = this._onResponse;\n return builder;\n }\n\n /**\n * Set request headers\n */\n headers(headers: Record<string, string>): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._headers = { ...this._headers, ...headers };\n return builder;\n }\n\n /**\n * Set cookies\n */\n cookies(cookies: Record<string, string>): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._cookies = { ...this._cookies, ...cookies };\n return builder;\n }\n\n /**\n * Set Next.js fetch options\n */\n fetchOptions(options: RequestInit & { next?: { revalidate?: number | false; tags?: string[] } }): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._fetchOptions = { ...this._fetchOptions, ...options };\n return builder;\n }\n\n /**\n * Set request interceptor\n */\n onRequest(interceptor: RequestInterceptor): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._onRequest = interceptor;\n return builder;\n }\n\n /**\n * Set response interceptor\n */\n onResponse(interceptor: ResponseInterceptor): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._onResponse = interceptor;\n return builder;\n }\n\n /**\n * Execute the API call with structured input\n *\n * Input structure matches the server-side route definition:\n * - params: Path parameters (e.g., { id: '123' } for /users/:id)\n * - query: Query string parameters\n * - body: Request body (for POST, PUT, PATCH)\n */\n call(input?: CleanStructuredInput<TInput>): Promise<TOutput>\n {\n const options: CallOptions = {};\n\n if (this._headers)\n {\n options.headers = this._headers;\n }\n\n if (this._cookies)\n {\n options.cookies = this._cookies;\n }\n\n if (this._fetchOptions)\n {\n options.fetchOptions = this._fetchOptions;\n }\n\n if (this._onRequest)\n {\n options.onRequest = this._onRequest;\n }\n\n if (this._onResponse)\n {\n options.onResponse = this._onResponse;\n }\n\n return this.executor(input || {}, options);\n }\n}\n\n/**\n * Individual route client with structured input API\n */\nexport type RouteClient<TRoute extends RouteDef<any, any>> = {\n /**\n * Set request headers\n */\n headers(headers: Record<string, string>): RouteClient<TRoute>;\n\n /**\n * Set cookies\n */\n cookies(cookies: Record<string, string>): RouteClient<TRoute>;\n\n /**\n * Set Next.js fetch options\n */\n fetchOptions(options: RequestInit & { next?: { revalidate?: number | false; tags?: string[] } }): RouteClient<TRoute>;\n\n /**\n * Set request interceptor\n */\n onRequest(interceptor: RequestInterceptor): RouteClient<TRoute>;\n\n /**\n * Set response interceptor\n */\n onResponse(interceptor: ResponseInterceptor): RouteClient<TRoute>;\n\n /**\n * Execute the API call with structured input\n *\n * @example\n * ```typescript\n * // GET /users/:id\n * api.getUser.call({ params: { id: '123' } });\n *\n * // PUT /users/:id\n * api.updateUser.call({ params: { id: '123' }, body: { name: 'Jane' } });\n * ```\n */\n call: HasAnyRequiredFields<InferRouteInput<TRoute>> extends true\n ? (input: CleanStructuredInput<InferRouteInput<TRoute>>) => Promise<InferRouteOutput<TRoute>>\n : (input?: CleanStructuredInput<InferRouteInput<TRoute>>) => Promise<InferRouteOutput<TRoute>>;\n};\n\n/**\n * Typed client for entire router\n */\nexport type Client<TRouter extends Router<any>> = {\n [K in keyof TRouter['routes']]: TRouter['routes'][K] extends RouteDef<any, any, any>\n ? RouteClient<TRouter['routes'][K]>\n : TRouter['routes'][K] extends Router<any>\n ? Client<TRouter['routes'][K]>\n : never;\n};","/**\n * Type-Safe RPC-Style Client with Structured Input API\n *\n * Provides full end-to-end type safety from server routes to client calls.\n * No metadata codegen required - method/path resolution happens at the proxy layer.\n *\n * @example\n * ```typescript\n * // Server\n * export const appRouter = defineRouter({\n * getUser: route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => { ... }),\n * createUser: route.post('/users')\n * .input({ body: Type.Object({ name: Type.String() }) })\n * .handler(async (c) => { ... }),\n * });\n *\n * export type AppRouter = typeof appRouter;\n *\n * // Client - no metadata needed!\n * const api = createApi<AppRouter>();\n *\n * // ✅ GET (no body) - becomes GET /api/rpc/getUser?input={...}\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // ✅ POST (has body) - becomes POST /api/rpc/createUser\n * const newUser = await api.createUser.call({ body: { name: 'John' } });\n *\n * // ✅ With options (headers, cookies, interceptors)\n * const user = await api.getUser\n * .headers({ 'X-Custom': 'value' })\n * .cookies({ session: 'xxx' })\n * .fetchOptions({ next: { revalidate: 60 } })\n * .call({ params: { id: '1' } });\n * ```\n */\nimport { env } from '@spfn/core/config';\nimport { ErrorRegistry, errorRegistry as coreErrorRegistry } from '@spfn/core/errors';\nimport { logger } from '@spfn/core/logger';\nimport type { Router } from '@spfn/core/route';\nimport * as debugLogs from './debug-logs';\nimport { ApiError } from \"./errors\";\nimport {\n parseResponseBody,\n executeFetchWithTimeout,\n handleErrorResponse,\n buildCookieHeader,\n autoDetectServerCookies,\n} from './helpers';\nimport { RouteCallBuilder } from './builder';\nimport type { ApiConfig, CallOptions } from \"./types\";\nimport type { Client } from \"./builder\";\n\nconst apiLogger = logger.child('@spfn/core:api-client');\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\n/**\n * Create type-safe RPC client\n *\n * No metadata required - the client sends routeName + input to the proxy,\n * and the proxy resolves the actual HTTP method and path from the router.\n *\n * @example\n * ```typescript\n * // Client - no metadata needed!\n * const api = createApi<AppRouter>();\n *\n * // GET request (no body) - browser cacheable\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // POST request (has body)\n * const newUser = await api.createUser.call({ body: { name: 'John' } });\n * ```\n */\nexport function createApi<TRouter extends Router<any>>(\n config: ApiConfig = {}\n): Client<TRouter>\n{\n const {\n baseUrl = '/api/rpc',\n headers: defaultHeaders = {},\n timeout = 30000,\n fetch: customFetch = fetch,\n onRequest: globalOnRequest,\n onResponse: globalOnResponse,\n errorRegistry: errorRegistryConfig,\n debug = false,\n } = config;\n\n // Normalize errorRegistry: always include coreErrorRegistry\n const errorRegistry = Array.isArray(errorRegistryConfig)\n ? new ErrorRegistry([coreErrorRegistry, ...errorRegistryConfig])\n : errorRegistryConfig ?? coreErrorRegistry;\n\n if (debug)\n {\n apiLogger.debug('API client initialized', { baseUrl });\n }\n\n /**\n * Execute API call\n *\n * Determines GET vs POST based on body/formData presence:\n * - No body/formData → GET /api/rpc/{routeName}?input={...}\n * - Has body → POST /api/rpc/{routeName} with JSON body\n * - Has formData → POST /api/rpc/{routeName} with multipart/form-data\n */\n async function executeCall(\n routeName: string,\n input: any = {},\n options: CallOptions = {}\n ): Promise<any>\n {\n const hasBody = input.body !== undefined;\n const hasFormData = input.formData !== undefined && Object.keys(input.formData).length > 0;\n const method = (hasBody || hasFormData) ? 'POST' : 'GET';\n\n // Build full URL - handle SSR case where SPFN_APP_URL might not be set\n let appUrl = env.SPFN_APP_URL || '';\n\n // In SSR environment, if SPFN_APP_URL is not set, try to get host from request headers\n if (!appUrl && typeof window === 'undefined')\n {\n try\n {\n const { headers } = await import('next/headers');\n const headersList = await headers();\n const host = headersList.get('host');\n const protocol = headersList.get('x-forwarded-proto') || 'http';\n if (host)\n {\n appUrl = `${protocol}://${host}`;\n if (debug)\n {\n apiLogger.debug(`Auto-detected app URL from headers: ${appUrl}`);\n }\n }\n }\n catch\n {\n // Fallback: use relative URL and let fetch handle it\n if (debug)\n {\n apiLogger.warn('Could not determine app URL in SSR environment, using relative URL');\n }\n }\n }\n\n // Build URL based on method\n let fullUrl: string;\n if (method === 'GET')\n {\n // GET: encode input in query string\n const inputParam = encodeURIComponent(JSON.stringify(input));\n fullUrl = `${appUrl}${baseUrl}/${routeName}?input=${inputParam}`;\n }\n else\n {\n // POST: input goes in body\n fullUrl = `${appUrl}${baseUrl}/${routeName}`;\n }\n\n // Prepare headers\n // Note: Don't set Content-Type for formData - browser sets it with boundary\n const headers: Record<string, string> = {\n ...(hasFormData ? {} : { 'Content-Type': 'application/json' }),\n ...defaultHeaders,\n ...options.headers,\n };\n\n // Auto-detect server cookies and merge with user-provided cookies\n const autoDetectedCookies = await autoDetectServerCookies();\n const cookiesToSend = {\n ...autoDetectedCookies,\n ...(options.cookies || {}),\n };\n\n // Add Cookie header if we have cookies to send\n if (Object.keys(cookiesToSend).length > 0)\n {\n headers['Cookie'] = buildCookieHeader(cookiesToSend);\n }\n\n // Log cookie auto-detection if debug enabled\n if (debug && Object.keys(autoDetectedCookies).length > 0)\n {\n const cookieArray = Object.entries(autoDetectedCookies).map(([name, value]) => ({ name, value }));\n debugLogs.logCookieAutoDetection(apiLogger, cookieArray);\n }\n\n // Build request init\n const requestInit: RequestInit = {\n method,\n headers,\n ...options.fetchOptions,\n };\n\n // Add body for POST\n if (method === 'POST')\n {\n if (hasFormData)\n {\n // Build FormData for file uploads\n const formData = new FormData();\n\n // Add non-formData fields (params, query, headers, cookies) as JSON metadata\n const metadata: Record<string, any> = {};\n if (input.params) metadata.params = input.params;\n if (input.query) metadata.query = input.query;\n if (input.headers) metadata.headers = input.headers;\n if (input.cookies) metadata.cookies = input.cookies;\n\n if (Object.keys(metadata).length > 0)\n {\n formData.append('__metadata', JSON.stringify(metadata));\n }\n\n // Add formData fields\n for (const [key, value] of Object.entries(input.formData))\n {\n if (value instanceof File)\n {\n formData.append(key, value);\n }\n else if (Array.isArray(value))\n {\n // Handle array of files or values\n for (const item of value)\n {\n if (item instanceof File)\n {\n formData.append(key, item);\n }\n else\n {\n formData.append(key, String(item));\n }\n }\n }\n else if (value !== undefined && value !== null)\n {\n formData.append(key, String(value));\n }\n }\n\n requestInit.body = formData;\n }\n else\n {\n requestInit.body = JSON.stringify(input);\n }\n }\n\n // Execute request interceptors\n let init = requestInit;\n if (globalOnRequest)\n {\n init = await globalOnRequest(fullUrl, init);\n }\n if (options.onRequest)\n {\n init = await options.onRequest(fullUrl, init);\n }\n\n if (debug)\n {\n debugLogs.logRequest(apiLogger, routeName, method, fullUrl, !!init.body);\n }\n\n // Execute fetch with timeout\n let response: Response;\n let body: any;\n\n try\n {\n response = await executeFetchWithTimeout(fullUrl, init, timeout, customFetch);\n\n // Parse response\n body = await parseResponseBody(response);\n\n // Execute global + local response interceptors\n if (globalOnResponse)\n {\n const result = await globalOnResponse(response, body);\n response = result.response;\n body = result.body;\n }\n if (options.onResponse)\n {\n const result = await options.onResponse(response, body);\n response = result.response;\n body = result.body;\n }\n\n if (debug)\n {\n debugLogs.logResponse(apiLogger, routeName, response.status, !!body);\n }\n }\n catch (error)\n {\n // Handle timeout specifically\n if (error instanceof Error && error.name === 'AbortError')\n {\n apiLogger.error('Request timeout', {\n route: routeName,\n method,\n url: fullUrl,\n timeout,\n });\n\n throw new ApiError(\n `Request timeout after ${timeout}ms`,\n 408,\n fullUrl,\n undefined,\n 'timeout'\n );\n }\n\n // Network error\n const errorMessage = error instanceof Error ? error.message : 'Network error';\n apiLogger.error('Network error', {\n route: routeName,\n method,\n url: fullUrl,\n error: errorMessage,\n errorName: error instanceof Error ? error.name : 'unknown',\n });\n\n throw new ApiError(\n errorMessage,\n 0,\n fullUrl,\n undefined,\n 'network'\n );\n }\n\n // Handle error responses\n if (!response.ok)\n {\n await handleErrorResponse(response, body, fullUrl, errorRegistry, debug, apiLogger);\n }\n\n return body;\n }\n\n /**\n * Build client proxy\n *\n * Every property access returns a RouteCallBuilder.\n * Nested routers are supported via dot notation in routeName.\n */\n function buildProxy(prefix = ''): any\n {\n return new Proxy(\n {},\n {\n get(_target, prop: string)\n {\n const currentPath = prefix ? `${prefix}.${prop}` : prop;\n\n // Return RouteCallBuilder that can either be called or chained\n return new RouteCallBuilder(\n (input: any, options: CallOptions) => executeCall(currentPath, input, options),\n currentPath\n );\n },\n }\n );\n }\n\n return buildProxy() as Client<TRouter>;\n}"]}
1
+ {"version":3,"sources":["../../src/nextjs/client/debug-logs.ts","../../src/nextjs/client/errors.ts","../../src/nextjs/shared.ts","../../src/nextjs/client/helpers.ts","../../src/nextjs/client/builder.ts","../../src/nextjs/client/core.ts"],"names":["logger","errorRegistry","coreErrorRegistry","headers"],"mappings":";;;;;;;AAMO,SAAS,sBAAA,CACZA,SACA,OAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,sDAAA,EAAwD;AAAA,IACjE,aAAa,OAAA,CAAQ,MAAA;AAAA,IACrB,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAI;AAAA,GACvC,CAAA;AACL;AAEO,SAAS,UAAA,CACZA,OAAAA,EACA,SAAA,EACA,MAAA,EACA,KACA,OAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,gBAAA,EAAa;AAAA,IACtB,KAAA,EAAO,SAAA;AAAA,IACP,MAAA;AAAA,IACA,GAAA;AAAA,IACA;AAAA,GACH,CAAA;AACL;AAEO,SAAS,WAAA,CACZA,OAAAA,EACA,SAAA,EACA,MAAA,EACA,OAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,iBAAA,EAAc;AAAA,IACvB,KAAA,EAAO,SAAA;AAAA,IACP,MAAA;AAAA,IACA;AAAA,GACH,CAAA;AACL;AAEO,SAAS,gBAAA,CACZA,OAAAA,EACA,MAAA,EACA,IAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,yBAAA,EAA2B;AAAA,IACpC,MAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAC,IAAA;AAAA,IACX,UAAU,OAAO,IAAA;AAAA,IACjB,YAAA,EAAc,IAAA,IAAQ,OAAO,IAAA,KAAS,YAAY,QAAA,IAAY,IAAA;AAAA,IAC9D,WAAW,IAAA,EAAM;AAAA,GACpB,CAAA;AACL;AAEO,SAAS,8BAAA,CACZA,OAAAA,EACA,SAAA,EACA,eAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,kCAAA,EAAoC;AAAA,IAC7C,SAAA;AAAA,IACA,WAAA,EAAa,IAAA;AAAA,IACb;AAAA,GACH,CAAA;AACL;AAEO,SAAS,8BAAA,CACZA,SACA,KAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,iCAAA,EAAmC;AAAA,IAC5C,WAAW,KAAA,EAAO,IAAA;AAAA,IAClB,gBAAA,EAAkB,OAAO,WAAA,CAAY,IAAA;AAAA,IACrC,SAAS,KAAA,EAAO;AAAA,GACnB,CAAA;AACL;AAEO,SAAS,8BAAA,CACZA,SACA,KAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,wBAAA,EAA0B;AAAA,IACnC,SAAA,EAAW,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,IAAA,GAAO,SAAA;AAAA,IACjD,cAAc,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAAA,GACtE,CAAA;AACL;AAEO,SAAS,8BAAA,CACZA,OAAAA,EACA,aAAA,EACA,IAAA,EAEJ;AACI,EAAA,MAAM,MAAA,GAAS,CAAC,aAAA,GACV,aAAA,GACA,CAAC,IAAA,GACG,SAAA,GACA,OAAO,IAAA,KAAS,QAAA,GACZ,iBAAA,GACA,EAAE,QAAA,IAAY,QACV,iBAAA,GACA,SAAA;AAElB,EAAAA,OAAAA,CAAO,KAAA,CAAM,gCAAA,EAAkC,EAAE,QAAQ,CAAA;AAC7D;AAEO,SAAS,4BAAA,CACZA,SACA,KAAA,EAEJ;AACI,EAAAA,OAAAA,CAAO,MAAM,6BAAA,EAA+B;AAAA,IACxC,WAAW,KAAA,CAAM,IAAA;AAAA,IACjB,oBAAA,EAAsB,MAAM,WAAA,CAAY,IAAA;AAAA,IACxC,SAAA,EAAW,MAAA,CAAO,cAAA,CAAe,KAAK,EAAE,WAAA,CAAY;AAAA,GACvD,CAAA;AACL;;;ACxHO,IAAM,QAAA,GAAN,cAAuB,KAAA,CAC9B;AAAA,EACI,WAAA,CACI,OAAA,EACgB,MAAA,EACA,GAAA,EACA,UACA,SAAA,EAEpB;AACI,IAAA,KAAA,CAAM,OAAO,CAAA;AANG,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAIhB,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AAAA,EAChB;AACJ;;;ACyCO,SAAS,kBAAkB,OAAA,EAClC;AACI,EAAA,OAAO,OAAO,OAAA,CAAQ,OAAO,CAAA,CACxB,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,GAAG,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,CAAA,CACvC,KAAK,IAAI,CAAA;AAClB;AAUA,eAAsB,kBAAkB,QAAA,EACxC;AAEI,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EACxB;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAEvD,EAAA,IAAI,WAAA,EAAa,QAAA,CAAS,kBAAkB,CAAA,EAC5C;AACI,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,EACrC,CAAA,MAEA;AACI,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC/B;AACJ;;;ACnFA,eAAsB,uBAAA,GACtB;AACI,EAAA,IACA;AAEI,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,OAAO,cAAc,CAAA;AAC/C,IAAA,MAAM,WAAA,GAAc,MAAM,OAAA,EAAQ;AAClC,IAAA,MAAM,UAAA,GAAa,YAAY,MAAA,EAAO;AAEtC,IAAA,OAAO,MAAA,CAAO,WAAA;AAAA,MACV,UAAA,CAAW,IAAI,CAAA,MAAA,KAAU,CAAC,OAAO,IAAA,EAAM,MAAA,CAAO,KAAK,CAAC;AAAA,KACxD;AAAA,EACJ,SACO,KAAA,EACP;AAGI,IAAA,OAAO,EAAC;AAAA,EACZ;AACJ;AAKA,eAAsB,uBAAA,CAClB,GAAA,EACA,IAAA,EACA,OAAA,EACA,cAA4B,KAAA,EAEhC;AACI,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,YAAY,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE9D,EAAA,IACA;AACI,IAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,GAAA,EAAK;AAAA,MACpC,GAAG,IAAA;AAAA,MACH,QAAQ,UAAA,CAAW;AAAA,KACtB,CAAA;AAED,IAAA,YAAA,CAAa,SAAS,CAAA;AACtB,IAAA,OAAO,QAAA;AAAA,EACX,SACO,KAAA,EACP;AACI,IAAA,YAAA,CAAa,SAAS,CAAA;AACtB,IAAA,MAAM,KAAA;AAAA,EACV;AACJ;AAOA,eAAsB,oBAClB,QAAA,EACA,IAAA,EACA,OAAA,EACA,aAAA,EACA,OACAA,OAAAA,EAEJ;AACI,EAAA,IAAI,KAAA,EACJ;AACI,IAAU,gBAAA,CAAiBA,OAAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,IAAI,CAAA;AAAA,EAC5D;AAGA,EAAA,IAAI,iBAAA,GAAkC,IAAA;AAEtC,EAAA,IAAI,iBAAiB,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,YAAY,IAAA,EACrE;AACI,IAAA,IAAI,KAAA,EACJ;AACI,MAAU,+BAA+BA,OAAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,aAAA,CAAc,oBAAoB,CAAA;AAAA,IACpG;AAEA,IAAA,IACA;AACI,MAAA,iBAAA,GAAoB,aAAA,CAAc,YAAY,IAAW,CAAA;AAEzD,MAAA,IAAI,KAAA,EACJ;AACI,QAAU,8BAAA,CAA+BA,SAAQ,iBAAiB,CAAA;AAAA,MACtE;AAAA,IACJ,SACO,gBAAA,EACP;AAEI,MAAA,IAAI,KAAA,EACJ;AACI,QAAU,8BAAA,CAA+BA,SAAQ,gBAAgB,CAAA;AAAA,MACrE;AAAA,IAEJ;AAAA,EACJ,WACS,KAAA,EACT;AACI,IAAU,8BAAA,CAA+BA,OAAAA,EAAQ,aAAA,EAAe,IAAI,CAAA;AAAA,EACxE;AAGA,EAAA,IAAI,iBAAA,EACJ;AACI,IAAA,IAAI,KAAA,EACJ;AACI,MAAU,4BAAA,CAA6BA,SAAQ,iBAAiB,CAAA;AAAA,IACpE;AAEA,IAAA,MAAM,iBAAA;AAAA,EACV;AAGA,EAAA,IAAI,SAAS,MAAA,KAAW,GAAA,IAAO,OAAA,CAAQ,GAAA,CAAI,aAAa,YAAA,EACxD;AACI,IAAAA,OAAAA,CAAO,IAAA;AAAA,MACH;AAAA,KAMJ;AAAA,EACJ;AAEA,EAAA,MAAM,IAAI,QAAA;AAAA,IACN,MAAM,OAAA,IAAW,CAAA,KAAA,EAAQ,SAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAAA,IAChE,QAAA,CAAS,MAAA;AAAA,IACT,OAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;AC/DO,IAAM,gBAAA,GAAN,MAAM,iBAAA,CAIb;AAAA,EAOI,WAAA,CACqB,UACA,SAAA,EACnB;AAFmB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAClB;AAAA,EATK,QAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KAAA,GACR;AACI,IAAA,MAAM,UAAU,IAAI,iBAAA;AAAA,MAChB,IAAA,CAAK,QAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACT;AACA,IAAA,OAAA,CAAQ,WAAW,IAAA,CAAK,QAAA;AACxB,IAAA,OAAA,CAAQ,WAAW,IAAA,CAAK,QAAA;AACxB,IAAA,OAAA,CAAQ,gBAAgB,IAAA,CAAK,aAAA;AAC7B,IAAA,OAAA,CAAQ,aAAa,IAAA,CAAK,UAAA;AAC1B,IAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,WAAA;AAC3B,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAA,EACR;AACI,IAAA,MAAM,OAAA,GAAU,KAAK,KAAA,EAAM;AAC3B,IAAA,OAAA,CAAQ,WAAW,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAClD,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAA,EACR;AACI,IAAA,MAAM,OAAA,GAAU,KAAK,KAAA,EAAM;AAC3B,IAAA,OAAA,CAAQ,WAAW,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAClD,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAA,EACb;AACI,IAAA,MAAM,OAAA,GAAU,KAAK,KAAA,EAAM;AAC3B,IAAA,OAAA,CAAQ,gBAAgB,EAAE,GAAG,IAAA,CAAK,aAAA,EAAe,GAAG,OAAA,EAAQ;AAC5D,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,WAAA,EACV;AACI,IAAA,MAAM,OAAA,GAAU,KAAK,KAAA,EAAM;AAC3B,IAAA,OAAA,CAAQ,UAAA,GAAa,WAAA;AACrB,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,WAAA,EACX;AACI,IAAA,MAAM,OAAA,GAAU,KAAK,KAAA,EAAM;AAC3B,IAAA,OAAA,CAAQ,WAAA,GAAc,WAAA;AACtB,IAAA,OAAO,OAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KAAK,KAAA,EACL;AACI,IAAA,MAAM,UAAuB,EAAC;AAE9B,IAAA,IAAI,KAAK,QAAA,EACT;AACI,MAAA,OAAA,CAAQ,UAAU,IAAA,CAAK,QAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,KAAK,QAAA,EACT;AACI,MAAA,OAAA,CAAQ,UAAU,IAAA,CAAK,QAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,KAAK,aAAA,EACT;AACI,MAAA,OAAA,CAAQ,eAAe,IAAA,CAAK,aAAA;AAAA,IAChC;AAEA,IAAA,IAAI,KAAK,UAAA,EACT;AACI,MAAA,OAAA,CAAQ,YAAY,IAAA,CAAK,UAAA;AAAA,IAC7B;AAEA,IAAA,IAAI,KAAK,WAAA,EACT;AACI,MAAA,OAAA,CAAQ,aAAa,IAAA,CAAK,WAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,KAAA,IAAS,IAAI,OAAO,CAAA;AAAA,EAC7C;AACJ,CAAA;;;ACxJA,IAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,uBAAuB,CAAA;AAwB/C,SAAS,SAAA,CACZ,MAAA,GAAoB,EAAC,EAEzB;AACI,EAAA,MAAM;AAAA,IACF,OAAA,GAAU,UAAA;AAAA,IACV,OAAA,EAAS,iBAAiB,EAAC;AAAA,IAC3B,UAAU,GAAA,CAAI,cAAA;AAAA,IACd,OAAO,WAAA,GAAc,KAAA;AAAA,IACrB,SAAA,EAAW,eAAA;AAAA,IACX,UAAA,EAAY,gBAAA;AAAA,IACZ,aAAA,EAAe,mBAAA;AAAA,IACf,KAAA,GAAQ;AAAA,GACZ,GAAI,MAAA;AAGJ,EAAA,MAAMC,eAAA,GAAgB,KAAA,CAAM,OAAA,CAAQ,mBAAmB,CAAA,GACjD,IAAI,aAAA,CAAc,CAACC,aAAA,EAAmB,GAAG,mBAAmB,CAAC,IAC7D,mBAAA,IAAuBA,aAAA;AAE7B,EAAA,IAAI,KAAA,EACJ;AACI,IAAA,SAAA,CAAU,KAAA,CAAM,wBAAA,EAA0B,EAAE,OAAA,EAAS,CAAA;AAAA,EACzD;AAUA,EAAA,eAAe,YACX,SAAA,EACA,KAAA,GAAa,EAAC,EACd,OAAA,GAAuB,EAAC,EAE5B;AACI,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,KAAS,MAAA;AAC/B,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,KAAa,MAAA,IAAa,OAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,CAAE,MAAA,GAAS,CAAA;AACzF,IAAA,MAAM,MAAA,GAAU,OAAA,IAAW,WAAA,GAAe,MAAA,GAAS,KAAA;AAGnD,IAAA,IAAI,MAAA,GAAS,IAAI,YAAA,IAAgB,EAAA;AAGjC,IAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,WAAA,EACjC;AACI,MAAA,IACA;AACI,QAAA,MAAM,EAAE,OAAA,EAAAC,QAAAA,EAAQ,GAAI,MAAM,OAAO,cAAc,CAAA;AAC/C,QAAA,MAAM,WAAA,GAAc,MAAMA,QAAAA,EAAQ;AAClC,QAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AACnC,QAAA,MAAM,QAAA,GAAW,WAAA,CAAY,GAAA,CAAI,mBAAmB,CAAA,IAAK,MAAA;AACzD,QAAA,IAAI,IAAA,EACJ;AACI,UAAA,MAAA,GAAS,CAAA,EAAG,QAAQ,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA;AAC9B,UAAA,IAAI,KAAA,EACJ;AACI,YAAA,SAAA,CAAU,KAAA,CAAM,CAAA,oCAAA,EAAuC,MAAM,CAAA,CAAE,CAAA;AAAA,UACnE;AAAA,QACJ;AAAA,MACJ,CAAA,CAAA,MAEA;AAEI,QAAA,IAAI,KAAA,EACJ;AACI,UAAA,SAAA,CAAU,KAAK,oEAAoE,CAAA;AAAA,QACvF;AAAA,MACJ;AAAA,IACJ;AAGA,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,WAAW,KAAA,EACf;AAEI,MAAA,MAAM,UAAA,GAAa,kBAAA,CAAmB,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAC3D,MAAA,OAAA,GAAU,GAAG,MAAM,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,SAAS,UAAU,UAAU,CAAA,CAAA;AAAA,IAClE,CAAA,MAEA;AAEI,MAAA,OAAA,GAAU,CAAA,EAAG,MAAM,CAAA,EAAG,OAAO,IAAI,SAAS,CAAA,CAAA;AAAA,IAC9C;AAIA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACpC,GAAI,WAAA,GAAc,EAAC,GAAI,EAAE,gBAAgB,kBAAA,EAAmB;AAAA,MAC5D,GAAG,cAAA;AAAA,MACH,GAAG,OAAA,CAAQ;AAAA,KACf;AAGA,IAAA,MAAM,mBAAA,GAAsB,MAAM,uBAAA,EAAwB;AAC1D,IAAA,MAAM,aAAA,GAAgB;AAAA,MAClB,GAAG,mBAAA;AAAA,MACH,GAAI,OAAA,CAAQ,OAAA,IAAW;AAAC,KAC5B;AAGA,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,CAAE,SAAS,CAAA,EACxC;AACI,MAAA,OAAA,CAAQ,QAAQ,CAAA,GAAI,iBAAA,CAAkB,aAAa,CAAA;AAAA,IACvD;AAGA,IAAA,IAAI,SAAS,MAAA,CAAO,IAAA,CAAK,mBAAmB,CAAA,CAAE,SAAS,CAAA,EACvD;AACI,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,mBAAmB,EAAE,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,MAAO,EAAE,IAAA,EAAM,OAAM,CAAE,CAAA;AAChG,MAAU,sBAAA,CAAuB,WAAW,WAAW,CAAA;AAAA,IAC3D;AAGA,IAAA,MAAM,WAAA,GAA2B;AAAA,MAC7B,MAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAG,OAAA,CAAQ;AAAA,KACf;AAGA,IAAA,IAAI,WAAW,MAAA,EACf;AACI,MAAA,IAAI,WAAA,EACJ;AAEI,QAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAG9B,QAAA,MAAM,WAAgC,EAAC;AACvC,QAAA,IAAI,KAAA,CAAM,MAAA,EAAQ,QAAA,CAAS,MAAA,GAAS,KAAA,CAAM,MAAA;AAC1C,QAAA,IAAI,KAAA,CAAM,KAAA,EAAO,QAAA,CAAS,KAAA,GAAQ,KAAA,CAAM,KAAA;AACxC,QAAA,IAAI,KAAA,CAAM,OAAA,EAAS,QAAA,CAAS,OAAA,GAAU,KAAA,CAAM,OAAA;AAC5C,QAAA,IAAI,KAAA,CAAM,OAAA,EAAS,QAAA,CAAS,OAAA,GAAU,KAAA,CAAM,OAAA;AAE5C,QAAA,IAAI,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,CAAE,SAAS,CAAA,EACnC;AACI,UAAA,QAAA,CAAS,MAAA,CAAO,YAAA,EAAc,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,QAC1D;AAGA,QAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA,EACxD;AACI,UAAA,IAAI,iBAAiB,IAAA,EACrB;AACI,YAAA,QAAA,CAAS,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,UAC9B,CAAA,MAAA,IACS,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAC5B;AAEI,YAAA,KAAA,MAAW,QAAQ,KAAA,EACnB;AACI,cAAA,IAAI,gBAAgB,IAAA,EACpB;AACI,gBAAA,QAAA,CAAS,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,cAC7B,CAAA,MAEA;AACI,gBAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,cACrC;AAAA,YACJ;AAAA,UACJ,CAAA,MAAA,IACS,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAC1C;AACI,YAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,UACtC;AAAA,QACJ;AAEA,QAAA,WAAA,CAAY,IAAA,GAAO,QAAA;AAAA,MACvB,CAAA,MAEA;AACI,QAAA,WAAA,CAAY,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAAA,MAC3C;AAAA,IACJ;AAGA,IAAA,IAAI,IAAA,GAAO,WAAA;AACX,IAAA,IAAI,eAAA,EACJ;AACI,MAAA,IAAA,GAAO,MAAM,eAAA,CAAgB,OAAA,EAAS,IAAI,CAAA;AAAA,IAC9C;AACA,IAAA,IAAI,QAAQ,SAAA,EACZ;AACI,MAAA,IAAA,GAAO,MAAM,OAAA,CAAQ,SAAA,CAAU,OAAA,EAAS,IAAI,CAAA;AAAA,IAChD;AAEA,IAAA,IAAI,KAAA,EACJ;AACI,MAAU,UAAA,CAAW,WAAW,SAAA,EAAW,MAAA,EAAQ,SAAS,CAAC,CAAC,KAAK,IAAI,CAAA;AAAA,IAC3E;AAGA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,IAAA;AAEJ,IAAA,IACA;AACI,MAAA,QAAA,GAAW,MAAM,uBAAA,CAAwB,OAAA,EAAS,IAAA,EAAM,SAAS,WAAW,CAAA;AAG5E,MAAA,IAAA,GAAO,MAAM,kBAAkB,QAAQ,CAAA;AAGvC,MAAA,IAAI,gBAAA,EACJ;AACI,QAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,CAAiB,QAAA,EAAU,IAAI,CAAA;AACpD,QAAA,QAAA,GAAW,MAAA,CAAO,QAAA;AAClB,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAClB;AACA,MAAA,IAAI,QAAQ,UAAA,EACZ;AACI,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,UAAA,CAAW,UAAU,IAAI,CAAA;AACtD,QAAA,QAAA,GAAW,MAAA,CAAO,QAAA;AAClB,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAClB;AAEA,MAAA,IAAI,KAAA,EACJ;AACI,QAAU,YAAY,SAAA,EAAW,SAAA,EAAW,SAAS,MAAA,EAAQ,CAAC,CAAC,IAAI,CAAA;AAAA,MACvE;AAAA,IACJ,SACO,KAAA,EACP;AAEI,MAAA,IAAI,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,IAAA,KAAS,YAAA,EAC7C;AACI,QAAA,SAAA,CAAU,MAAM,iBAAA,EAAmB;AAAA,UAC/B,KAAA,EAAO,SAAA;AAAA,UACP,MAAA;AAAA,UACA,GAAA,EAAK,OAAA;AAAA,UACL;AAAA,SACH,CAAA;AAED,QAAA,MAAM,IAAI,QAAA;AAAA,UACN,yBAAyB,OAAO,CAAA,EAAA,CAAA;AAAA,UAChC,GAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACJ;AAAA,MACJ;AAGA,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAC9D,MAAA,SAAA,CAAU,MAAM,eAAA,EAAiB;AAAA,QAC7B,KAAA,EAAO,SAAA;AAAA,QACP,MAAA;AAAA,QACA,GAAA,EAAK,OAAA;AAAA,QACL,KAAA,EAAO,YAAA;AAAA,QACP,SAAA,EAAW,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,IAAA,GAAO;AAAA,OACpD,CAAA;AAED,MAAA,MAAM,IAAI,QAAA;AAAA,QACN,YAAA;AAAA,QACA,CAAA;AAAA,QACA,OAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACJ;AAAA,IACJ;AAGA,IAAA,IAAI,CAAC,SAAS,EAAA,EACd;AACI,MAAA,MAAM,oBAAoB,QAAA,EAAU,IAAA,EAAM,OAAA,EAASF,eAAA,EAAe,OAAO,SAAS,CAAA;AAAA,IACtF;AAEA,IAAA,OAAO,IAAA;AAAA,EACX;AAQA,EAAA,SAAS,UAAA,CAAW,SAAS,EAAA,EAC7B;AACI,IAAA,OAAO,IAAI,KAAA;AAAA,MACP,EAAC;AAAA,MACD;AAAA,QACI,GAAA,CAAI,SAAS,IAAA,EACb;AACI,UAAA,MAAM,cAAc,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GAAK,IAAA;AAGnD,UAAA,OAAO,IAAI,gBAAA;AAAA,YACP,CAAC,KAAA,EAAY,OAAA,KAAyB,WAAA,CAAY,WAAA,EAAa,OAAO,OAAO,CAAA;AAAA,YAC7E;AAAA,WACJ;AAAA,QACJ;AAAA;AACJ,KACJ;AAAA,EACJ;AAEA,EAAA,OAAO,UAAA,EAAW;AACtB","file":"index.js","sourcesContent":["/**\n * Debug logging utilities for API client\n * Separates debug logging logic from main client code for better maintainability\n */\nimport type { Logger } from '@spfn/core/logger';\n\nexport function logCookieAutoDetection(\n logger: Logger,\n cookies: Array<{ name: string; value: string }>\n): void\n{\n logger.debug('Auto-detected server environment, forwarding cookies', {\n cookieCount: cookies.length,\n cookieNames: cookies.map(c => c.name),\n });\n}\n\nexport function logRequest(\n logger: Logger,\n routeName: string,\n method: string,\n url: string,\n hasBody: boolean\n): void\n{\n logger.debug('→ Request', {\n route: routeName,\n method,\n url,\n hasBody,\n });\n}\n\nexport function logResponse(\n logger: Logger,\n routeName: string,\n status: number,\n hasBody: boolean\n): void\n{\n logger.debug('← Response', {\n route: routeName,\n status,\n hasBody,\n });\n}\n\nexport function logErrorResponse(\n logger: Logger,\n status: number,\n body: any\n): void\n{\n logger.debug('Error response received', {\n status,\n hasBody: !!body,\n bodyType: typeof body,\n hasTypeField: body && typeof body === 'object' && '__type' in body,\n typeValue: body?.__type,\n });\n}\n\nexport function logErrorDeserializationAttempt(\n logger: Logger,\n errorType: string,\n registeredTypes: string[]\n): void\n{\n logger.debug('Attempting error deserialization', {\n errorType,\n hasRegistry: true,\n registeredTypes,\n });\n}\n\nexport function logErrorDeserializationSuccess(\n logger: Logger,\n error: Error | null\n): void\n{\n logger.debug('Error deserialized successfully', {\n errorName: error?.name,\n errorConstructor: error?.constructor.name,\n message: error?.message,\n });\n}\n\nexport function logErrorDeserializationFailure(\n logger: Logger,\n error: unknown\n): void\n{\n logger.debug('Deserialization failed', {\n errorName: error instanceof Error ? error.name : 'unknown',\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n}\n\nexport function logErrorDeserializationSkipped(\n logger: Logger,\n errorRegistry: any,\n body: any\n): void\n{\n const reason = !errorRegistry\n ? 'no registry'\n : !body\n ? 'no body'\n : typeof body !== 'object'\n ? 'body not object'\n : !('__type' in body)\n ? 'no __type field'\n : 'unknown';\n\n logger.debug('Skipping error deserialization', { reason });\n}\n\nexport function logThrowingDeserializedError(\n logger: Logger,\n error: Error\n): void\n{\n logger.debug('Throwing deserialized error', {\n errorName: error.name,\n errorConstructorName: error.constructor.name,\n prototype: Object.getPrototypeOf(error).constructor.name,\n });\n}","// ============================================================================\n// Client Error\n// ============================================================================\n\n/**\n * Typed client error\n */\nexport class ApiError extends Error\n{\n constructor(\n message: string,\n public readonly status: number,\n public readonly url: string,\n public readonly response?: unknown,\n public readonly errorType?: 'http' | 'network' | 'timeout'\n )\n {\n super(message);\n this.name = 'ApiError';\n }\n}","/**\n * Shared utilities for Next.js client and proxy modules\n *\n * Contains common functions used by both client and proxy to avoid code duplication.\n */\n\n/**\n * Build URL with path parameters replaced\n *\n * @example\n * buildUrlWithParams('/users/:id/posts/:postId', { id: '123', postId: '456' })\n * // Returns: '/users/123/posts/456'\n */\nexport function buildUrlWithParams(path: string, params: Record<string, any>): string\n{\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n return url;\n}\n\n/**\n * Build query string from object\n *\n * @example\n * buildQueryString({ page: '1', limit: '10', tags: ['foo', 'bar'] })\n * // Returns: '?page=1&limit=10&tags=foo&tags=bar'\n */\nexport function buildQueryString(query: Record<string, any>): string\n{\n if (Object.keys(query).length === 0)\n {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => searchParams.append(key, String(v)));\n }\n else\n {\n searchParams.append(key, String(value));\n }\n }\n\n return `?${searchParams.toString()}`;\n}\n\n/**\n * Build Cookie header string from cookies object\n *\n * @example\n * buildCookieHeader({ session: 'abc123', theme: 'dark' })\n * // Returns: 'session=abc123; theme=dark'\n */\nexport function buildCookieHeader(cookies: Record<string, string>): string\n{\n return Object.entries(cookies)\n .map(([key, value]) => `${key}=${value}`)\n .join('; ');\n}\n\n/**\n * Parse response body based on content type\n *\n * Handles:\n * - 204 No Content: returns null (no body expected)\n * - application/json: parses JSON body\n * - Other content types: returns raw text\n */\nexport async function parseResponseBody(response: Response): Promise<any>\n{\n // 204 No Content has no body\n if (response.status === 204)\n {\n return null;\n }\n\n const contentType = response.headers.get('content-type');\n\n if (contentType?.includes('application/json'))\n {\n const text = await response.text();\n return text ? JSON.parse(text) : null;\n }\n else\n {\n return await response.text();\n }\n}","import type { Logger } from '@spfn/core/logger';\nimport type { ErrorRegistry } from '@spfn/core/errors';\nimport { ApiError } from './errors';\nimport * as debugLogs from './debug-logs';\n\n// Re-export shared utilities\nexport { buildCookieHeader, parseResponseBody } from '../shared';\n\n/**\n * Auto-detect cookies from Next.js server environment\n * Returns empty object if not in server environment or if cookies are not accessible\n */\nexport async function autoDetectServerCookies(): Promise<Record<string, string>>\n{\n try\n {\n // Next.js cookies() API is only available in server environment\n const { cookies } = await import('next/headers');\n const cookieStore = await cookies();\n const allCookies = cookieStore.getAll();\n\n return Object.fromEntries(\n allCookies.map(cookie => [cookie.name, cookie.value])\n );\n }\n catch (error)\n {\n // Client environment or cookies not accessible\n // Browser automatically sends cookies in client components\n return {};\n }\n}\n\n/**\n * Execute fetch with timeout and abort controller\n */\nexport async function executeFetchWithTimeout(\n url: string,\n init: RequestInit,\n timeout: number,\n customFetch: typeof fetch = fetch\n): Promise<Response>\n{\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try\n {\n const response = await customFetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n return response;\n }\n catch (error)\n {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n\n/**\n * Handle error response with deserialization support\n * Attempts to deserialize custom errors if errorRegistry is provided\n * Falls back to ApiError if deserialization fails or is not available\n */\nexport async function handleErrorResponse(\n response: Response,\n body: any,\n fullUrl: string,\n errorRegistry: ErrorRegistry | undefined,\n debug: boolean,\n logger: Logger\n): Promise<never>\n{\n if (debug)\n {\n debugLogs.logErrorResponse(logger, response.status, body);\n }\n\n // Try to deserialize error if registry is provided\n let deserializedError: Error | null = null;\n\n if (errorRegistry && body && typeof body === 'object' && '__type' in body)\n {\n if (debug)\n {\n debugLogs.logErrorDeserializationAttempt(logger, body.__type, errorRegistry.getRegisteredTypes());\n }\n\n try\n {\n deserializedError = errorRegistry.deserialize(body as any);\n\n if (debug)\n {\n debugLogs.logErrorDeserializationSuccess(logger, deserializedError);\n }\n }\n catch (deserializeError)\n {\n // Deserialization itself failed (type not found, invalid data, etc.)\n if (debug)\n {\n debugLogs.logErrorDeserializationFailure(logger, deserializeError);\n }\n // Fall through to ApiError below\n }\n }\n else if (debug)\n {\n debugLogs.logErrorDeserializationSkipped(logger, errorRegistry, body);\n }\n\n // If deserialization succeeded, throw the deserialized error\n if (deserializedError)\n {\n if (debug)\n {\n debugLogs.logThrowingDeserializedError(logger, deserializedError);\n }\n\n throw deserializedError;\n }\n\n // Fallback to generic ApiError\n if (response.status === 404 && process.env.NODE_ENV !== 'production')\n {\n logger.warn(\n '\\n⚠️ 404 Not Found\\n\\n' +\n 'Check the following:\\n' +\n ' 1. Routes are registered in server.config.ts:\\n' +\n ' → defineServerConfig().routes(appRouter)\\n' +\n ' 2. Delete .spfn cache if you recently added new routes:\\n' +\n ' → rm -rf .spfn\\n'\n );\n }\n\n throw new ApiError(\n body?.message || `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n fullUrl,\n body,\n 'http'\n );\n}","// ============================================================================\n// Route Call Builder (Structured Input API)\n// ============================================================================\n\nimport type { RouteDef, Router } from \"@spfn/core/route\";\nimport type {\n CallOptions,\n InferRouteInput,\n InferRouteOutput,\n RequestInterceptor,\n ResponseInterceptor,\n} from \"./types\";\n\n/**\n * Pick only non-empty fields from StructuredInput\n *\n * This removes fields that are empty objects `{}` from the input type,\n * so users only need to provide fields that are actually defined in the route.\n */\ntype PickNonEmpty<T> = {\n [K in keyof T as T[K] extends Record<string, never> ? never : K]: T[K];\n};\n\n/**\n * Make fields that can be undefined into optional fields\n *\n * When a field is defined as `Type.Optional(Type.Object({...}))`,\n * the resulting type is `T | undefined`. This utility converts such fields\n * into proper optional fields (`field?: T`) so users don't need to pass them.\n */\ntype MakeOptionalIfUndefinable<T> =\n // Required fields (undefined is not assignable)\n { [K in keyof T as undefined extends T[K] ? never : K]: T[K] }\n // Optional fields (undefined is assignable)\n & { [K in keyof T as undefined extends T[K] ? K : never]?: Exclude<T[K], undefined> };\n\n/**\n * Clean structured input - only include fields that have actual schema,\n * and make fields optional if they accept undefined\n */\ntype CleanStructuredInput<TInput> = MakeOptionalIfUndefinable<PickNonEmpty<TInput>>;\n\n/**\n * Check if input has any required fields\n *\n * Returns false if all fields are optional (i.e., {} is assignable to the input type)\n */\ntype HasAnyRequiredFields<TInput> = {} extends CleanStructuredInput<TInput> ? false : true;\n\n/**\n * Route call builder with structured input API\n *\n * Input is structured with explicit params, query, body fields\n * that match the server-side route definition.\n *\n * @example\n * ```typescript\n * // GET /users/:id - params only\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // GET /users/:id?include=posts - params + query\n * const user = await api.getUser.call({\n * params: { id: '1' },\n * query: { include: 'posts' }\n * });\n *\n * // POST /users - body only\n * const user = await api.createUser.call({\n * body: { name: 'John', email: 'john@example.com' }\n * });\n *\n * // PUT /users/:id - params + body\n * const user = await api.updateUser.call({\n * params: { id: '1' },\n * body: { name: 'Jane' }\n * });\n *\n * // With options (headers, cookies, Next.js caching)\n * const user = await api.getUser\n * .headers({ 'X-Custom': 'value' })\n * .fetchOptions({ next: { revalidate: 60 } })\n * .call({ params: { id: '1' } });\n * ```\n */\nexport class RouteCallBuilder<\n TInput,\n TOutput\n>\n{\n private _headers?: Record<string, string>;\n private _cookies?: Record<string, string>;\n private _fetchOptions?: RequestInit;\n private _onRequest?: RequestInterceptor;\n private _onResponse?: ResponseInterceptor;\n\n constructor(\n private readonly executor: (input: any, options: CallOptions) => Promise<TOutput>,\n private readonly routeName: string\n ) {}\n\n /**\n * Clone builder\n */\n private clone(): RouteCallBuilder<TInput, TOutput>\n {\n const builder = new RouteCallBuilder<TInput, TOutput>(\n this.executor,\n this.routeName\n );\n builder._headers = this._headers;\n builder._cookies = this._cookies;\n builder._fetchOptions = this._fetchOptions;\n builder._onRequest = this._onRequest;\n builder._onResponse = this._onResponse;\n return builder;\n }\n\n /**\n * Set request headers\n */\n headers(headers: Record<string, string>): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._headers = { ...this._headers, ...headers };\n return builder;\n }\n\n /**\n * Set cookies\n */\n cookies(cookies: Record<string, string>): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._cookies = { ...this._cookies, ...cookies };\n return builder;\n }\n\n /**\n * Set Next.js fetch options\n */\n fetchOptions(options: RequestInit & { next?: { revalidate?: number | false; tags?: string[] } }): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._fetchOptions = { ...this._fetchOptions, ...options };\n return builder;\n }\n\n /**\n * Set request interceptor\n */\n onRequest(interceptor: RequestInterceptor): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._onRequest = interceptor;\n return builder;\n }\n\n /**\n * Set response interceptor\n */\n onResponse(interceptor: ResponseInterceptor): RouteCallBuilder<TInput, TOutput>\n {\n const builder = this.clone();\n builder._onResponse = interceptor;\n return builder;\n }\n\n /**\n * Execute the API call with structured input\n *\n * Input structure matches the server-side route definition:\n * - params: Path parameters (e.g., { id: '123' } for /users/:id)\n * - query: Query string parameters\n * - body: Request body (for POST, PUT, PATCH)\n */\n call(input?: CleanStructuredInput<TInput>): Promise<TOutput>\n {\n const options: CallOptions = {};\n\n if (this._headers)\n {\n options.headers = this._headers;\n }\n\n if (this._cookies)\n {\n options.cookies = this._cookies;\n }\n\n if (this._fetchOptions)\n {\n options.fetchOptions = this._fetchOptions;\n }\n\n if (this._onRequest)\n {\n options.onRequest = this._onRequest;\n }\n\n if (this._onResponse)\n {\n options.onResponse = this._onResponse;\n }\n\n return this.executor(input || {}, options);\n }\n}\n\n/**\n * Individual route client with structured input API\n */\nexport type RouteClient<TRoute extends RouteDef<any, any>> = {\n /**\n * Set request headers\n */\n headers(headers: Record<string, string>): RouteClient<TRoute>;\n\n /**\n * Set cookies\n */\n cookies(cookies: Record<string, string>): RouteClient<TRoute>;\n\n /**\n * Set Next.js fetch options\n */\n fetchOptions(options: RequestInit & { next?: { revalidate?: number | false; tags?: string[] } }): RouteClient<TRoute>;\n\n /**\n * Set request interceptor\n */\n onRequest(interceptor: RequestInterceptor): RouteClient<TRoute>;\n\n /**\n * Set response interceptor\n */\n onResponse(interceptor: ResponseInterceptor): RouteClient<TRoute>;\n\n /**\n * Execute the API call with structured input\n *\n * @example\n * ```typescript\n * // GET /users/:id\n * api.getUser.call({ params: { id: '123' } });\n *\n * // PUT /users/:id\n * api.updateUser.call({ params: { id: '123' }, body: { name: 'Jane' } });\n * ```\n */\n call: HasAnyRequiredFields<InferRouteInput<TRoute>> extends true\n ? (input: CleanStructuredInput<InferRouteInput<TRoute>>) => Promise<InferRouteOutput<TRoute>>\n : (input?: CleanStructuredInput<InferRouteInput<TRoute>>) => Promise<InferRouteOutput<TRoute>>;\n};\n\n/**\n * Typed client for entire router\n */\nexport type Client<TRouter extends Router<any>> = {\n [K in keyof TRouter['routes']]: TRouter['routes'][K] extends RouteDef<any, any, any>\n ? RouteClient<TRouter['routes'][K]>\n : TRouter['routes'][K] extends Router<any>\n ? Client<TRouter['routes'][K]>\n : never;\n};","/**\n * Type-Safe RPC-Style Client with Structured Input API\n *\n * Provides full end-to-end type safety from server routes to client calls.\n * No metadata codegen required - method/path resolution happens at the proxy layer.\n *\n * @example\n * ```typescript\n * // Server\n * export const appRouter = defineRouter({\n * getUser: route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => { ... }),\n * createUser: route.post('/users')\n * .input({ body: Type.Object({ name: Type.String() }) })\n * .handler(async (c) => { ... }),\n * });\n *\n * export type AppRouter = typeof appRouter;\n *\n * // Client - no metadata needed!\n * const api = createApi<AppRouter>();\n *\n * // ✅ GET (no body) - becomes GET /api/rpc/getUser?input={...}\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // ✅ POST (has body) - becomes POST /api/rpc/createUser\n * const newUser = await api.createUser.call({ body: { name: 'John' } });\n *\n * // ✅ With options (headers, cookies, interceptors)\n * const user = await api.getUser\n * .headers({ 'X-Custom': 'value' })\n * .cookies({ session: 'xxx' })\n * .fetchOptions({ next: { revalidate: 60 } })\n * .call({ params: { id: '1' } });\n * ```\n */\nimport { env } from '@spfn/core/config';\nimport { ErrorRegistry, errorRegistry as coreErrorRegistry } from '@spfn/core/errors';\nimport { logger } from '@spfn/core/logger';\nimport type { Router } from '@spfn/core/route';\nimport * as debugLogs from './debug-logs';\nimport { ApiError } from \"./errors\";\nimport {\n parseResponseBody,\n executeFetchWithTimeout,\n handleErrorResponse,\n buildCookieHeader,\n autoDetectServerCookies,\n} from './helpers';\nimport { RouteCallBuilder } from './builder';\nimport type { ApiConfig, CallOptions } from \"./types\";\nimport type { Client } from \"./builder\";\n\nconst apiLogger = logger.child('@spfn/core:api-client');\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\n/**\n * Create type-safe RPC client\n *\n * No metadata required - the client sends routeName + input to the proxy,\n * and the proxy resolves the actual HTTP method and path from the router.\n *\n * @example\n * ```typescript\n * // Client - no metadata needed!\n * const api = createApi<AppRouter>();\n *\n * // GET request (no body) - browser cacheable\n * const user = await api.getUser.call({ params: { id: '1' } });\n *\n * // POST request (has body)\n * const newUser = await api.createUser.call({ body: { name: 'John' } });\n * ```\n */\nexport function createApi<TRouter extends Router<any>>(\n config: ApiConfig = {}\n): Client<TRouter>\n{\n const {\n baseUrl = '/api/rpc',\n headers: defaultHeaders = {},\n timeout = env.SERVER_TIMEOUT,\n fetch: customFetch = fetch,\n onRequest: globalOnRequest,\n onResponse: globalOnResponse,\n errorRegistry: errorRegistryConfig,\n debug = false,\n } = config;\n\n // Normalize errorRegistry: always include coreErrorRegistry\n const errorRegistry = Array.isArray(errorRegistryConfig)\n ? new ErrorRegistry([coreErrorRegistry, ...errorRegistryConfig])\n : errorRegistryConfig ?? coreErrorRegistry;\n\n if (debug)\n {\n apiLogger.debug('API client initialized', { baseUrl });\n }\n\n /**\n * Execute API call\n *\n * Determines GET vs POST based on body/formData presence:\n * - No body/formData → GET /api/rpc/{routeName}?input={...}\n * - Has body → POST /api/rpc/{routeName} with JSON body\n * - Has formData → POST /api/rpc/{routeName} with multipart/form-data\n */\n async function executeCall(\n routeName: string,\n input: any = {},\n options: CallOptions = {}\n ): Promise<any>\n {\n const hasBody = input.body !== undefined;\n const hasFormData = input.formData !== undefined && Object.keys(input.formData).length > 0;\n const method = (hasBody || hasFormData) ? 'POST' : 'GET';\n\n // Build full URL - handle SSR case where SPFN_APP_URL might not be set\n let appUrl = env.SPFN_APP_URL || '';\n\n // In SSR environment, if SPFN_APP_URL is not set, try to get host from request headers\n if (!appUrl && typeof window === 'undefined')\n {\n try\n {\n const { headers } = await import('next/headers');\n const headersList = await headers();\n const host = headersList.get('host');\n const protocol = headersList.get('x-forwarded-proto') || 'http';\n if (host)\n {\n appUrl = `${protocol}://${host}`;\n if (debug)\n {\n apiLogger.debug(`Auto-detected app URL from headers: ${appUrl}`);\n }\n }\n }\n catch\n {\n // Fallback: use relative URL and let fetch handle it\n if (debug)\n {\n apiLogger.warn('Could not determine app URL in SSR environment, using relative URL');\n }\n }\n }\n\n // Build URL based on method\n let fullUrl: string;\n if (method === 'GET')\n {\n // GET: encode input in query string\n const inputParam = encodeURIComponent(JSON.stringify(input));\n fullUrl = `${appUrl}${baseUrl}/${routeName}?input=${inputParam}`;\n }\n else\n {\n // POST: input goes in body\n fullUrl = `${appUrl}${baseUrl}/${routeName}`;\n }\n\n // Prepare headers\n // Note: Don't set Content-Type for formData - browser sets it with boundary\n const headers: Record<string, string> = {\n ...(hasFormData ? {} : { 'Content-Type': 'application/json' }),\n ...defaultHeaders,\n ...options.headers,\n };\n\n // Auto-detect server cookies and merge with user-provided cookies\n const autoDetectedCookies = await autoDetectServerCookies();\n const cookiesToSend = {\n ...autoDetectedCookies,\n ...(options.cookies || {}),\n };\n\n // Add Cookie header if we have cookies to send\n if (Object.keys(cookiesToSend).length > 0)\n {\n headers['Cookie'] = buildCookieHeader(cookiesToSend);\n }\n\n // Log cookie auto-detection if debug enabled\n if (debug && Object.keys(autoDetectedCookies).length > 0)\n {\n const cookieArray = Object.entries(autoDetectedCookies).map(([name, value]) => ({ name, value }));\n debugLogs.logCookieAutoDetection(apiLogger, cookieArray);\n }\n\n // Build request init\n const requestInit: RequestInit = {\n method,\n headers,\n ...options.fetchOptions,\n };\n\n // Add body for POST\n if (method === 'POST')\n {\n if (hasFormData)\n {\n // Build FormData for file uploads\n const formData = new FormData();\n\n // Add non-formData fields (params, query, headers, cookies) as JSON metadata\n const metadata: Record<string, any> = {};\n if (input.params) metadata.params = input.params;\n if (input.query) metadata.query = input.query;\n if (input.headers) metadata.headers = input.headers;\n if (input.cookies) metadata.cookies = input.cookies;\n\n if (Object.keys(metadata).length > 0)\n {\n formData.append('__metadata', JSON.stringify(metadata));\n }\n\n // Add formData fields\n for (const [key, value] of Object.entries(input.formData))\n {\n if (value instanceof File)\n {\n formData.append(key, value);\n }\n else if (Array.isArray(value))\n {\n // Handle array of files or values\n for (const item of value)\n {\n if (item instanceof File)\n {\n formData.append(key, item);\n }\n else\n {\n formData.append(key, String(item));\n }\n }\n }\n else if (value !== undefined && value !== null)\n {\n formData.append(key, String(value));\n }\n }\n\n requestInit.body = formData;\n }\n else\n {\n requestInit.body = JSON.stringify(input);\n }\n }\n\n // Execute request interceptors\n let init = requestInit;\n if (globalOnRequest)\n {\n init = await globalOnRequest(fullUrl, init);\n }\n if (options.onRequest)\n {\n init = await options.onRequest(fullUrl, init);\n }\n\n if (debug)\n {\n debugLogs.logRequest(apiLogger, routeName, method, fullUrl, !!init.body);\n }\n\n // Execute fetch with timeout\n let response: Response;\n let body: any;\n\n try\n {\n response = await executeFetchWithTimeout(fullUrl, init, timeout, customFetch);\n\n // Parse response\n body = await parseResponseBody(response);\n\n // Execute global + local response interceptors\n if (globalOnResponse)\n {\n const result = await globalOnResponse(response, body);\n response = result.response;\n body = result.body;\n }\n if (options.onResponse)\n {\n const result = await options.onResponse(response, body);\n response = result.response;\n body = result.body;\n }\n\n if (debug)\n {\n debugLogs.logResponse(apiLogger, routeName, response.status, !!body);\n }\n }\n catch (error)\n {\n // Handle timeout specifically\n if (error instanceof Error && error.name === 'AbortError')\n {\n apiLogger.error('Request timeout', {\n route: routeName,\n method,\n url: fullUrl,\n timeout,\n });\n\n throw new ApiError(\n `Request timeout after ${timeout}ms`,\n 408,\n fullUrl,\n undefined,\n 'timeout'\n );\n }\n\n // Network error\n const errorMessage = error instanceof Error ? error.message : 'Network error';\n apiLogger.error('Network error', {\n route: routeName,\n method,\n url: fullUrl,\n error: errorMessage,\n errorName: error instanceof Error ? error.name : 'unknown',\n });\n\n throw new ApiError(\n errorMessage,\n 0,\n fullUrl,\n undefined,\n 'network'\n );\n }\n\n // Handle error responses\n if (!response.ok)\n {\n await handleErrorResponse(response, body, fullUrl, errorRegistry, debug, apiLogger);\n }\n\n return body;\n }\n\n /**\n * Build client proxy\n *\n * Every property access returns a RouteCallBuilder.\n * Nested routers are supported via dot notation in routeName.\n */\n function buildProxy(prefix = ''): any\n {\n return new Proxy(\n {},\n {\n get(_target, prop: string)\n {\n const currentPath = prefix ? `${prefix}.${prop}` : prop;\n\n // Return RouteCallBuilder that can either be called or chained\n return new RouteCallBuilder(\n (input: any, options: CallOptions) => executeCall(currentPath, input, options),\n currentPath\n );\n },\n }\n );\n }\n\n return buildProxy() as Client<TRouter>;\n}"]}
@@ -1,7 +1,7 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
2
  import { Router, HttpMethod } from '@spfn/core/route';
3
3
  import { InterceptorRule as InterceptorRule$1 } from '@spfn/core/nextjs/server';
4
- import { f as SetCookie } from '../types-DP8nzQcY.js';
4
+ import { f as SetCookie } from '../types-7Mhoxnnt.js';
5
5
  import '@sinclair/typebox';
6
6
  import '@spfn/core/errors';
7
7
 
@@ -46,7 +46,7 @@ interface TypedProxyConfig {
46
46
  /**
47
47
  * Request timeout in milliseconds
48
48
  *
49
- * @default 30000
49
+ * @default env.SERVER_TIMEOUT (120000)
50
50
  */
51
51
  timeout?: number;
52
52
  /**
@@ -359,7 +359,7 @@ function createRpcProxy(config) {
359
359
  const {
360
360
  apiUrl = env.SPFN_API_URL || "http://localhost:8790",
361
361
  debug = env.NODE_ENV === "development",
362
- timeout = 3e4,
362
+ timeout = env.SERVER_TIMEOUT,
363
363
  headers: defaultHeaders = {},
364
364
  interceptors,
365
365
  autoDiscoverInterceptors = true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/nextjs/shared.ts","../../src/nextjs/proxy/interceptors/helpers.ts","../../src/nextjs/proxy/interceptors/registry.ts","../../src/nextjs/proxy/helpers.ts","../../src/nextjs/proxy/rpc.ts"],"names":["headersToForward"],"mappings":";;;;;;;AAaO,SAAS,kBAAA,CAAmB,MAAc,MAAA,EACjD;AACI,EAAA,IAAI,GAAA,GAAM,IAAA;AACV,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAChD;AACI,IAAA,GAAA,GAAM,GAAA,CAAI,QAAQ,CAAA,CAAA,EAAI,GAAG,IAAI,kBAAA,CAAmB,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,GAAA;AACX;AASO,SAAS,iBAAiB,KAAA,EACjC;AACI,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,WAAW,CAAA,EAClC;AACI,IAAA,OAAO,EAAA;AAAA,EACX;AAEA,EAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAC/C;AACI,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EACvB;AACI,MAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,YAAA,CAAa,OAAO,GAAA,EAAK,MAAA,CAAO,CAAC,CAAC,CAAC,CAAA;AAAA,IAC5D,CAAA,MAEA;AACI,MAAA,YAAA,CAAa,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IAC1C;AAAA,EACJ;AAEA,EAAA,OAAO,CAAA,CAAA,EAAI,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA;AACtC;AAwBA,eAAsB,kBAAkB,QAAA,EACxC;AAEI,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EACxB;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAEvD,EAAA,IAAI,WAAA,EAAa,QAAA,CAAS,kBAAkB,CAAA,EAC5C;AACI,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,EACrC,CAAA,MAEA;AACI,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC/B;AACJ;;;ACrEO,SAAS,SAAA,CAAU,MAAc,OAAA,EACxC;AAEI,EAAA,IAAI,YAAY,GAAA,EAChB;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAGA,EAAA,IAAI,mBAAmB,MAAA,EACvB;AACI,IAAA,OAAO,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,EAC5B;AAMA,EAAA,MAAM,YAAA,GAAe,OAAA,CAChB,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA,CACnB,OAAA,CAAQ,SAAA,EAAW,OAAO,CAAA,CAC1B,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAEzB,EAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA,CAAG,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAC1B;AASO,SAAS,WAAA,CACZ,QACA,OAAA,EAEJ;AAEI,EAAA,IAAI,CAAC,OAAA,EACL;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAGA,EAAA,IAAI,OAAO,YAAY,QAAA,EACvB;AACI,IAAA,OAAO,MAAA,CAAO,WAAA,EAAY,KAAM,OAAA,CAAQ,WAAA,EAAY;AAAA,EACxD;AAGA,EAAA,OAAO,OAAA,CAAQ,KAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,KAAM,MAAA,CAAO,WAAA,EAAa,CAAA;AACvE;AAUO,SAAS,0BAAA,CACZ,KAAA,EACA,IAAA,EACA,MAAA,EAEJ;AACI,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,IAAA,KAAS;AAC1B,IAAA,OAAO,SAAA,CAAU,MAAM,IAAA,CAAK,WAAW,KAAK,WAAA,CAAY,MAAA,EAAQ,KAAK,MAAM,CAAA;AAAA,EAC/E,CAAC,CAAA;AACL;AAgBA,eAAsB,0BAAA,CAClB,SACA,YAAA,EAEJ;AACI,EAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,EAAA,MAAM,OAAO,YAA2B;AACpC,IAAA,IAAI,KAAA,IAAS,aAAa,MAAA,EAC1B;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,WAAA,GAAc,aAAa,KAAK,CAAA;AACtC,IAAA,KAAA,EAAA;AAEA,IAAA,MAAM,WAAA,CAAY,SAAS,IAAI,CAAA;AAAA,EACnC,CAAA;AAEA,EAAA,MAAM,IAAA,EAAK;AACf;AAgBA,eAAsB,2BAAA,CAClB,SACA,YAAA,EAEJ;AACI,EAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,EAAA,MAAM,OAAO,YAA2B;AACpC,IAAA,IAAI,KAAA,IAAS,aAAa,MAAA,EAC1B;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,WAAA,GAAc,aAAa,KAAK,CAAA;AACtC,IAAA,KAAA,EAAA;AAEA,IAAA,MAAM,WAAA,CAAY,SAAS,IAAI,CAAA;AAAA,EACnC,CAAA;AAEA,EAAA,MAAM,IAAA,EAAK;AACf;;;AC3IO,IAAM,sBAAN,MACP;AAAA,EACY,YAAA,uBAAmB,GAAA,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkB1D,QAAA,CAAS,aAAqB,YAAA,EAC9B;AACI,IAAA,IAAI,CAAC,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA,EACtC;AACI,MAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,WAAA,EAAa,YAAY,CAAA;AAAA,IACnD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAA,CAAO,OAAA,GAAoB,EAAC,EAC5B;AACI,IAAA,MAAM,MAAyB,EAAC;AAEhC,IAAA,KAAA,MAAW,CAAC,WAAA,EAAa,YAAY,KAAK,IAAA,CAAK,YAAA,CAAa,SAAQ,EACpE;AACI,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EACjC;AACI,QAAA,GAAA,CAAI,IAAA,CAAK,GAAG,YAAY,CAAA;AAAA,MAC5B;AAAA,IACJ;AAEA,IAAA,OAAO,GAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,WAAA,EACJ;AACI,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GACA;AACI,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAA,EACJ;AACI,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,WAAA,EACX;AACI,IAAA,IAAA,CAAK,YAAA,CAAa,OAAO,WAAW,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAA,GACA;AACI,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GACA;AACI,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,YAAA,IAAgB,IAAA,CAAK,YAAA,CAAa,MAAA,EAAO,EACpD;AACI,MAAA,KAAA,IAAS,YAAA,CAAa,MAAA;AAAA,IAC1B;AACA,IAAA,OAAO,KAAA;AAAA,EACX;AACJ,CAAA;AAQO,IAAM,uBAAuB,MACpC;AACI,EAAA,IAAI,CAAC,WAAW,6BAAA,EAChB;AACI,IAAA,UAAA,CAAW,6BAAA,GAAgC,IAAI,mBAAA,EAAoB;AAAA,EACvE;AAEA,EAAA,OAAO,UAAA,CAAW,6BAAA;AACtB,CAAA;AA+BO,SAAS,oBAAA,CACZ,aACA,YAAA,EAEJ;AACI,EAAA,mBAAA,CAAoB,QAAA,CAAS,aAAa,YAAY,CAAA;AAC1D;;;AC7KO,SAAS,iBAAA,CACZ,eACA,cAAA,EAEJ;AACI,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAG5B,EAAA,MAAMA,iBAAAA,GAAmB;AAAA,IACrB,cAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACJ;AAEA,EAAA,KAAA,MAAW,UAAUA,iBAAAA,EACrB;AACI,IAAA,MAAM,KAAA,GAAQ,yBAAyB,OAAA,GACjC,aAAA,CAAc,IAAI,MAAM,CAAA,GACxB,cAAc,MAAM,CAAA;AAE1B,IAAA,IAAI,KAAA,EACJ;AACI,MAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,KAAK,CAAA;AAAA,IAC7B;AAAA,EACJ;AAGA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,cAAc,CAAA,EACxD;AACI,IAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,OAAA;AACX;AAQO,SAAS,aAAa,YAAA,EAC7B;AACI,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoB;AAE3C,EAAA,IAAI,CAAC,YAAA,EACL;AACI,IAAA,OAAO,UAAA;AAAA,EACX;AAEA,EAAA,MAAM,WAAA,GAAc,aAAa,KAAA,CAAM,GAAG,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,EAAM,CAAA;AAC7D,EAAA,KAAA,MAAW,QAAQ,WAAA,EACnB;AACI,IAAA,MAAM,CAAC,IAAA,EAAM,GAAG,UAAU,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AAC5C,IAAA,IAAI,IAAA,IAAQ,UAAA,CAAW,MAAA,GAAS,CAAA,EAChC;AACI,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACjC,MAAA,UAAA,CAAW,IAAI,IAAA,CAAK,IAAA,EAAK,EAAG,KAAA,CAAM,MAAM,CAAA;AAAA,IAC5C;AAAA,EACJ;AAEA,EAAA,OAAO,UAAA;AACX;AAMO,SAAS,4BAA4B,OAAA,EAC5C;AACI,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoB;AAG3C,EAAA,KAAA,MAAW,MAAA,IAAU,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAO,EAC5C;AACI,IAAA,UAAA,CAAW,GAAA,CAAI,MAAA,CAAO,IAAA,EAAM,MAAA,CAAO,KAAK,CAAA;AAAA,EAC5C;AAGA,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AACjD,EAAA,IAAI,YAAA,EACJ;AACI,IAAA,MAAM,MAAA,GAAS,aAAa,YAAY,CAAA;AACxC,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,SAAQ,EAC3C;AACI,MAAA,UAAA,CAAW,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,IAC9B;AAAA,EACJ;AAEA,EAAA,OAAO,UAAA;AACX;AAGA,IAAM,cAAA,GAGD;AAAA,EACD,EAAE,KAAK,UAAA,EAAY,MAAA,EAAQ,CAAC,CAAA,KAAM,CAAA,GAAI,aAAa,IAAA,EAAK;AAAA,EACxD,EAAE,KAAK,QAAA,EAAU,MAAA,EAAQ,CAAC,CAAA,KAAM,CAAA,GAAI,WAAW,IAAA,EAAK;AAAA,EACpD,EAAE,GAAA,EAAK,UAAA,EAAY,MAAA,EAAQ,CAAC,MAAM,CAAA,GAAI,CAAA,SAAA,EAAY,CAAC,CAAA,CAAA,GAAK,IAAA,EAAK;AAAA,EAC7D,EAAE,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAC,CAAA,KAAM,CAAA,KAAM,MAAA,GAAY,CAAA,QAAA,EAAW,CAAC,CAAA,CAAA,GAAK,IAAA,EAAK;AAAA,EACxE,EAAE,GAAA,EAAK,MAAA,EAAQ,MAAA,EAAQ,CAAC,MAAM,CAAA,GAAI,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,GAAK,IAAA,EAAK;AAAA,EACrD,EAAE,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAC,MAAM,CAAA,GAAI,CAAA,OAAA,EAAU,CAAC,CAAA,CAAA,GAAK,IAAA;AACxD,CAAA;AAKO,SAAS,qBAAqB,MAAA,EACrC;AACI,EAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,EAAC;AAEnC,EAAA,KAAA,MAAW,EAAE,GAAA,EAAK,MAAA,EAAO,IAAK,cAAA,EAC9B;AACI,IAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,KAAA,EACrC;AACI,MAAA,MAAM,SAAA,GAAY,OAAO,KAAK,CAAA;AAC9B,MAAA,IAAI,SAAA,EACJ;AACI,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MACxB;AAAA,IACJ;AAAA,EACJ;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAC1B;AAKO,SAAS,kBAAA,CACZ,SAAA,EACA,OAAA,EACA,KAAA,EACA,KAAA,EAEJ;AACI,EAAA,OAAO;AAAA,IACH,KAAA,EAAO,SAAA;AAAA,IACP,OAAA;AAAA,IACA,GAAI,KAAA,IAAS,KAAA,EAAO,SAAS,EAAE,KAAA,EAAO,MAAM,KAAA;AAAM,GACtD;AACJ;AAEA,IAAM,gBAAA,GAAmB;AAAA,EACrB,cAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA;AACJ,CAAA;AAKO,SAAS,sBAAA,CACZ,eACA,aAAA,EAEJ;AACI,EAAA,KAAA,MAAW,UAAU,gBAAA,EACrB;AACI,IAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,MAAM,CAAA;AACtC,IAAA,IAAI,KAAA,EACJ;AACI,MAAA,aAAA,CAAc,GAAA,CAAI,QAAQ,KAAK,CAAA;AAAA,IACnC;AAAA,EACJ;AACJ;AAKO,SAAS,mBAAA,CACZ,wBAAA,EACA,uBAAA,EACA,kBAAA,EACA,QAAA,EAEJ;AACI,EAAA,MAAM,kBAAqC,EAAC;AAG5C,EAAA,IAAI,wBAAA,EACJ;AACI,IAAA,MAAM,sBAAA,GAAyB,QAAA,CAAS,MAAA,CAAO,uBAAA,IAA2B,EAAE,CAAA;AAC5E,IAAA,eAAA,CAAgB,IAAA,CAAK,GAAG,sBAAsB,CAAA;AAAA,EAClD;AAGA,EAAA,IAAI,kBAAA,EACJ;AACI,IAAA,eAAA,CAAgB,IAAA,CAAK,GAAG,kBAAkB,CAAA;AAAA,EAC9C;AAEA,EAAA,OAAO,eAAA;AACX;AAKO,SAAS,oBACZ,IAAA,EACA,MAAA,EACA,SACA,IAAA,EACA,YAAA,EACA,YACA,OAAA,EAEJ;AACI,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA;AAAA,IACd,MAAA;AAAA,IACA,OAAA,EAAS,MAAA,CAAO,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC7C,IAAA;AAAA,IACA,KAAA,EAAO,MAAA,CAAO,WAAA,CAAY,YAAA,CAAa,SAAS,CAAA;AAAA,IAChD,OAAA,EAAS,UAAA;AAAA,IACT,OAAA;AAAA,IACA,UAAU;AAAC,GACf;AACJ;AAKO,SAAS,oBAAA,CACZ,MACA,MAAA,EACA,cAAA,EACA,aACA,QAAA,EACA,YAAA,EACA,iBACA,OAAA,EAEJ;AACI,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA;AAAA,IACd,MAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACL,OAAA,EAAS,MAAA,CAAO,WAAA,CAAY,cAAA,CAAe,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM;AAAA,KACV;AAAA,IACA,QAAA,EAAU;AAAA,MACN,IAAI,QAAA,CAAS,EAAA;AAAA,MACb,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,IAAA,EAAM;AAAA,KACV;AAAA,IACA,OAAA;AAAA,IACA,YAAY,EAAC;AAAA,IACb,QAAA,EAAU;AAAA,GACd;AACJ;;;ACzOA,IAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,sBAAsB,CAAA;AAmFrD,SAAS,WAAW,KAAA,EACpB;AACI,EAAA,OAAO,KAAA,KAAU,QACb,OAAO,KAAA,KAAU,YACjB,SAAA,IAAa,KAAA,IACb,QAAA,IAAY,KAAA,IACZ,MAAA,IAAU,KAAA;AAClB;AAKA,SAAS,SAAS,KAAA,EAClB;AACI,EAAA,OAAO,UAAU,IAAA,IACb,OAAO,UAAU,QAAA,IACjB,QAAA,IAAY,SACZ,SAAA,IAAa,KAAA;AACrB;AASA,SAAS,cAAA,CAAe,QAAqB,SAAA,EAC7C;AACI,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,GAAG,CAAA;AACjC,EAAA,IAAI,UAAe,MAAA,CAAO,MAAA;AAE1B,EAAA,KAAA,MAAW,QAAQ,KAAA,EACnB;AACI,IAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,EACnC;AACI,MAAA,OAAO,IAAA;AAAA,IACX;AAEA,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAI,CAAA;AAEzB,IAAA,IAAI,QAAA,CAAS,IAAI,CAAA,EACjB;AACI,MAAA,OAAA,GAAU,IAAA,CAAK,MAAA;AAAA,IACnB,CAAA,MAAA,IACS,UAAA,CAAW,IAAI,CAAA,EACxB;AACI,MAAA,OAAO,IAAA;AAAA,IACX,CAAA,MAEA;AACI,MAAA,OAAA,GAAU,IAAA;AAAA,IACd;AAAA,EACJ;AAEA,EAAA,IAAI,UAAA,CAAW,OAAO,CAAA,EACtB;AACI,IAAA,OAAO,OAAA;AAAA,EACX;AAEA,EAAA,OAAO,IAAA;AACX;AAgBO,SAAS,eAA4C,MAAA,EAC5D;AACI,EAAA,MAAM;AAAA,IACF,MAAA,GAAS,IAAI,YAAA,IAAgB,uBAAA;AAAA,IAC7B,KAAA,GAAQ,IAAI,QAAA,KAAa,aAAA;AAAA,IACzB,OAAA,GAAU,GAAA;AAAA,IACV,OAAA,EAAS,iBAAiB,EAAC;AAAA,IAC3B,YAAA;AAAA,IACA,wBAAA,GAA2B,IAAA;AAAA,IAC3B;AAAA,GACJ,GAAI,MAAA;AAGJ,EAAA,MAAM,WAAA,GAAc,UAAA,IAAc,MAAA,IAAU,MAAA,CAAO,QAAA,KAAa,MAAA;AAChE,EAAA,MAAM,QAAA,GAAW,WAAA,GAAc,MAAA,CAAO,QAAA,GAAW,IAAA;AACjD,EAAA,MAAM,SAAS,CAAC,WAAA,IAAe,QAAA,IAAY,MAAA,GAAS,OAAO,MAAA,GAAS,IAAA;AAGpE,EAAA,MAAM,cAAA,GAAiB,MAAA,EAAQ,eAAA,IAAmB,EAAC;AAKnD,EAAA,SAAS,aAAa,SAAA,EACtB;AAEI,IAAA,IAAI,QAAA,EACJ;AACI,MAAA,MAAM,KAAA,GAAQ,SAAS,SAAS,CAAA;AAChC,MAAA,IAAI,KAAA,EACJ;AACI,QAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAQ,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,MACpD;AACA,MAAA,OAAO,IAAA;AAAA,IACX;AAGA,IAAA,IAAI,MAAA,EACJ;AACI,MAAA,IAAI,QAAA,GAAW,cAAA,CAAe,MAAA,EAAQ,SAAS,CAAA;AAG/C,MAAA,IAAI,CAAC,QAAA,IAAY,cAAA,CAAe,MAAA,GAAS,CAAA,EACzC;AACI,QAAA,KAAA,MAAW,aAAa,cAAA,EACxB;AACI,UAAA,QAAA,GAAW,cAAA,CAAe,WAAW,SAAS,CAAA;AAC9C,UAAA,IAAI,QAAA,EACJ;AACI,YAAA,IAAI,KAAA,EACJ;AACI,cAAA,SAAA,CAAU,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,yBAAA,CAA2B,CAAA;AAAA,YAClE;AACA,YAAA;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAEA,MAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,IAAU,QAAA,CAAS,IAAA,EAC5C;AACI,QAAA,OAAO,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,IAAA,EAAM,SAAS,IAAA,EAAK;AAAA,MAC1D;AAAA,IACJ;AAEA,IAAA,OAAO,IAAA;AAAA,EACX;AAKA,EAAA,eAAe,SAAA,CACX,SACA,OAAA,EAEJ;AACI,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA;AAE7B,IAAA,IACA;AACI,MAAA,MAAM,YAAY,MAAA,CAAO,SAAA;AAEzB,MAAA,IAAI,CAAC,SAAA,EACL;AACI,QAAA,OAAO,YAAA,CAAa,IAAA;AAAA,UAChB,kBAAA,CAAmB,aAAA,EAAe,6BAAA,EAA+B,KAAK,CAAA;AAAA,UACtE,EAAE,QAAQ,GAAA;AAAI,SAClB;AAAA,MACJ;AAGA,MAAA,IAAI,QAOA,EAAC;AACL,MAAA,IAAI,WAAA,GAA+B,IAAA;AAEnC,MAAA,IAAI,OAAA,CAAQ,WAAW,KAAA,EACvB;AACI,QAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,OAAA,CAAQ,YAAA,CAAa,IAAI,OAAO,CAAA;AAC3D,QAAA,IAAI,UAAA,EACJ;AACI,UAAA,IACA;AACI,YAAA,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmB,UAAU,CAAC,CAAA;AAAA,UACrD,CAAA,CAAA,MAEA;AACI,YAAA,OAAO,YAAA,CAAa,IAAA;AAAA,cAChB,kBAAA,CAAmB,aAAA,EAAe,yBAAA,EAA2B,KAAK,CAAA;AAAA,cAClE,EAAE,QAAQ,GAAA;AAAI,aAClB;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,CAAA,MAEA;AAEI,QAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAE3D,QAAA,IAAI,WAAA,CAAY,QAAA,CAAS,qBAAqB,CAAA,EAC9C;AAEI,UAAA,IACA;AACI,YAAA,WAAA,GAAc,MAAM,QAAQ,QAAA,EAAS;AAGrC,YAAA,MAAM,WAAA,GAAc,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA;AAChD,YAAA,IAAI,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAA,EAC1C;AACI,cAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA;AACvC,cAAA,KAAA,CAAM,SAAS,QAAA,CAAS,MAAA;AACxB,cAAA,KAAA,CAAM,QAAQ,QAAA,CAAS,KAAA;AACvB,cAAA,KAAA,CAAM,UAAU,QAAA,CAAS,OAAA;AACzB,cAAA,KAAA,CAAM,UAAU,QAAA,CAAS,OAAA;AAAA,YAC7B;AAGA,YAAA,KAAA,CAAM,WAAW,EAAC;AAClB,YAAA,WAAA,CAAY,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAC5B;AACI,cAAA,IAAI,QAAQ,YAAA,EAAc;AAE1B,cAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,CAAU,GAAG,CAAA;AACpC,cAAA,IAAI,aAAa,MAAA,EACjB;AAEI,gBAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAC1B;AACI,kBAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA,gBACvB,CAAA,MAEA;AACI,kBAAA,KAAA,CAAM,QAAA,CAAU,GAAG,CAAA,GAAI,CAAC,UAAU,KAAK,CAAA;AAAA,gBAC3C;AAAA,cACJ,CAAA,MAEA;AACI,gBAAA,KAAA,CAAM,QAAA,CAAU,GAAG,CAAA,GAAI,KAAA;AAAA,cAC3B;AAAA,YACJ,CAAC,CAAA;AAAA,UACL,SACO,KAAA,EACP;AACI,YAAA,OAAO,YAAA,CAAa,IAAA;AAAA,cAChB,kBAAA,CAAmB,aAAA,EAAe,mBAAA,EAAqB,KAAK,CAAA;AAAA,cAC5D,EAAE,QAAQ,GAAA;AAAI,aAClB;AAAA,UACJ;AAAA,QACJ,CAAA,MAEA;AAEI,UAAA,IACA;AACI,YAAA,KAAA,GAAQ,MAAM,QAAQ,IAAA,EAAK;AAAA,UAC/B,CAAA,CAAA,MAEA;AACI,YAAA,OAAO,YAAA,CAAa,IAAA;AAAA,cAChB,kBAAA,CAAmB,aAAA,EAAe,mBAAA,EAAqB,KAAK,CAAA;AAAA,cAC5D,EAAE,QAAQ,GAAA;AAAI,aAClB;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAGA,MAAA,MAAM,SAAA,GAAY,aAAa,SAAS,CAAA;AAExC,MAAA,IAAI,CAAC,SAAA,EACL;AACI,QAAA,SAAA,CAAU,IAAA,CAAK,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAE,CAAA;AAC9C,QAAA,OAAO,YAAA,CAAa,IAAA;AAAA,UAChB,kBAAA,CAAmB,WAAA,EAAa,CAAA,OAAA,EAAU,SAAS,eAAe,KAAK,CAAA;AAAA,UACvE,EAAE,QAAQ,GAAA;AAAI,SAClB;AAAA,MACJ;AAEA,MAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,IAAA,EAAM,YAAW,GAAI,SAAA;AAGnD,MAAA,MAAM,WAAA,GAAc,KAAA,CAAM,MAAA,IAAU,EAAC;AACrC,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,IAAS,EAAC;AACnC,MAAA,MAAM,YAAY,KAAA,CAAM,IAAA;AACxB,MAAA,MAAM,gBAAgB,KAAA,CAAM,QAAA;AAC5B,MAAA,MAAM,WAAA,GAAc,gBAAgB,IAAA,IAAQ,aAAA,IAAiB,OAAO,IAAA,CAAK,aAAa,EAAE,MAAA,GAAS,CAAA;AAEjG,MAAA,MAAM,YAAA,GAAe,kBAAA,CAAmB,UAAA,EAAY,WAAW,CAAA;AAC/D,MAAA,MAAM,WAAA,GAAc,iBAAiB,UAAU,CAAA;AAC/C,MAAA,MAAM,YAAY,CAAA,EAAG,MAAM,CAAA,EAAG,YAAY,GAAG,WAAW,CAAA,CAAA;AAExD,MAAA,IAAI,KAAA,EACJ;AACI,QAAA,SAAA,CAAU,MAAM,oBAAA,EAAiB;AAAA,UAC7B,SAAA;AAAA,UACA,YAAA;AAAA,UACA,UAAA,EAAY,YAAA;AAAA,UACZ,SAAA;AAAA,UACA,OAAA,EAAS,CAAC,CAAC,SAAA;AAAA,UACX;AAAA,SACH,CAAA;AAAA,MACL;AAGA,MAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,OAAA,CAAQ,OAAA,EAAS,cAAc,CAAA;AAGjE,MAAA,IAAI,WAAA,EACJ;AACI,QAAA,OAAA,CAAQ,OAAO,cAAc,CAAA;AAAA,MACjC;AAGA,MAAA,MAAM,YAAA,GAA4B;AAAA,QAC9B,MAAA,EAAQ,YAAA;AAAA,QACR;AAAA,OACJ;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAClD;AACI,QAAA,IAAI,eAAe,WAAA,EACnB;AAEI,UAAA,MAAM,eAAA,GAAkB,IAAI,QAAA,EAAS;AACrC,UAAA,WAAA,CAAY,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAC5B;AACI,YAAA,IAAI,QAAQ,YAAA,EACZ;AACI,cAAA,eAAA,CAAgB,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,YACrC;AAAA,UACJ,CAAC,CAAA;AACD,UAAA,YAAA,CAAa,IAAA,GAAO,eAAA;AAAA,QACxB,WACS,SAAA,EACT;AACI,UAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,SAAS,CAAA;AAAA,QAChD;AAAA,MACJ;AAOA,MAAA,MAAM,eAAA,GAAkB,mBAAA,CAAoB,wBAAA,EAA0B,uBAAA,EAAyB,cAAc,mBAAmB,CAAA;AAChI,MAAA,MAAM,oBAAA,GAAuB,0BAAA,CAA2B,eAAA,EAAiB,YAAA,EAAc,YAAY,CAAA;AAEnG,MAAA,IAAI,KAAA,IAAS,oBAAA,CAAqB,MAAA,GAAS,CAAA,EAC3C;AACI,QAAA,SAAA,CAAU,KAAA,CAAM,mBAAY,oBAAA,CAAqB,MAAM,8BAA8B,YAAY,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAAA,MACvH;AAGA,MAAA,MAAM,UAAA,GAAa,4BAA4B,OAAO,CAAA;AACtD,MAAA,MAAM,UAAA,GAAa,mBAAA;AAAA,QACf,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA;AAAA,QACpB,YAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA;AAAA,QACA,IAAI,eAAA,CAAgB,WAAA,CAAY,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA;AAAA,QACxC,UAAA;AAAA,QACA;AAAA,OACJ;AAGA,MAAA,MAAM,wBAAA,GAA2B,oBAAA,CAAqB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAkC,CAAC,CAAC,CAAC,CAAA;AACvH,MAAA,IAAI,wBAAA,CAAyB,SAAS,CAAA,EACtC;AACI,QAAA,MAAM,0BAAA,CAA2B,YAAY,wBAAwB,CAAA;AAGrE,QAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAA,EAC5D;AACI,UAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,QAC1B;AAGA,QAAA,IAAI,WAAW,IAAA,EACf;AACI,UAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,UAAA,CAAW,IAAI,CAAA;AAAA,QACtD;AAAA,MACJ;AAGA,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,MAAM,YAAY,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE9D,MAAA,IACA;AACI,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,SAAA,EAAW;AAAA,UACpC,GAAG,YAAA;AAAA,UACH,QAAQ,UAAA,CAAW;AAAA,SACtB,CAAA;AAED,QAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,QAAA,IAAI,IAAA,GAAO,MAAM,iBAAA,CAAkB,QAAQ,CAAA;AAO3C,QAAA,MAAM,WAAA,GAAc,oBAAA;AAAA,UAChB,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA,UACpB,YAAA;AAAA,UACA,OAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,UACA,IAAA;AAAA,UACA,UAAA,CAAW,QAAA;AAAA,UACX,UAAA,CAAW;AAAA,SACf;AAGA,QAAA,MAAM,yBAAA,GAA4B,oBAAA,CAAqB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAkC,CAAC,CAAC,CAAC,CAAA;AACzH,QAAA,IAAI,yBAAA,CAA0B,SAAS,CAAA,EACvC;AACI,UAAA,MAAM,2BAAA,CAA4B,aAAa,yBAAyB,CAAA;AACxE,UAAA,IAAA,GAAO,YAAY,QAAA,CAAS,IAAA;AAAA,QAChC;AAEA,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAE9B,QAAA,IAAI,KAAA,EACJ;AACI,UAAA,SAAA,CAAU,MAAM,qBAAA,EAAkB;AAAA,YAC9B,SAAA;AAAA,YACA,MAAA,EAAQ,YAAY,QAAA,CAAS,MAAA;AAAA,YAC7B,QAAA,EAAU,GAAG,QAAQ,CAAA,EAAA;AAAA,WACxB,CAAA;AAAA,QACL;AAIA,QAAA,MAAM,eAAe,WAAA,CAAY,QAAA,CAAS,WAAW,GAAA,GAC/C,IAAI,aAAa,IAAA,EAAM;AAAA,UACrB,MAAA,EAAQ,GAAA;AAAA,UACR,UAAA,EAAY,YAAY,QAAA,CAAS;AAAA,SACpC,CAAA,GACC,YAAA,CAAa,IAAA,CAAK,IAAA,EAAM;AAAA,UACtB,MAAA,EAAQ,YAAY,QAAA,CAAS,MAAA;AAAA,UAC7B,UAAA,EAAY,YAAY,QAAA,CAAS;AAAA,SACpC,CAAA;AAGL,QAAA,sBAAA,CAAuB,QAAA,CAAS,OAAA,EAAS,YAAA,CAAa,OAAO,CAAA;AAG7D,QAAA,KAAA,MAAW,MAAA,IAAU,YAAY,UAAA,EACjC;AACI,UAAA,MAAM,eAAA,GAAkB,qBAAqB,MAAM,CAAA;AACnD,UAAA,YAAA,CAAa,OAAA,CAAQ,MAAA,CAAO,YAAA,EAAc,eAAe,CAAA;AAEzD,UAAA,IAAI,KAAA,EACJ;AACI,YAAA,SAAA,CAAU,MAAM,mCAAA,EAA8B;AAAA,cAC1C,MAAM,MAAA,CAAO;AAAA,aAChB,CAAA;AAAA,UACL;AAAA,QACJ;AAEA,QAAA,OAAO,YAAA;AAAA,MACX,SACO,KAAA,EACP;AACI,QAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,QAAA,IAAI,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,IAAA,KAAS,YAAA,EAC7C;AACI,UAAA,SAAA,CAAU,MAAM,iBAAA,EAAmB;AAAA,YAC/B,SAAA;AAAA,YACA,SAAA;AAAA,YACA;AAAA,WACH,CAAA;AAED,UAAA,OAAO,YAAA,CAAa,IAAA;AAAA,YAChB,mBAAmB,iBAAA,EAAmB,CAAA,wBAAA,EAA2B,OAAO,CAAA,EAAA,CAAA,EAAM,OAAO,KAAK,CAAA;AAAA,YAC1F,EAAE,QAAQ,GAAA;AAAI,WAClB;AAAA,QACJ;AAGA,QAAA,MAAM,QAAA,GAAW,KAAA;AACjB,QAAA,SAAA,CAAU,MAAM,aAAA,EAAe;AAAA,UAC3B,SAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAO,QAAA,CAAS;AAAA,SACnB,CAAA;AAED,QAAA,OAAO,YAAA,CAAa,IAAA;AAAA,UAChB,mBAAmB,aAAA,EAAe,QAAA,CAAS,OAAA,IAAW,8BAAA,EAAgC,OAAO,QAAQ,CAAA;AAAA,UACrG,EAAE,QAAQ,GAAA;AAAI,SAClB;AAAA,MACJ;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC9B,MAAA,MAAM,GAAA,GAAM,KAAA;AAEZ,MAAA,SAAA,CAAU,MAAM,iBAAA,EAAmB;AAAA,QAC/B,OAAO,GAAA,CAAI,OAAA;AAAA,QACX,OAAO,GAAA,CAAI,KAAA;AAAA,QACX,QAAA,EAAU,GAAG,QAAQ,CAAA,EAAA;AAAA,OACxB,CAAA;AAED,MAAA,OAAO,YAAA,CAAa,IAAA;AAAA,QAChB,mBAAmB,uBAAA,EAAyB,GAAA,CAAI,OAAA,IAAW,eAAA,EAAiB,OAAO,GAAG,CAAA;AAAA,QACtF,EAAE,QAAQ,GAAA;AAAI,OAClB;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,OAAO;AAAA,IACH,KAAK,CAAC,GAAA,EAAkB,OAAA,KACpB,SAAA,CAAU,KAAK,OAAO,CAAA;AAAA,IAC1B,MAAM,CAAC,GAAA,EAAkB,OAAA,KACrB,SAAA,CAAU,KAAK,OAAO;AAAA,GAC9B;AACJ","file":"server.js","sourcesContent":["/**\n * Shared utilities for Next.js client and proxy modules\n *\n * Contains common functions used by both client and proxy to avoid code duplication.\n */\n\n/**\n * Build URL with path parameters replaced\n *\n * @example\n * buildUrlWithParams('/users/:id/posts/:postId', { id: '123', postId: '456' })\n * // Returns: '/users/123/posts/456'\n */\nexport function buildUrlWithParams(path: string, params: Record<string, any>): string\n{\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n return url;\n}\n\n/**\n * Build query string from object\n *\n * @example\n * buildQueryString({ page: '1', limit: '10', tags: ['foo', 'bar'] })\n * // Returns: '?page=1&limit=10&tags=foo&tags=bar'\n */\nexport function buildQueryString(query: Record<string, any>): string\n{\n if (Object.keys(query).length === 0)\n {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => searchParams.append(key, String(v)));\n }\n else\n {\n searchParams.append(key, String(value));\n }\n }\n\n return `?${searchParams.toString()}`;\n}\n\n/**\n * Build Cookie header string from cookies object\n *\n * @example\n * buildCookieHeader({ session: 'abc123', theme: 'dark' })\n * // Returns: 'session=abc123; theme=dark'\n */\nexport function buildCookieHeader(cookies: Record<string, string>): string\n{\n return Object.entries(cookies)\n .map(([key, value]) => `${key}=${value}`)\n .join('; ');\n}\n\n/**\n * Parse response body based on content type\n *\n * Handles:\n * - 204 No Content: returns null (no body expected)\n * - application/json: parses JSON body\n * - Other content types: returns raw text\n */\nexport async function parseResponseBody(response: Response): Promise<any>\n{\n // 204 No Content has no body\n if (response.status === 204)\n {\n return null;\n }\n\n const contentType = response.headers.get('content-type');\n\n if (contentType?.includes('application/json'))\n {\n const text = await response.text();\n return text ? JSON.parse(text) : null;\n }\n else\n {\n return await response.text();\n }\n}","/**\n * SPFN Next.js Proxy Interceptor Execution Engine\n */\n\nimport type {\n InterceptorRule,\n RequestInterceptor,\n ResponseInterceptor,\n RequestInterceptorContext,\n ResponseInterceptorContext,\n} from './types';\n\n/**\n * Check if path matches pattern\n *\n * Supports:\n * - Wildcards: '/_auth/*' matches '/_auth/login'\n * - Path params: '/users/:id' matches '/users/123'\n * - RegExp: /^\\/_auth\\/.+$/ matches '/_auth/login'\n * - Exact match: '/_auth/login' matches '/_auth/login'\n * - All: '*' matches any path\n *\n * @param path - Request path to test\n * @param pattern - Pattern to match against\n * @returns True if path matches pattern\n */\nexport function matchPath(path: string, pattern: string | RegExp): boolean\n{\n // Match all\n if (pattern === '*')\n {\n return true;\n }\n\n // RegExp pattern\n if (pattern instanceof RegExp)\n {\n return pattern.test(path);\n }\n\n // String pattern\n // Convert wildcard pattern to RegExp\n // '/_auth/*' -> /^\\/_auth\\/.*/\n // '/users/:id' -> /^\\/users\\/[^/]+$/\n const regexPattern = pattern\n .replace(/\\*/g, '.*')\n .replace(/:[^/]+/g, '[^/]+')\n .replace(/\\//g, '\\\\/');\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(path);\n}\n\n/**\n * Check if method matches pattern\n *\n * @param method - Request method (e.g., 'POST')\n * @param pattern - Method pattern (e.g., 'POST' or ['POST', 'PUT'])\n * @returns True if method matches pattern\n */\nexport function matchMethod(\n method: string,\n pattern?: string | string[]\n): boolean\n{\n // No method filter = match all\n if (!pattern)\n {\n return true;\n }\n\n // Single method\n if (typeof pattern === 'string')\n {\n return method.toUpperCase() === pattern.toUpperCase();\n }\n\n // Multiple methods\n return pattern.some((m) => m.toUpperCase() === method.toUpperCase());\n}\n\n/**\n * Filter interceptors that match the request\n *\n * @param rules - All interceptor rules\n * @param path - Request path\n * @param method - Request method\n * @returns Matched interceptors\n */\nexport function filterMatchingInterceptors(\n rules: InterceptorRule[],\n path: string,\n method: string\n): InterceptorRule[]\n{\n return rules.filter((rule) => {\n return matchPath(path, rule.pathPattern) && matchMethod(method, rule.method);\n });\n}\n\n/**\n * Execute request interceptors in chain\n *\n * Interceptors are executed in order:\n * 1. First registered interceptor\n * 2. Second registered interceptor\n * 3. ... and so on\n *\n * Each interceptor must call next() to continue the chain.\n * If next() is not called, the chain stops and remaining interceptors are skipped.\n *\n * @param context - Request interceptor context\n * @param interceptors - Interceptors to execute\n */\nexport async function executeRequestInterceptors(\n context: RequestInterceptorContext,\n interceptors: RequestInterceptor[]\n): Promise<void>\n{\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index >= interceptors.length)\n {\n return;\n }\n\n const interceptor = interceptors[index];\n index++;\n\n await interceptor(context, next);\n };\n\n await next();\n}\n\n/**\n * Execute response interceptors in chain\n *\n * Interceptors are executed in order:\n * 1. First registered interceptor\n * 2. Second registered interceptor\n * 3. ... and so on\n *\n * Each interceptor must call next() to continue the chain.\n * If next() is not called, the chain stops and remaining interceptors are skipped.\n *\n * @param context - Response interceptor context\n * @param interceptors - Interceptors to execute\n */\nexport async function executeResponseInterceptors(\n context: ResponseInterceptorContext,\n interceptors: ResponseInterceptor[]\n): Promise<void>\n{\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index >= interceptors.length)\n {\n return;\n }\n\n const interceptor = interceptors[index];\n index++;\n\n await interceptor(context, next);\n };\n\n await next();\n}","/**\n * Global Interceptor Registry\n *\n * Allows packages to automatically register their interceptors\n * for Next.js proxy without manual configuration.\n *\n * Uses globalThis for persistence across module reloads (HMR).\n */\nimport type { InterceptorRule } from './types';\n\n// ============================================================================\n// Global Type Declarations\n// ============================================================================\n\n/**\n * Extend globalThis with interceptor registry\n *\n * Using globalThis allows the registry to persist across module reloads (HMR).\n * preventing duplicate registrations during development with HMR.\n */\ndeclare global\n{\n var __SPFN_INTERCEPTOR_REGISTRY__: InterceptorRegistry | undefined;\n}\n\n/**\n * Global interceptor registry\n *\n * Packages register their interceptors on import,\n * and proxy automatically discovers and applies them.\n */\nexport class InterceptorRegistry\n{\n private interceptors = new Map<string, InterceptorRule[]>();\n\n /**\n * Register interceptors for a package\n *\n * @param packageName - Unique package identifier (e.g., 'auth', 'storage')\n * @param interceptors - Array of interceptor rules\n *\n * @example\n * ```typescript\n * registerInterceptors('auth', [\n * {\n * pathPattern: '/_auth/*',\n * request: async (ctx, next) => { ... }\n * }\n * ]);\n * ```\n */\n register(packageName: string, interceptors: InterceptorRule[]): void\n {\n if (!this.interceptors.has(packageName))\n {\n this.interceptors.set(packageName, interceptors);\n }\n }\n\n /**\n * Get all registered interceptors\n *\n * @param exclude - Package names to exclude\n * @returns Flat array of all interceptor rules\n */\n getAll(exclude: string[] = []): InterceptorRule[]\n {\n const all: InterceptorRule[] = [];\n\n for (const [packageName, interceptors] of this.interceptors.entries())\n {\n if (!exclude.includes(packageName))\n {\n all.push(...interceptors);\n }\n }\n\n return all;\n }\n\n /**\n * Get interceptors for specific package\n *\n * @param packageName - Package identifier\n * @returns Interceptor rules or undefined\n */\n get(packageName: string): InterceptorRule[] | undefined\n {\n return this.interceptors.get(packageName);\n }\n\n /**\n * Get list of registered package names\n */\n getPackageNames(): string[]\n {\n return Array.from(this.interceptors.keys());\n }\n\n /**\n * Check if package has registered interceptors\n */\n has(packageName: string): boolean\n {\n return this.interceptors.has(packageName);\n }\n\n /**\n * Unregister interceptors for a package\n *\n * @param packageName - Package identifier\n */\n unregister(packageName: string): void\n {\n this.interceptors.delete(packageName);\n }\n\n /**\n * Clear all registered interceptors\n *\n * Useful for testing\n */\n clear(): void\n {\n this.interceptors.clear();\n }\n\n /**\n * Get total count of registered interceptors\n */\n count(): number\n {\n let total = 0;\n for (const interceptors of this.interceptors.values())\n {\n total += interceptors.length;\n }\n return total;\n }\n}\n\n/**\n * Global singleton registry instance\n *\n * Uses globalThis to persist across module reloads (HMR).\n * This prevents duplicate registrations during development.\n */\nexport const interceptorRegistry = (() =>\n{\n if (!globalThis.__SPFN_INTERCEPTOR_REGISTRY__)\n {\n globalThis.__SPFN_INTERCEPTOR_REGISTRY__ = new InterceptorRegistry();\n }\n\n return globalThis.__SPFN_INTERCEPTOR_REGISTRY__;\n})();\n\n/**\n * Register interceptors for a package\n *\n * This should be called during package initialization (on import).\n * The interceptors will be automatically applied by the Next.js proxy.\n *\n * @param packageName - Unique package identifier (e.g., 'auth', 'storage')\n * @param interceptors - Array of interceptor rules\n *\n * @example\n * ```typescript\n * // packages/auth/src/adapters/nextjs/interceptors/index.ts\n * import { registerInterceptors } from '@spfn/core/nextjs';\n *\n * const authInterceptors = [\n * {\n * pathPattern: '/_auth/*',\n * request: async (ctx, next) => {\n * // Add JWT token\n * ctx.headers['Authorization'] = 'Bearer token';\n * await next();\n * }\n * }\n * ];\n *\n * // Auto-register on import\n * registerInterceptors('auth', authInterceptors);\n * ```\n */\nexport function registerInterceptors(\n packageName: string,\n interceptors: InterceptorRule[]\n): void\n{\n interceptorRegistry.register(packageName, interceptors);\n}","/**\n * Helper functions for proxy handler\n * Separates utility logic from main proxy handler for better maintainability\n */\nimport { NextRequest } from 'next/server';\nimport type { CookieOptions, SetCookie } from \"../client\";\nimport type { InterceptorRule, RequestInterceptorContext, ResponseInterceptorContext } from './interceptors/types';\nimport type { InterceptorRegistry } from './interceptors';\n\n// Re-export from shared\nexport { parseResponseBody } from '../shared';\n\n/**\n * Build request headers for proxying\n * Forwards important headers from source and adds default headers\n *\n * @param sourceHeaders - Source headers (can be Headers object or Record)\n * @param defaultHeaders - Default headers to add\n */\nexport function buildProxyHeaders(\n sourceHeaders: Headers | Record<string, string>,\n defaultHeaders: Record<string, string>\n): Headers\n{\n const headers = new Headers();\n\n // Forward important headers from source\n const headersToForward = [\n 'content-type',\n 'authorization',\n 'cookie',\n 'user-agent',\n 'accept',\n 'accept-language',\n ];\n\n for (const header of headersToForward)\n {\n const value = sourceHeaders instanceof Headers\n ? sourceHeaders.get(header)\n : sourceHeaders[header];\n\n if (value)\n {\n headers.set(header, value);\n }\n }\n\n // Add default headers\n for (const [key, value] of Object.entries(defaultHeaders))\n {\n headers.set(key, value);\n }\n\n return headers;\n}\n\n/**\n * Parse cookies from Cookie header string\n *\n * @param cookieHeader - Cookie header string (e.g., \"session=abc; theme=dark\")\n * @returns Map of cookie name-value pairs\n */\nexport function parseCookies(cookieHeader: string | null | undefined): Map<string, string>\n{\n const cookiesMap = new Map<string, string>();\n\n if (!cookieHeader)\n {\n return cookiesMap;\n }\n\n const cookiePairs = cookieHeader.split(';').map(c => c.trim());\n for (const pair of cookiePairs)\n {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0)\n {\n const value = valueParts.join('='); // Handle = in cookie value\n cookiesMap.set(name.trim(), value.trim());\n }\n }\n\n return cookiesMap;\n}\n\n/**\n * Parse cookies from NextRequest (Next.js specific helper)\n * Combines cookies from both NextRequest.cookies and Cookie header\n */\nexport function parseCookiesFromNextRequest(request: NextRequest): Map<string, string>\n{\n const cookiesMap = new Map<string, string>();\n\n // Add cookies from NextRequest (browser cookies)\n for (const cookie of request.cookies.getAll())\n {\n cookiesMap.set(cookie.name, cookie.value);\n }\n\n // Add cookies from Cookie header (server-side forwarded cookies)\n const cookieHeader = request.headers.get('cookie');\n if (cookieHeader)\n {\n const parsed = parseCookies(cookieHeader);\n for (const [name, value] of parsed.entries())\n {\n cookiesMap.set(name, value);\n }\n }\n\n return cookiesMap;\n}\n\n// Mapping of option names to Set-Cookie attribute formats\nconst optionMappings: Array<{\n key: keyof CookieOptions;\n format: (value: any) => string | null;\n}> = [\n { key: 'httpOnly', format: (v) => v ? 'HttpOnly' : null },\n { key: 'secure', format: (v) => v ? 'Secure' : null },\n { key: 'sameSite', format: (v) => v ? `SameSite=${v}` : null },\n { key: 'maxAge', format: (v) => v !== undefined ? `Max-Age=${v}` : null },\n { key: 'path', format: (v) => v ? `Path=${v}` : null },\n { key: 'domain', format: (v) => v ? `Domain=${v}` : null },\n];\n\n/**\n * Build Set-Cookie header string from cookie options\n */\nexport function buildSetCookieHeader(cookie: SetCookie): string\n{\n const parts = [`${cookie.name}=${cookie.value}`];\n const options = cookie.options || {};\n\n for (const { key, format } of optionMappings)\n {\n const value = options[key];\n if (value !== undefined && value !== false)\n {\n const formatted = format(value);\n if (formatted)\n {\n parts.push(formatted);\n }\n }\n }\n\n return parts.join('; ');\n}\n\n/**\n * Build error response JSON\n */\nexport function buildErrorResponse(\n errorType: string,\n message: string,\n debug: boolean,\n error?: Error\n): any\n{\n return {\n error: errorType,\n message,\n ...(debug && error?.stack && { stack: error.stack }),\n };\n}\n\nconst headersToForward = [\n 'content-type',\n 'cache-control',\n 'set-cookie',\n 'etag',\n 'last-modified',\n];\n\n/**\n * Forward response headers back to client\n */\nexport function forwardResponseHeaders(\n sourceHeaders: Headers,\n targetHeaders: Headers\n): void\n{\n for (const header of headersToForward)\n {\n const value = sourceHeaders.get(header);\n if (value)\n {\n targetHeaders.set(header, value);\n }\n }\n}\n\n/**\n * Collect all interceptors (auto-discovered + config)\n */\nexport function collectInterceptors(\n autoDiscoverInterceptors: boolean,\n disableAutoInterceptors: string[] | undefined,\n configInterceptors: InterceptorRule[] | undefined,\n registry: InterceptorRegistry\n): InterceptorRule[]\n{\n const allInterceptors: InterceptorRule[] = [];\n\n // Auto-discover from registry\n if (autoDiscoverInterceptors)\n {\n const registeredInterceptors = registry.getAll(disableAutoInterceptors || []);\n allInterceptors.push(...registeredInterceptors);\n }\n\n // Add config interceptors\n if (configInterceptors)\n {\n allInterceptors.push(...configInterceptors);\n }\n\n return allInterceptors;\n}\n\n/**\n * Build RequestInterceptorContext\n */\nexport function buildRequestContext(\n path: string,\n method: string,\n headers: Headers,\n body: any,\n searchParams: URLSearchParams,\n cookiesMap: Map<string, string>,\n request: NextRequest\n): RequestInterceptorContext\n{\n return {\n path: `/${path}`,\n method,\n headers: Object.fromEntries(headers.entries()),\n body,\n query: Object.fromEntries(searchParams.entries()),\n cookies: cookiesMap,\n request,\n metadata: {},\n };\n}\n\n/**\n * Build ResponseInterceptorContext\n */\nexport function buildResponseContext(\n path: string,\n method: string,\n requestHeaders: Headers,\n requestBody: any,\n response: Response,\n responseBody: any,\n requestMetadata: Record<string, any>,\n cookies: Map<string, string>\n): ResponseInterceptorContext\n{\n return {\n path: `/${path}`,\n method,\n request: {\n headers: Object.fromEntries(requestHeaders.entries()),\n body: requestBody,\n },\n response: {\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n body: responseBody,\n },\n cookies,\n setCookies: [],\n metadata: requestMetadata,\n };\n}","/**\n * RPC-Style Proxy for define-route System\n *\n * Next.js API Route handler that resolves routeName to method/path\n * and forwards requests to SPFN backend.\n *\n * @example Using routeMap (recommended - no server code loaded)\n * ```typescript\n * // app/api/rpc/[routeName]/route.ts\n * import { routeMap } from '@/generated/route-map';\n * import { createRpcProxy } from '@spfn/core/nextjs/proxy';\n *\n * export const { GET, POST } = createRpcProxy({ routeMap });\n * ```\n *\n * @example Using router (legacy - loads full server code)\n * ```typescript\n * // app/api/rpc/[routeName]/route.ts\n * import { appRouter } from '@/server/router';\n * import { createRpcProxy } from '@spfn/core/nextjs/proxy';\n *\n * export const { GET, POST } = createRpcProxy({ router: appRouter });\n * ```\n */\nimport { NextRequest, NextResponse } from 'next/server';\n\nimport { env } from '@spfn/core/config';\nimport { logger } from '@spfn/core/logger';\nimport type { Router, RouteDef, HttpMethod } from '@spfn/core/route';\n\nimport { buildUrlWithParams, buildQueryString } from '../shared';\nimport { interceptorRegistry } from './interceptors';\nimport { executeRequestInterceptors, executeResponseInterceptors, filterMatchingInterceptors } from './interceptors';\nimport {\n buildProxyHeaders,\n parseCookiesFromNextRequest,\n buildSetCookieHeader,\n buildErrorResponse,\n forwardResponseHeaders,\n parseResponseBody,\n collectInterceptors,\n buildRequestContext,\n buildResponseContext,\n} from './helpers';\nimport type { TypedProxyConfig } from \"./types\";\n\nconst rpcLogger = logger.child('@spfn/core:rpc-proxy');\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Route info from generated route map\n */\nexport interface RouteMapEntry\n{\n method: HttpMethod;\n path: string;\n}\n\n/**\n * Generated route map type\n */\nexport type RouteMap = Record<string, RouteMapEntry>;\n\n/**\n * Base config for RPC proxy\n */\ninterface RpcProxyBaseConfig extends Omit<TypedProxyConfig, 'onRequest' | 'onResponse'> {}\n\n/**\n * Config using routeMap (recommended)\n *\n * Uses generated route map file - no server code loaded in Next.js process.\n */\nexport interface RpcProxyRouteMapConfig extends RpcProxyBaseConfig\n{\n /**\n * Generated route map containing routeName → {method, path} mappings\n *\n * @example\n * ```typescript\n * import { routeMap } from '@/generated/route-map';\n *\n * export const { GET, POST } = createRpcProxy({ routeMap });\n * ```\n */\n routeMap: RouteMap;\n router?: never;\n}\n\n/**\n * Config using router (legacy)\n *\n * @deprecated Use routeMap instead to avoid loading server code in Next.js process\n */\nexport interface RpcProxyRouterConfig<TRouter extends Router<any>> extends RpcProxyBaseConfig\n{\n /**\n * The router containing all route definitions\n *\n * @deprecated Use routeMap instead - router imports all server code\n *\n * @example\n * ```typescript\n * export const { GET, POST } = createRpcProxy({\n * router: appRouter,\n * });\n * ```\n */\n router: TRouter;\n routeMap?: never;\n}\n\n/**\n * Combined config type\n */\nexport type RpcProxyConfig<TRouter extends Router<any> = Router<any>> =\n | RpcProxyRouteMapConfig\n | RpcProxyRouterConfig<TRouter>;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Type guard to check if value is a RouteDef\n */\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'handler' in value &&\n 'method' in value &&\n 'path' in value;\n}\n\n/**\n * Type guard to check if value is a Router\n */\nfunction isRouter(value: unknown): value is Router<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'routes' in value &&\n '_routes' in value;\n}\n\n/**\n * Get route definition from router by dotted path\n *\n * @example\n * getRouteByPath(router, 'users.getUser') → RouteDef\n * getRouteByPath(router, 'getUser') → RouteDef\n */\nfunction getRouteByPath(router: Router<any>, routePath: string): RouteDef<any> | null\n{\n const parts = routePath.split('.');\n let current: any = router.routes;\n\n for (const part of parts)\n {\n if (!current || typeof current !== 'object')\n {\n return null;\n }\n\n const next = current[part];\n\n if (isRouter(next))\n {\n current = next.routes;\n }\n else if (isRouteDef(next))\n {\n return next;\n }\n else\n {\n current = next;\n }\n }\n\n if (isRouteDef(current))\n {\n return current;\n }\n\n return null;\n}\n\n// ============================================================================\n// RPC Proxy Handler\n// ============================================================================\n\n/**\n * Create RPC proxy handler for Next.js API Route\n *\n * Handles requests in the format:\n * - GET /api/rpc/{routeName}?input={...}\n * - POST /api/rpc/{routeName} with body\n *\n * Resolves routeName to actual HTTP method and path from the router or routeMap,\n * then forwards to SPFN backend.\n */\nexport function createRpcProxy<TRouter extends Router<any>>(config: RpcProxyConfig<TRouter>)\n{\n const {\n apiUrl = env.SPFN_API_URL || 'http://localhost:8790',\n debug = env.NODE_ENV === 'development',\n timeout = 30000,\n headers: defaultHeaders = {},\n interceptors,\n autoDiscoverInterceptors = true,\n disableAutoInterceptors,\n } = config;\n\n // Determine if using routeMap or router\n const useRouteMap = 'routeMap' in config && config.routeMap !== undefined;\n const routeMap = useRouteMap ? config.routeMap : null;\n const router = !useRouteMap && 'router' in config ? config.router : null;\n\n // Get package routers (only when using router mode)\n const packageRouters = router?._packageRouters || [];\n\n /**\n * Resolve route info from routeMap or router\n */\n function resolveRoute(routeName: string): { method: string; path: string } | null\n {\n // Try routeMap first (recommended)\n if (routeMap)\n {\n const entry = routeMap[routeName];\n if (entry)\n {\n return { method: entry.method, path: entry.path };\n }\n return null;\n }\n\n // Fall back to router (legacy)\n if (router)\n {\n let routeDef = getRouteByPath(router, routeName);\n\n // If not found in main router, search in package routers\n if (!routeDef && packageRouters.length > 0)\n {\n for (const pkgRouter of packageRouters)\n {\n routeDef = getRouteByPath(pkgRouter, routeName);\n if (routeDef)\n {\n if (debug)\n {\n rpcLogger.debug(`Route \"${routeName}\" found in package router`);\n }\n break;\n }\n }\n }\n\n if (routeDef && routeDef.method && routeDef.path)\n {\n return { method: routeDef.method, path: routeDef.path };\n }\n }\n\n return null;\n }\n\n /**\n * Handle RPC request\n */\n async function handleRpc(\n request: NextRequest,\n context: { params: Promise<{ routeName?: string }> }\n ): Promise<NextResponse>\n {\n const startTime = Date.now();\n const params = await context.params;\n\n try\n {\n const routeName = params.routeName;\n\n if (!routeName)\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Missing routeName parameter', debug),\n { status: 400 }\n );\n }\n\n // Parse input from query string (GET) or body (POST)\n let input: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n body?: Record<string, any>;\n formData?: Record<string, any>;\n headers?: Record<string, any>;\n cookies?: Record<string, any>;\n } = {};\n let rawFormData: FormData | null = null;\n\n if (request.method === 'GET')\n {\n const inputParam = request.nextUrl.searchParams.get('input');\n if (inputParam)\n {\n try\n {\n input = JSON.parse(decodeURIComponent(inputParam));\n }\n catch\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid input parameter', debug),\n { status: 400 }\n );\n }\n }\n }\n else\n {\n // POST - check Content-Type for formData vs JSON\n const contentType = request.headers.get('content-type') || '';\n\n if (contentType.includes('multipart/form-data'))\n {\n // Parse multipart/form-data\n try\n {\n rawFormData = await request.formData();\n\n // Extract __metadata if present (contains params, query, etc.)\n const metadataStr = rawFormData.get('__metadata');\n if (metadataStr && typeof metadataStr === 'string')\n {\n const metadata = JSON.parse(metadataStr);\n input.params = metadata.params;\n input.query = metadata.query;\n input.headers = metadata.headers;\n input.cookies = metadata.cookies;\n }\n\n // Collect formData fields (excluding __metadata)\n input.formData = {};\n rawFormData.forEach((value, key) =>\n {\n if (key === '__metadata') return;\n\n const existing = input.formData![key];\n if (existing !== undefined)\n {\n // Multiple values with same key\n if (Array.isArray(existing))\n {\n existing.push(value);\n }\n else\n {\n input.formData![key] = [existing, value];\n }\n }\n else\n {\n input.formData![key] = value;\n }\n });\n }\n catch (error)\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid form data', debug),\n { status: 400 }\n );\n }\n }\n else\n {\n // Parse JSON body\n try\n {\n input = await request.json();\n }\n catch\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid JSON body', debug),\n { status: 400 }\n );\n }\n }\n }\n\n // Resolve route info from routeMap or router\n const routeInfo = resolveRoute(routeName);\n\n if (!routeInfo)\n {\n rpcLogger.warn(`Route not found: ${routeName}`);\n return NextResponse.json(\n buildErrorResponse('Not Found', `Route \"${routeName}\" not found`, debug),\n { status: 404 }\n );\n }\n\n const { method: targetMethod, path: targetPath } = routeInfo;\n\n // Build target URL with params and query\n const inputParams = input.params || {};\n const inputQuery = input.query || {};\n const inputBody = input.body;\n const inputFormData = input.formData;\n const hasFormData = rawFormData !== null && inputFormData && Object.keys(inputFormData).length > 0;\n\n const resolvedPath = buildUrlWithParams(targetPath, inputParams);\n const queryString = buildQueryString(inputQuery);\n const targetUrl = `${apiUrl}${resolvedPath}${queryString}`;\n\n if (debug)\n {\n rpcLogger.debug('→ RPC request', {\n routeName,\n targetMethod,\n targetPath: resolvedPath,\n targetUrl,\n hasBody: !!inputBody,\n hasFormData,\n });\n }\n\n // Build headers\n const headers = buildProxyHeaders(request.headers, defaultHeaders);\n\n // Remove Content-Type for formData (let fetch set it with boundary)\n if (hasFormData)\n {\n headers.delete('content-type');\n }\n\n // Build fetch options\n const fetchOptions: RequestInit = {\n method: targetMethod,\n headers,\n };\n\n // Add body for POST/PUT/PATCH\n if (['POST', 'PUT', 'PATCH'].includes(targetMethod))\n {\n if (hasFormData && rawFormData)\n {\n // Forward formData to backend (rebuild without __metadata)\n const forwardFormData = new FormData();\n rawFormData.forEach((value, key) =>\n {\n if (key !== '__metadata')\n {\n forwardFormData.append(key, value);\n }\n });\n fetchOptions.body = forwardFormData;\n }\n else if (inputBody)\n {\n fetchOptions.body = JSON.stringify(inputBody);\n }\n }\n\n // ============================================================\n // Advanced Interceptors - BEFORE FETCH\n // ============================================================\n\n // Collect and filter interceptors\n const allInterceptors = collectInterceptors(autoDiscoverInterceptors, disableAutoInterceptors, interceptors, interceptorRegistry);\n const matchingInterceptors = filterMatchingInterceptors(allInterceptors, resolvedPath, targetMethod);\n\n if (debug && matchingInterceptors.length > 0)\n {\n rpcLogger.debug(`🎯 Found ${matchingInterceptors.length} matching interceptors for ${targetMethod} ${resolvedPath}`);\n }\n\n // Create RequestInterceptorContext\n const cookiesMap = parseCookiesFromNextRequest(request);\n const requestCtx = buildRequestContext(\n resolvedPath.slice(1), // Remove leading slash\n targetMethod,\n headers,\n inputBody,\n new URLSearchParams(queryString.slice(1)), // Remove leading ?\n cookiesMap,\n request\n );\n\n // Execute request interceptors\n const requestInterceptorsToRun = matchingInterceptors.map(r => r.request).filter((i): i is NonNullable<typeof i> => !!i);\n if (requestInterceptorsToRun.length > 0)\n {\n await executeRequestInterceptors(requestCtx, requestInterceptorsToRun);\n\n // Apply modified headers\n for (const [key, value] of Object.entries(requestCtx.headers))\n {\n headers.set(key, value);\n }\n\n // Apply modified body\n if (requestCtx.body)\n {\n fetchOptions.body = JSON.stringify(requestCtx.body);\n }\n }\n\n // Execute fetch with timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try\n {\n const response = await fetch(targetUrl, {\n ...fetchOptions,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n let body = await parseResponseBody(response);\n\n // ============================================================\n // Advanced Interceptors - AFTER FETCH\n // ============================================================\n\n // Create ResponseInterceptorContext\n const responseCtx = buildResponseContext(\n resolvedPath.slice(1),\n targetMethod,\n headers,\n inputBody,\n response,\n body,\n requestCtx.metadata,\n requestCtx.cookies\n );\n\n // Execute response interceptors\n const responseInterceptorsToRun = matchingInterceptors.map(r => r.response).filter((i): i is NonNullable<typeof i> => !!i);\n if (responseInterceptorsToRun.length > 0)\n {\n await executeResponseInterceptors(responseCtx, responseInterceptorsToRun);\n body = responseCtx.response.body;\n }\n\n const duration = Date.now() - startTime;\n\n if (debug)\n {\n rpcLogger.debug('← RPC response', {\n routeName,\n status: responseCtx.response.status,\n duration: `${duration}ms`,\n });\n }\n\n // Build Next.js response\n // 204 No Content should use NextResponse directly, not NextResponse.json()\n const nextResponse = responseCtx.response.status === 204\n ? new NextResponse(null, {\n status: 204,\n statusText: responseCtx.response.statusText,\n })\n : NextResponse.json(body, {\n status: responseCtx.response.status,\n statusText: responseCtx.response.statusText,\n });\n\n // Forward response headers\n forwardResponseHeaders(response.headers, nextResponse.headers);\n\n // Apply setCookies from interceptors\n for (const cookie of responseCtx.setCookies)\n {\n const setCookieHeader = buildSetCookieHeader(cookie);\n nextResponse.headers.append('Set-Cookie', setCookieHeader);\n\n if (debug)\n {\n rpcLogger.debug('🍪 Set-Cookie header added', {\n name: cookie.name,\n });\n }\n }\n\n return nextResponse;\n }\n catch (error)\n {\n clearTimeout(timeoutId);\n\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError')\n {\n rpcLogger.error('Request timeout', {\n routeName,\n targetUrl,\n timeout,\n });\n\n return NextResponse.json(\n buildErrorResponse('Gateway Timeout', `Request timed out after ${timeout}ms`, debug, error),\n { status: 504 }\n );\n }\n\n // Handle other fetch errors\n const fetchErr = error as Error;\n rpcLogger.error('Fetch error', {\n routeName,\n targetUrl,\n error: fetchErr.message,\n });\n\n return NextResponse.json(\n buildErrorResponse('Bad Gateway', fetchErr.message || 'Failed to connect to backend', debug, fetchErr),\n { status: 502 }\n );\n }\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n const err = error as Error;\n\n rpcLogger.error('RPC proxy error', {\n error: err.message,\n stack: err.stack,\n duration: `${duration}ms`,\n });\n\n return NextResponse.json(\n buildErrorResponse('Internal Server Error', err.message || 'Unknown error', debug, err),\n { status: 500 }\n );\n }\n }\n\n // Return route handlers\n return {\n GET: (req: NextRequest, context: { params: Promise<{ routeName?: string }> }) =>\n handleRpc(req, context),\n POST: (req: NextRequest, context: { params: Promise<{ routeName?: string }> }) =>\n handleRpc(req, context),\n };\n}"]}
1
+ {"version":3,"sources":["../../src/nextjs/shared.ts","../../src/nextjs/proxy/interceptors/helpers.ts","../../src/nextjs/proxy/interceptors/registry.ts","../../src/nextjs/proxy/helpers.ts","../../src/nextjs/proxy/rpc.ts"],"names":["headersToForward"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * Shared utilities for Next.js client and proxy modules\n *\n * Contains common functions used by both client and proxy to avoid code duplication.\n */\n\n/**\n * Build URL with path parameters replaced\n *\n * @example\n * buildUrlWithParams('/users/:id/posts/:postId', { id: '123', postId: '456' })\n * // Returns: '/users/123/posts/456'\n */\nexport function buildUrlWithParams(path: string, params: Record<string, any>): string\n{\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n return url;\n}\n\n/**\n * Build query string from object\n *\n * @example\n * buildQueryString({ page: '1', limit: '10', tags: ['foo', 'bar'] })\n * // Returns: '?page=1&limit=10&tags=foo&tags=bar'\n */\nexport function buildQueryString(query: Record<string, any>): string\n{\n if (Object.keys(query).length === 0)\n {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => searchParams.append(key, String(v)));\n }\n else\n {\n searchParams.append(key, String(value));\n }\n }\n\n return `?${searchParams.toString()}`;\n}\n\n/**\n * Build Cookie header string from cookies object\n *\n * @example\n * buildCookieHeader({ session: 'abc123', theme: 'dark' })\n * // Returns: 'session=abc123; theme=dark'\n */\nexport function buildCookieHeader(cookies: Record<string, string>): string\n{\n return Object.entries(cookies)\n .map(([key, value]) => `${key}=${value}`)\n .join('; ');\n}\n\n/**\n * Parse response body based on content type\n *\n * Handles:\n * - 204 No Content: returns null (no body expected)\n * - application/json: parses JSON body\n * - Other content types: returns raw text\n */\nexport async function parseResponseBody(response: Response): Promise<any>\n{\n // 204 No Content has no body\n if (response.status === 204)\n {\n return null;\n }\n\n const contentType = response.headers.get('content-type');\n\n if (contentType?.includes('application/json'))\n {\n const text = await response.text();\n return text ? JSON.parse(text) : null;\n }\n else\n {\n return await response.text();\n }\n}","/**\n * SPFN Next.js Proxy Interceptor Execution Engine\n */\n\nimport type {\n InterceptorRule,\n RequestInterceptor,\n ResponseInterceptor,\n RequestInterceptorContext,\n ResponseInterceptorContext,\n} from './types';\n\n/**\n * Check if path matches pattern\n *\n * Supports:\n * - Wildcards: '/_auth/*' matches '/_auth/login'\n * - Path params: '/users/:id' matches '/users/123'\n * - RegExp: /^\\/_auth\\/.+$/ matches '/_auth/login'\n * - Exact match: '/_auth/login' matches '/_auth/login'\n * - All: '*' matches any path\n *\n * @param path - Request path to test\n * @param pattern - Pattern to match against\n * @returns True if path matches pattern\n */\nexport function matchPath(path: string, pattern: string | RegExp): boolean\n{\n // Match all\n if (pattern === '*')\n {\n return true;\n }\n\n // RegExp pattern\n if (pattern instanceof RegExp)\n {\n return pattern.test(path);\n }\n\n // String pattern\n // Convert wildcard pattern to RegExp\n // '/_auth/*' -> /^\\/_auth\\/.*/\n // '/users/:id' -> /^\\/users\\/[^/]+$/\n const regexPattern = pattern\n .replace(/\\*/g, '.*')\n .replace(/:[^/]+/g, '[^/]+')\n .replace(/\\//g, '\\\\/');\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(path);\n}\n\n/**\n * Check if method matches pattern\n *\n * @param method - Request method (e.g., 'POST')\n * @param pattern - Method pattern (e.g., 'POST' or ['POST', 'PUT'])\n * @returns True if method matches pattern\n */\nexport function matchMethod(\n method: string,\n pattern?: string | string[]\n): boolean\n{\n // No method filter = match all\n if (!pattern)\n {\n return true;\n }\n\n // Single method\n if (typeof pattern === 'string')\n {\n return method.toUpperCase() === pattern.toUpperCase();\n }\n\n // Multiple methods\n return pattern.some((m) => m.toUpperCase() === method.toUpperCase());\n}\n\n/**\n * Filter interceptors that match the request\n *\n * @param rules - All interceptor rules\n * @param path - Request path\n * @param method - Request method\n * @returns Matched interceptors\n */\nexport function filterMatchingInterceptors(\n rules: InterceptorRule[],\n path: string,\n method: string\n): InterceptorRule[]\n{\n return rules.filter((rule) => {\n return matchPath(path, rule.pathPattern) && matchMethod(method, rule.method);\n });\n}\n\n/**\n * Execute request interceptors in chain\n *\n * Interceptors are executed in order:\n * 1. First registered interceptor\n * 2. Second registered interceptor\n * 3. ... and so on\n *\n * Each interceptor must call next() to continue the chain.\n * If next() is not called, the chain stops and remaining interceptors are skipped.\n *\n * @param context - Request interceptor context\n * @param interceptors - Interceptors to execute\n */\nexport async function executeRequestInterceptors(\n context: RequestInterceptorContext,\n interceptors: RequestInterceptor[]\n): Promise<void>\n{\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index >= interceptors.length)\n {\n return;\n }\n\n const interceptor = interceptors[index];\n index++;\n\n await interceptor(context, next);\n };\n\n await next();\n}\n\n/**\n * Execute response interceptors in chain\n *\n * Interceptors are executed in order:\n * 1. First registered interceptor\n * 2. Second registered interceptor\n * 3. ... and so on\n *\n * Each interceptor must call next() to continue the chain.\n * If next() is not called, the chain stops and remaining interceptors are skipped.\n *\n * @param context - Response interceptor context\n * @param interceptors - Interceptors to execute\n */\nexport async function executeResponseInterceptors(\n context: ResponseInterceptorContext,\n interceptors: ResponseInterceptor[]\n): Promise<void>\n{\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index >= interceptors.length)\n {\n return;\n }\n\n const interceptor = interceptors[index];\n index++;\n\n await interceptor(context, next);\n };\n\n await next();\n}","/**\n * Global Interceptor Registry\n *\n * Allows packages to automatically register their interceptors\n * for Next.js proxy without manual configuration.\n *\n * Uses globalThis for persistence across module reloads (HMR).\n */\nimport type { InterceptorRule } from './types';\n\n// ============================================================================\n// Global Type Declarations\n// ============================================================================\n\n/**\n * Extend globalThis with interceptor registry\n *\n * Using globalThis allows the registry to persist across module reloads (HMR).\n * preventing duplicate registrations during development with HMR.\n */\ndeclare global\n{\n var __SPFN_INTERCEPTOR_REGISTRY__: InterceptorRegistry | undefined;\n}\n\n/**\n * Global interceptor registry\n *\n * Packages register their interceptors on import,\n * and proxy automatically discovers and applies them.\n */\nexport class InterceptorRegistry\n{\n private interceptors = new Map<string, InterceptorRule[]>();\n\n /**\n * Register interceptors for a package\n *\n * @param packageName - Unique package identifier (e.g., 'auth', 'storage')\n * @param interceptors - Array of interceptor rules\n *\n * @example\n * ```typescript\n * registerInterceptors('auth', [\n * {\n * pathPattern: '/_auth/*',\n * request: async (ctx, next) => { ... }\n * }\n * ]);\n * ```\n */\n register(packageName: string, interceptors: InterceptorRule[]): void\n {\n if (!this.interceptors.has(packageName))\n {\n this.interceptors.set(packageName, interceptors);\n }\n }\n\n /**\n * Get all registered interceptors\n *\n * @param exclude - Package names to exclude\n * @returns Flat array of all interceptor rules\n */\n getAll(exclude: string[] = []): InterceptorRule[]\n {\n const all: InterceptorRule[] = [];\n\n for (const [packageName, interceptors] of this.interceptors.entries())\n {\n if (!exclude.includes(packageName))\n {\n all.push(...interceptors);\n }\n }\n\n return all;\n }\n\n /**\n * Get interceptors for specific package\n *\n * @param packageName - Package identifier\n * @returns Interceptor rules or undefined\n */\n get(packageName: string): InterceptorRule[] | undefined\n {\n return this.interceptors.get(packageName);\n }\n\n /**\n * Get list of registered package names\n */\n getPackageNames(): string[]\n {\n return Array.from(this.interceptors.keys());\n }\n\n /**\n * Check if package has registered interceptors\n */\n has(packageName: string): boolean\n {\n return this.interceptors.has(packageName);\n }\n\n /**\n * Unregister interceptors for a package\n *\n * @param packageName - Package identifier\n */\n unregister(packageName: string): void\n {\n this.interceptors.delete(packageName);\n }\n\n /**\n * Clear all registered interceptors\n *\n * Useful for testing\n */\n clear(): void\n {\n this.interceptors.clear();\n }\n\n /**\n * Get total count of registered interceptors\n */\n count(): number\n {\n let total = 0;\n for (const interceptors of this.interceptors.values())\n {\n total += interceptors.length;\n }\n return total;\n }\n}\n\n/**\n * Global singleton registry instance\n *\n * Uses globalThis to persist across module reloads (HMR).\n * This prevents duplicate registrations during development.\n */\nexport const interceptorRegistry = (() =>\n{\n if (!globalThis.__SPFN_INTERCEPTOR_REGISTRY__)\n {\n globalThis.__SPFN_INTERCEPTOR_REGISTRY__ = new InterceptorRegistry();\n }\n\n return globalThis.__SPFN_INTERCEPTOR_REGISTRY__;\n})();\n\n/**\n * Register interceptors for a package\n *\n * This should be called during package initialization (on import).\n * The interceptors will be automatically applied by the Next.js proxy.\n *\n * @param packageName - Unique package identifier (e.g., 'auth', 'storage')\n * @param interceptors - Array of interceptor rules\n *\n * @example\n * ```typescript\n * // packages/auth/src/adapters/nextjs/interceptors/index.ts\n * import { registerInterceptors } from '@spfn/core/nextjs';\n *\n * const authInterceptors = [\n * {\n * pathPattern: '/_auth/*',\n * request: async (ctx, next) => {\n * // Add JWT token\n * ctx.headers['Authorization'] = 'Bearer token';\n * await next();\n * }\n * }\n * ];\n *\n * // Auto-register on import\n * registerInterceptors('auth', authInterceptors);\n * ```\n */\nexport function registerInterceptors(\n packageName: string,\n interceptors: InterceptorRule[]\n): void\n{\n interceptorRegistry.register(packageName, interceptors);\n}","/**\n * Helper functions for proxy handler\n * Separates utility logic from main proxy handler for better maintainability\n */\nimport { NextRequest } from 'next/server';\nimport type { CookieOptions, SetCookie } from \"../client\";\nimport type { InterceptorRule, RequestInterceptorContext, ResponseInterceptorContext } from './interceptors/types';\nimport type { InterceptorRegistry } from './interceptors';\n\n// Re-export from shared\nexport { parseResponseBody } from '../shared';\n\n/**\n * Build request headers for proxying\n * Forwards important headers from source and adds default headers\n *\n * @param sourceHeaders - Source headers (can be Headers object or Record)\n * @param defaultHeaders - Default headers to add\n */\nexport function buildProxyHeaders(\n sourceHeaders: Headers | Record<string, string>,\n defaultHeaders: Record<string, string>\n): Headers\n{\n const headers = new Headers();\n\n // Forward important headers from source\n const headersToForward = [\n 'content-type',\n 'authorization',\n 'cookie',\n 'user-agent',\n 'accept',\n 'accept-language',\n ];\n\n for (const header of headersToForward)\n {\n const value = sourceHeaders instanceof Headers\n ? sourceHeaders.get(header)\n : sourceHeaders[header];\n\n if (value)\n {\n headers.set(header, value);\n }\n }\n\n // Add default headers\n for (const [key, value] of Object.entries(defaultHeaders))\n {\n headers.set(key, value);\n }\n\n return headers;\n}\n\n/**\n * Parse cookies from Cookie header string\n *\n * @param cookieHeader - Cookie header string (e.g., \"session=abc; theme=dark\")\n * @returns Map of cookie name-value pairs\n */\nexport function parseCookies(cookieHeader: string | null | undefined): Map<string, string>\n{\n const cookiesMap = new Map<string, string>();\n\n if (!cookieHeader)\n {\n return cookiesMap;\n }\n\n const cookiePairs = cookieHeader.split(';').map(c => c.trim());\n for (const pair of cookiePairs)\n {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0)\n {\n const value = valueParts.join('='); // Handle = in cookie value\n cookiesMap.set(name.trim(), value.trim());\n }\n }\n\n return cookiesMap;\n}\n\n/**\n * Parse cookies from NextRequest (Next.js specific helper)\n * Combines cookies from both NextRequest.cookies and Cookie header\n */\nexport function parseCookiesFromNextRequest(request: NextRequest): Map<string, string>\n{\n const cookiesMap = new Map<string, string>();\n\n // Add cookies from NextRequest (browser cookies)\n for (const cookie of request.cookies.getAll())\n {\n cookiesMap.set(cookie.name, cookie.value);\n }\n\n // Add cookies from Cookie header (server-side forwarded cookies)\n const cookieHeader = request.headers.get('cookie');\n if (cookieHeader)\n {\n const parsed = parseCookies(cookieHeader);\n for (const [name, value] of parsed.entries())\n {\n cookiesMap.set(name, value);\n }\n }\n\n return cookiesMap;\n}\n\n// Mapping of option names to Set-Cookie attribute formats\nconst optionMappings: Array<{\n key: keyof CookieOptions;\n format: (value: any) => string | null;\n}> = [\n { key: 'httpOnly', format: (v) => v ? 'HttpOnly' : null },\n { key: 'secure', format: (v) => v ? 'Secure' : null },\n { key: 'sameSite', format: (v) => v ? `SameSite=${v}` : null },\n { key: 'maxAge', format: (v) => v !== undefined ? `Max-Age=${v}` : null },\n { key: 'path', format: (v) => v ? `Path=${v}` : null },\n { key: 'domain', format: (v) => v ? `Domain=${v}` : null },\n];\n\n/**\n * Build Set-Cookie header string from cookie options\n */\nexport function buildSetCookieHeader(cookie: SetCookie): string\n{\n const parts = [`${cookie.name}=${cookie.value}`];\n const options = cookie.options || {};\n\n for (const { key, format } of optionMappings)\n {\n const value = options[key];\n if (value !== undefined && value !== false)\n {\n const formatted = format(value);\n if (formatted)\n {\n parts.push(formatted);\n }\n }\n }\n\n return parts.join('; ');\n}\n\n/**\n * Build error response JSON\n */\nexport function buildErrorResponse(\n errorType: string,\n message: string,\n debug: boolean,\n error?: Error\n): any\n{\n return {\n error: errorType,\n message,\n ...(debug && error?.stack && { stack: error.stack }),\n };\n}\n\nconst headersToForward = [\n 'content-type',\n 'cache-control',\n 'set-cookie',\n 'etag',\n 'last-modified',\n];\n\n/**\n * Forward response headers back to client\n */\nexport function forwardResponseHeaders(\n sourceHeaders: Headers,\n targetHeaders: Headers\n): void\n{\n for (const header of headersToForward)\n {\n const value = sourceHeaders.get(header);\n if (value)\n {\n targetHeaders.set(header, value);\n }\n }\n}\n\n/**\n * Collect all interceptors (auto-discovered + config)\n */\nexport function collectInterceptors(\n autoDiscoverInterceptors: boolean,\n disableAutoInterceptors: string[] | undefined,\n configInterceptors: InterceptorRule[] | undefined,\n registry: InterceptorRegistry\n): InterceptorRule[]\n{\n const allInterceptors: InterceptorRule[] = [];\n\n // Auto-discover from registry\n if (autoDiscoverInterceptors)\n {\n const registeredInterceptors = registry.getAll(disableAutoInterceptors || []);\n allInterceptors.push(...registeredInterceptors);\n }\n\n // Add config interceptors\n if (configInterceptors)\n {\n allInterceptors.push(...configInterceptors);\n }\n\n return allInterceptors;\n}\n\n/**\n * Build RequestInterceptorContext\n */\nexport function buildRequestContext(\n path: string,\n method: string,\n headers: Headers,\n body: any,\n searchParams: URLSearchParams,\n cookiesMap: Map<string, string>,\n request: NextRequest\n): RequestInterceptorContext\n{\n return {\n path: `/${path}`,\n method,\n headers: Object.fromEntries(headers.entries()),\n body,\n query: Object.fromEntries(searchParams.entries()),\n cookies: cookiesMap,\n request,\n metadata: {},\n };\n}\n\n/**\n * Build ResponseInterceptorContext\n */\nexport function buildResponseContext(\n path: string,\n method: string,\n requestHeaders: Headers,\n requestBody: any,\n response: Response,\n responseBody: any,\n requestMetadata: Record<string, any>,\n cookies: Map<string, string>\n): ResponseInterceptorContext\n{\n return {\n path: `/${path}`,\n method,\n request: {\n headers: Object.fromEntries(requestHeaders.entries()),\n body: requestBody,\n },\n response: {\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n body: responseBody,\n },\n cookies,\n setCookies: [],\n metadata: requestMetadata,\n };\n}","/**\n * RPC-Style Proxy for define-route System\n *\n * Next.js API Route handler that resolves routeName to method/path\n * and forwards requests to SPFN backend.\n *\n * @example Using routeMap (recommended - no server code loaded)\n * ```typescript\n * // app/api/rpc/[routeName]/route.ts\n * import { routeMap } from '@/generated/route-map';\n * import { createRpcProxy } from '@spfn/core/nextjs/proxy';\n *\n * export const { GET, POST } = createRpcProxy({ routeMap });\n * ```\n *\n * @example Using router (legacy - loads full server code)\n * ```typescript\n * // app/api/rpc/[routeName]/route.ts\n * import { appRouter } from '@/server/router';\n * import { createRpcProxy } from '@spfn/core/nextjs/proxy';\n *\n * export const { GET, POST } = createRpcProxy({ router: appRouter });\n * ```\n */\nimport { NextRequest, NextResponse } from 'next/server';\n\nimport { env } from '@spfn/core/config';\nimport { logger } from '@spfn/core/logger';\nimport type { Router, RouteDef, HttpMethod } from '@spfn/core/route';\n\nimport { buildUrlWithParams, buildQueryString } from '../shared';\nimport { interceptorRegistry } from './interceptors';\nimport { executeRequestInterceptors, executeResponseInterceptors, filterMatchingInterceptors } from './interceptors';\nimport {\n buildProxyHeaders,\n parseCookiesFromNextRequest,\n buildSetCookieHeader,\n buildErrorResponse,\n forwardResponseHeaders,\n parseResponseBody,\n collectInterceptors,\n buildRequestContext,\n buildResponseContext,\n} from './helpers';\nimport type { TypedProxyConfig } from \"./types\";\n\nconst rpcLogger = logger.child('@spfn/core:rpc-proxy');\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Route info from generated route map\n */\nexport interface RouteMapEntry\n{\n method: HttpMethod;\n path: string;\n}\n\n/**\n * Generated route map type\n */\nexport type RouteMap = Record<string, RouteMapEntry>;\n\n/**\n * Base config for RPC proxy\n */\ninterface RpcProxyBaseConfig extends Omit<TypedProxyConfig, 'onRequest' | 'onResponse'> {}\n\n/**\n * Config using routeMap (recommended)\n *\n * Uses generated route map file - no server code loaded in Next.js process.\n */\nexport interface RpcProxyRouteMapConfig extends RpcProxyBaseConfig\n{\n /**\n * Generated route map containing routeName → {method, path} mappings\n *\n * @example\n * ```typescript\n * import { routeMap } from '@/generated/route-map';\n *\n * export const { GET, POST } = createRpcProxy({ routeMap });\n * ```\n */\n routeMap: RouteMap;\n router?: never;\n}\n\n/**\n * Config using router (legacy)\n *\n * @deprecated Use routeMap instead to avoid loading server code in Next.js process\n */\nexport interface RpcProxyRouterConfig<TRouter extends Router<any>> extends RpcProxyBaseConfig\n{\n /**\n * The router containing all route definitions\n *\n * @deprecated Use routeMap instead - router imports all server code\n *\n * @example\n * ```typescript\n * export const { GET, POST } = createRpcProxy({\n * router: appRouter,\n * });\n * ```\n */\n router: TRouter;\n routeMap?: never;\n}\n\n/**\n * Combined config type\n */\nexport type RpcProxyConfig<TRouter extends Router<any> = Router<any>> =\n | RpcProxyRouteMapConfig\n | RpcProxyRouterConfig<TRouter>;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Type guard to check if value is a RouteDef\n */\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'handler' in value &&\n 'method' in value &&\n 'path' in value;\n}\n\n/**\n * Type guard to check if value is a Router\n */\nfunction isRouter(value: unknown): value is Router<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'routes' in value &&\n '_routes' in value;\n}\n\n/**\n * Get route definition from router by dotted path\n *\n * @example\n * getRouteByPath(router, 'users.getUser') → RouteDef\n * getRouteByPath(router, 'getUser') → RouteDef\n */\nfunction getRouteByPath(router: Router<any>, routePath: string): RouteDef<any> | null\n{\n const parts = routePath.split('.');\n let current: any = router.routes;\n\n for (const part of parts)\n {\n if (!current || typeof current !== 'object')\n {\n return null;\n }\n\n const next = current[part];\n\n if (isRouter(next))\n {\n current = next.routes;\n }\n else if (isRouteDef(next))\n {\n return next;\n }\n else\n {\n current = next;\n }\n }\n\n if (isRouteDef(current))\n {\n return current;\n }\n\n return null;\n}\n\n// ============================================================================\n// RPC Proxy Handler\n// ============================================================================\n\n/**\n * Create RPC proxy handler for Next.js API Route\n *\n * Handles requests in the format:\n * - GET /api/rpc/{routeName}?input={...}\n * - POST /api/rpc/{routeName} with body\n *\n * Resolves routeName to actual HTTP method and path from the router or routeMap,\n * then forwards to SPFN backend.\n */\nexport function createRpcProxy<TRouter extends Router<any>>(config: RpcProxyConfig<TRouter>)\n{\n const {\n apiUrl = env.SPFN_API_URL || 'http://localhost:8790',\n debug = env.NODE_ENV === 'development',\n timeout = env.SERVER_TIMEOUT,\n headers: defaultHeaders = {},\n interceptors,\n autoDiscoverInterceptors = true,\n disableAutoInterceptors,\n } = config;\n\n // Determine if using routeMap or router\n const useRouteMap = 'routeMap' in config && config.routeMap !== undefined;\n const routeMap = useRouteMap ? config.routeMap : null;\n const router = !useRouteMap && 'router' in config ? config.router : null;\n\n // Get package routers (only when using router mode)\n const packageRouters = router?._packageRouters || [];\n\n /**\n * Resolve route info from routeMap or router\n */\n function resolveRoute(routeName: string): { method: string; path: string } | null\n {\n // Try routeMap first (recommended)\n if (routeMap)\n {\n const entry = routeMap[routeName];\n if (entry)\n {\n return { method: entry.method, path: entry.path };\n }\n return null;\n }\n\n // Fall back to router (legacy)\n if (router)\n {\n let routeDef = getRouteByPath(router, routeName);\n\n // If not found in main router, search in package routers\n if (!routeDef && packageRouters.length > 0)\n {\n for (const pkgRouter of packageRouters)\n {\n routeDef = getRouteByPath(pkgRouter, routeName);\n if (routeDef)\n {\n if (debug)\n {\n rpcLogger.debug(`Route \"${routeName}\" found in package router`);\n }\n break;\n }\n }\n }\n\n if (routeDef && routeDef.method && routeDef.path)\n {\n return { method: routeDef.method, path: routeDef.path };\n }\n }\n\n return null;\n }\n\n /**\n * Handle RPC request\n */\n async function handleRpc(\n request: NextRequest,\n context: { params: Promise<{ routeName?: string }> }\n ): Promise<NextResponse>\n {\n const startTime = Date.now();\n const params = await context.params;\n\n try\n {\n const routeName = params.routeName;\n\n if (!routeName)\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Missing routeName parameter', debug),\n { status: 400 }\n );\n }\n\n // Parse input from query string (GET) or body (POST)\n let input: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n body?: Record<string, any>;\n formData?: Record<string, any>;\n headers?: Record<string, any>;\n cookies?: Record<string, any>;\n } = {};\n let rawFormData: FormData | null = null;\n\n if (request.method === 'GET')\n {\n const inputParam = request.nextUrl.searchParams.get('input');\n if (inputParam)\n {\n try\n {\n input = JSON.parse(decodeURIComponent(inputParam));\n }\n catch\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid input parameter', debug),\n { status: 400 }\n );\n }\n }\n }\n else\n {\n // POST - check Content-Type for formData vs JSON\n const contentType = request.headers.get('content-type') || '';\n\n if (contentType.includes('multipart/form-data'))\n {\n // Parse multipart/form-data\n try\n {\n rawFormData = await request.formData();\n\n // Extract __metadata if present (contains params, query, etc.)\n const metadataStr = rawFormData.get('__metadata');\n if (metadataStr && typeof metadataStr === 'string')\n {\n const metadata = JSON.parse(metadataStr);\n input.params = metadata.params;\n input.query = metadata.query;\n input.headers = metadata.headers;\n input.cookies = metadata.cookies;\n }\n\n // Collect formData fields (excluding __metadata)\n input.formData = {};\n rawFormData.forEach((value, key) =>\n {\n if (key === '__metadata') return;\n\n const existing = input.formData![key];\n if (existing !== undefined)\n {\n // Multiple values with same key\n if (Array.isArray(existing))\n {\n existing.push(value);\n }\n else\n {\n input.formData![key] = [existing, value];\n }\n }\n else\n {\n input.formData![key] = value;\n }\n });\n }\n catch (error)\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid form data', debug),\n { status: 400 }\n );\n }\n }\n else\n {\n // Parse JSON body\n try\n {\n input = await request.json();\n }\n catch\n {\n return NextResponse.json(\n buildErrorResponse('Bad Request', 'Invalid JSON body', debug),\n { status: 400 }\n );\n }\n }\n }\n\n // Resolve route info from routeMap or router\n const routeInfo = resolveRoute(routeName);\n\n if (!routeInfo)\n {\n rpcLogger.warn(`Route not found: ${routeName}`);\n return NextResponse.json(\n buildErrorResponse('Not Found', `Route \"${routeName}\" not found`, debug),\n { status: 404 }\n );\n }\n\n const { method: targetMethod, path: targetPath } = routeInfo;\n\n // Build target URL with params and query\n const inputParams = input.params || {};\n const inputQuery = input.query || {};\n const inputBody = input.body;\n const inputFormData = input.formData;\n const hasFormData = rawFormData !== null && inputFormData && Object.keys(inputFormData).length > 0;\n\n const resolvedPath = buildUrlWithParams(targetPath, inputParams);\n const queryString = buildQueryString(inputQuery);\n const targetUrl = `${apiUrl}${resolvedPath}${queryString}`;\n\n if (debug)\n {\n rpcLogger.debug('→ RPC request', {\n routeName,\n targetMethod,\n targetPath: resolvedPath,\n targetUrl,\n hasBody: !!inputBody,\n hasFormData,\n });\n }\n\n // Build headers\n const headers = buildProxyHeaders(request.headers, defaultHeaders);\n\n // Remove Content-Type for formData (let fetch set it with boundary)\n if (hasFormData)\n {\n headers.delete('content-type');\n }\n\n // Build fetch options\n const fetchOptions: RequestInit = {\n method: targetMethod,\n headers,\n };\n\n // Add body for POST/PUT/PATCH\n if (['POST', 'PUT', 'PATCH'].includes(targetMethod))\n {\n if (hasFormData && rawFormData)\n {\n // Forward formData to backend (rebuild without __metadata)\n const forwardFormData = new FormData();\n rawFormData.forEach((value, key) =>\n {\n if (key !== '__metadata')\n {\n forwardFormData.append(key, value);\n }\n });\n fetchOptions.body = forwardFormData;\n }\n else if (inputBody)\n {\n fetchOptions.body = JSON.stringify(inputBody);\n }\n }\n\n // ============================================================\n // Advanced Interceptors - BEFORE FETCH\n // ============================================================\n\n // Collect and filter interceptors\n const allInterceptors = collectInterceptors(autoDiscoverInterceptors, disableAutoInterceptors, interceptors, interceptorRegistry);\n const matchingInterceptors = filterMatchingInterceptors(allInterceptors, resolvedPath, targetMethod);\n\n if (debug && matchingInterceptors.length > 0)\n {\n rpcLogger.debug(`🎯 Found ${matchingInterceptors.length} matching interceptors for ${targetMethod} ${resolvedPath}`);\n }\n\n // Create RequestInterceptorContext\n const cookiesMap = parseCookiesFromNextRequest(request);\n const requestCtx = buildRequestContext(\n resolvedPath.slice(1), // Remove leading slash\n targetMethod,\n headers,\n inputBody,\n new URLSearchParams(queryString.slice(1)), // Remove leading ?\n cookiesMap,\n request\n );\n\n // Execute request interceptors\n const requestInterceptorsToRun = matchingInterceptors.map(r => r.request).filter((i): i is NonNullable<typeof i> => !!i);\n if (requestInterceptorsToRun.length > 0)\n {\n await executeRequestInterceptors(requestCtx, requestInterceptorsToRun);\n\n // Apply modified headers\n for (const [key, value] of Object.entries(requestCtx.headers))\n {\n headers.set(key, value);\n }\n\n // Apply modified body\n if (requestCtx.body)\n {\n fetchOptions.body = JSON.stringify(requestCtx.body);\n }\n }\n\n // Execute fetch with timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try\n {\n const response = await fetch(targetUrl, {\n ...fetchOptions,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n let body = await parseResponseBody(response);\n\n // ============================================================\n // Advanced Interceptors - AFTER FETCH\n // ============================================================\n\n // Create ResponseInterceptorContext\n const responseCtx = buildResponseContext(\n resolvedPath.slice(1),\n targetMethod,\n headers,\n inputBody,\n response,\n body,\n requestCtx.metadata,\n requestCtx.cookies\n );\n\n // Execute response interceptors\n const responseInterceptorsToRun = matchingInterceptors.map(r => r.response).filter((i): i is NonNullable<typeof i> => !!i);\n if (responseInterceptorsToRun.length > 0)\n {\n await executeResponseInterceptors(responseCtx, responseInterceptorsToRun);\n body = responseCtx.response.body;\n }\n\n const duration = Date.now() - startTime;\n\n if (debug)\n {\n rpcLogger.debug('← RPC response', {\n routeName,\n status: responseCtx.response.status,\n duration: `${duration}ms`,\n });\n }\n\n // Build Next.js response\n // 204 No Content should use NextResponse directly, not NextResponse.json()\n const nextResponse = responseCtx.response.status === 204\n ? new NextResponse(null, {\n status: 204,\n statusText: responseCtx.response.statusText,\n })\n : NextResponse.json(body, {\n status: responseCtx.response.status,\n statusText: responseCtx.response.statusText,\n });\n\n // Forward response headers\n forwardResponseHeaders(response.headers, nextResponse.headers);\n\n // Apply setCookies from interceptors\n for (const cookie of responseCtx.setCookies)\n {\n const setCookieHeader = buildSetCookieHeader(cookie);\n nextResponse.headers.append('Set-Cookie', setCookieHeader);\n\n if (debug)\n {\n rpcLogger.debug('🍪 Set-Cookie header added', {\n name: cookie.name,\n });\n }\n }\n\n return nextResponse;\n }\n catch (error)\n {\n clearTimeout(timeoutId);\n\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError')\n {\n rpcLogger.error('Request timeout', {\n routeName,\n targetUrl,\n timeout,\n });\n\n return NextResponse.json(\n buildErrorResponse('Gateway Timeout', `Request timed out after ${timeout}ms`, debug, error),\n { status: 504 }\n );\n }\n\n // Handle other fetch errors\n const fetchErr = error as Error;\n rpcLogger.error('Fetch error', {\n routeName,\n targetUrl,\n error: fetchErr.message,\n });\n\n return NextResponse.json(\n buildErrorResponse('Bad Gateway', fetchErr.message || 'Failed to connect to backend', debug, fetchErr),\n { status: 502 }\n );\n }\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n const err = error as Error;\n\n rpcLogger.error('RPC proxy error', {\n error: err.message,\n stack: err.stack,\n duration: `${duration}ms`,\n });\n\n return NextResponse.json(\n buildErrorResponse('Internal Server Error', err.message || 'Unknown error', debug, err),\n { status: 500 }\n );\n }\n }\n\n // Return route handlers\n return {\n GET: (req: NextRequest, context: { params: Promise<{ routeName?: string }> }) =>\n handleRpc(req, context),\n POST: (req: NextRequest, context: { params: Promise<{ routeName?: string }> }) =>\n handleRpc(req, context),\n };\n}"]}
@@ -159,7 +159,7 @@ interface ApiConfig {
159
159
  /**
160
160
  * Request timeout in milliseconds
161
161
  *
162
- * @default 30000
162
+ * @default env.SERVER_TIMEOUT (120000)
163
163
  */
164
164
  timeout?: number;
165
165
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spfn/core",
3
- "version": "0.2.0-beta.14",
3
+ "version": "0.2.0-beta.15",
4
4
  "description": "SPFN Framework Core - File-based routing, transactions, repository pattern",
5
5
  "type": "module",
6
6
  "exports": {