@fgrzl/fetch 1.2.0 β†’ 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -24,6 +24,8 @@ __export(index_exports, {
24
24
  FetchError: () => FetchError,
25
25
  HttpError: () => HttpError,
26
26
  NetworkError: () => NetworkError,
27
+ appendQueryParams: () => appendQueryParams,
28
+ buildQueryParams: () => buildQueryParams,
27
29
  createAuthenticationMiddleware: () => createAuthenticationMiddleware,
28
30
  createAuthorizationMiddleware: () => createAuthorizationMiddleware,
29
31
  createCacheMiddleware: () => createCacheMiddleware,
@@ -1126,6 +1128,40 @@ var NetworkError = class extends FetchError {
1126
1128
  }
1127
1129
  };
1128
1130
 
1131
+ // src/client/query.ts
1132
+ function buildQueryParams(query) {
1133
+ const params = new URLSearchParams();
1134
+ for (const [key, value] of Object.entries(query)) {
1135
+ if (value !== void 0) {
1136
+ if (Array.isArray(value)) {
1137
+ value.forEach((item) => {
1138
+ if (item !== void 0) {
1139
+ params.append(key, String(item));
1140
+ }
1141
+ });
1142
+ } else {
1143
+ params.set(key, String(value));
1144
+ }
1145
+ }
1146
+ }
1147
+ return params.toString();
1148
+ }
1149
+ function appendQueryParams(baseUrl, query) {
1150
+ const queryString = buildQueryParams(query);
1151
+ if (!queryString) {
1152
+ return baseUrl;
1153
+ }
1154
+ const fragmentIndex = baseUrl.indexOf("#");
1155
+ if (fragmentIndex !== -1) {
1156
+ const urlPart = baseUrl.substring(0, fragmentIndex);
1157
+ const fragmentPart = baseUrl.substring(fragmentIndex);
1158
+ const separator2 = urlPart.includes("?") ? "&" : "?";
1159
+ return `${urlPart}${separator2}${queryString}${fragmentPart}`;
1160
+ }
1161
+ const separator = baseUrl.includes("?") ? "&" : "?";
1162
+ return `${baseUrl}${separator}${queryString}`;
1163
+ }
1164
+
1129
1165
  // src/index.ts
1130
1166
  var api = useProductionStack(
1131
1167
  new FetchClient({
@@ -1161,6 +1197,8 @@ var index_default = api;
1161
1197
  FetchError,
1162
1198
  HttpError,
1163
1199
  NetworkError,
1200
+ appendQueryParams,
1201
+ buildQueryParams,
1164
1202
  createAuthenticationMiddleware,
1165
1203
  createAuthorizationMiddleware,
1166
1204
  createCacheMiddleware,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/client/fetch-client.ts","../../src/middleware/authentication/authentication.ts","../../src/middleware/authentication/index.ts","../../src/middleware/authorization/authorization.ts","../../src/middleware/authorization/index.ts","../../src/middleware/cache/cache.ts","../../src/middleware/cache/index.ts","../../src/middleware/csrf/csrf.ts","../../src/middleware/csrf/index.ts","../../src/middleware/logging/logging.ts","../../src/middleware/logging/index.ts","../../src/middleware/rate-limit/rate-limit.ts","../../src/middleware/rate-limit/index.ts","../../src/middleware/retry/retry.ts","../../src/middleware/retry/index.ts","../../src/middleware/index.ts","../../src/errors/index.ts"],"sourcesContent":["/**\n * @fileoverview Main library entry point with \"pit of success\" architecture.\n *\n * This module exports everything users need in order of discoverability:\n * 1. Pre-configured client with smart defaults (80% of users start here)\n * 2. FetchClient for custom configurations\n * 3. Individual middleware functions for specific needs\n * 4. Pre-built middleware stacks for common scenarios\n * 5. Types for TypeScript users\n */\n\nimport { FetchClient } from './client/fetch-client';\nimport { useProductionStack } from './middleware';\n\n/**\n * 🎯 PIT OF SUCCESS: Pre-configured fetch client (Level 1 - 80% of users)\n *\n * This client is ready to use out of the box with production-ready middleware:\n * - Authentication support (configure your token provider)\n * - Automatic retries with exponential backoff\n * - Response caching for GET requests\n * - Request/response logging\n * - Rate limiting protection\n * - Same-origin credentials for session-based auth (cookies)\n *\n * @example Just import and use:\n * ```typescript\n * import api from '@fgrzl/fetch';\n *\n * // Works immediately - no setup required!\n * const users = await api.get('/api/users');\n * const newUser = await api.post('/api/users', { name: 'John' });\n *\n * // With query parameters\n * const activeUsers = await api.get('/api/users', { status: 'active', limit: 10 });\n * ```\n *\n * @example Configure authentication:\n * ```typescript\n * import api from '@fgrzl/fetch';\n * import { useAuthentication } from '@fgrzl/fetch/middleware';\n *\n * const authClient = useAuthentication(api, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * });\n * ```\n *\n * @example For token-only auth (no cookies):\n * ```typescript\n * import { FetchClient, useAuthentication } from '@fgrzl/fetch';\n *\n * const tokenClient = useAuthentication(new FetchClient({\n * credentials: 'omit' // Don't send cookies\n * }), {\n * tokenProvider: () => getJWTToken()\n * });\n * ```\n */\nconst api = useProductionStack(\n new FetchClient({\n // Smart default: include cookies for session-based auth\n // Can be overridden by creating a custom FetchClient\n credentials: 'same-origin',\n }),\n {\n // Smart defaults - users can override as needed\n retry: {\n maxRetries: 2,\n delay: 1000,\n },\n cache: {\n ttl: 5 * 60 * 1000, // 5 minutes\n methods: ['GET'],\n },\n logging: {\n level: 'info',\n },\n rateLimit: {\n maxRequests: 100,\n windowMs: 60 * 1000, // 100 requests per minute\n },\n },\n);\n\n// 🎯 LEVEL 1: Export the production-ready client as default\nexport default api;\n\n// 🎯 LEVEL 2: FetchClient for custom configurations\nexport { FetchClient } from './client/fetch-client';\nexport { FetchError, HttpError, NetworkError } from './errors';\n\n// 🎯 LEVEL 3: Individual middleware functions (import from our comprehensive middleware index)\nexport {\n // Authentication\n useAuthentication,\n createAuthenticationMiddleware,\n // Authorization\n useAuthorization,\n createAuthorizationMiddleware,\n // Cache\n useCache,\n createCacheMiddleware,\n // CSRF\n useCSRF,\n // Logging\n useLogging,\n createLoggingMiddleware,\n // Rate Limiting\n useRateLimit,\n createRateLimitMiddleware,\n // Retry\n useRetry,\n createRetryMiddleware,\n} from './middleware';\n\n// 🎯 LEVEL 4: Pre-built middleware stacks for common scenarios\nexport {\n useProductionStack,\n useDevelopmentStack,\n useBasicStack,\n} from './middleware';\n\n// 🎯 LEVEL 5: Types for TypeScript users\nexport type { FetchMiddleware as InterceptMiddleware } from './client/fetch-client';\nexport type { FetchResponse, FetchClientOptions } from './client/types';\n\n// Middleware types (re-exported from middleware index)\nexport type {\n // Authentication types\n AuthenticationOptions,\n AuthTokenProvider,\n // Authorization types\n AuthorizationOptions,\n UnauthorizedHandler,\n // Cache types\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n // Logging types\n LoggingOptions,\n Logger,\n LogLevel,\n // Rate limiting types\n RateLimitOptions,\n RateLimitAlgorithm,\n // Retry types\n RetryOptions,\n} from './middleware';\n","/**\n * @fileoverview Enhanced fetch client with intercept middleware architecture.\n */\n\nimport type { FetchResponse, FetchClientOptions } from './types';\n\n/**\n * Intercept middleware type that allows full control over request/response cycle.\n * Middleware can modify requests, handle responses, implement retries, etc.\n */\nexport type FetchMiddleware = (\n request: RequestInit & { url?: string },\n next: (\n modifiedRequest?: RequestInit & { url?: string },\n ) => Promise<FetchResponse<unknown>>,\n) => Promise<FetchResponse<unknown>>;\n\n/**\n * Enhanced HTTP client with intercept middleware architecture.\n *\n * Features:\n * - 🎯 Smart defaults (JSON content-type, same-origin credentials)\n * - πŸ”§ Powerful middleware system for cross-cutting concerns\n * - πŸ›‘οΈ Consistent error handling (never throws, always returns response)\n * - πŸ“¦ TypeScript-first with full type inference\n * - πŸš€ Modern async/await API\n *\n * @example Basic usage:\n * ```typescript\n * const client = new FetchClient();\n *\n * // GET request - just works\n * const users = await client.get<User[]>('/api/users');\n * if (users.ok) {\n * console.log(users.data); // Type is User[]\n * }\n *\n * // POST request - JSON by default\n * const result = await client.post('/api/users', { name: 'John' });\n * ```\n *\n * @example With middleware:\n * ```typescript\n * const client = new FetchClient();\n *\n * // Add auth middleware\n * client.use((request, next) => {\n * request.headers = { ...request.headers, Authorization: 'Bearer token' };\n * return next(request);\n * });\n *\n * // Now all requests include auth\n * const data = await client.get('/api/protected');\n * ```\n */\nexport class FetchClient {\n private middlewares: FetchMiddleware[] = [];\n private credentials: RequestCredentials;\n private baseUrl: string | undefined;\n\n constructor(config: FetchClientOptions = {}) {\n this.credentials = config.credentials ?? 'same-origin';\n this.baseUrl = config.baseUrl;\n }\n\n use(middleware: FetchMiddleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n /**\n * Set or update the base URL for this client instance.\n *\n * When a base URL is set, relative URLs will be resolved against it.\n * Absolute URLs will continue to work unchanged.\n *\n * @param baseUrl - The base URL to set, or undefined to clear it\n * @returns The client instance for method chaining\n *\n * @example Set base URL:\n * ```typescript\n * const client = new FetchClient();\n * client.setBaseUrl('https://api.example.com');\n *\n * // Now relative URLs work\n * await client.get('/users'); // β†’ GET https://api.example.com/users\n * ```\n *\n * @example Chain with middleware:\n * ```typescript\n * const client = useProductionStack(new FetchClient())\n * .setBaseUrl(process.env.API_BASE_URL);\n * ```\n */\n setBaseUrl(baseUrl?: string): this {\n this.baseUrl = baseUrl;\n return this;\n }\n\n async request<T = unknown>(\n url: string,\n init: RequestInit = {},\n ): Promise<FetchResponse<T>> {\n // Resolve URL against baseUrl if relative\n const resolvedUrl = this.resolveUrl(url);\n\n // Create the execution chain\n let index = 0;\n\n const execute = async (\n request?: RequestInit & { url?: string },\n ): Promise<FetchResponse<unknown>> => {\n // Use provided request or fall back to original\n const currentRequest = request || { ...init, url: resolvedUrl };\n const currentUrl = currentRequest.url || resolvedUrl;\n\n if (index >= this.middlewares.length) {\n // Core fetch - end of middleware chain\n const { url: _, ...requestInit } = currentRequest; // Remove url from request init\n return this.coreFetch(requestInit, currentUrl);\n }\n\n const middleware = this.middlewares[index++];\n if (!middleware) {\n const { url: _, ...requestInit } = currentRequest;\n return this.coreFetch(requestInit, currentUrl);\n }\n return middleware(currentRequest, execute);\n };\n\n const result = await execute();\n return result as FetchResponse<T>;\n }\n\n private async coreFetch(\n request: RequestInit,\n url: string,\n ): Promise<FetchResponse<unknown>> {\n try {\n const finalInit = {\n credentials: this.credentials,\n ...request,\n };\n\n // Convert Headers object to plain object for better compatibility\n if (finalInit.headers instanceof Headers) {\n const headersObj: Record<string, string> = {};\n finalInit.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n finalInit.headers = headersObj;\n }\n\n const response = await fetch(url, finalInit);\n const data = await this.parseResponse(response);\n\n return {\n data: response.ok ? data : null,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url,\n ok: response.ok,\n ...(response.ok\n ? {}\n : {\n error: {\n message: response.statusText,\n body: data,\n },\n }),\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return {\n data: null,\n status: 0,\n statusText: 'Network Error',\n headers: new Headers(),\n url,\n ok: false,\n error: {\n message: 'Failed to fetch',\n body: error,\n },\n };\n }\n throw error;\n }\n }\n\n private async parseResponse(res: Response): Promise<unknown> {\n const contentType = res.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n return res.json();\n }\n\n if (contentType.includes('text/')) {\n return res.text();\n }\n\n if (\n contentType.includes('application/octet-stream') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ) {\n return res.blob();\n }\n\n if (res.body) {\n const text = await res.text();\n return text || null;\n }\n\n return null;\n }\n\n // Helper method to build URL with query parameters\n private buildUrlWithParams(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): string {\n if (!params) {\n return url;\n }\n\n // Resolve the URL first (handles baseUrl if needed)\n const resolvedUrl = this.resolveUrl(url);\n\n // If the resolved URL is still relative (no base URL configured),\n // manually build query parameters\n if (\n !resolvedUrl.startsWith('http://') &&\n !resolvedUrl.startsWith('https://') &&\n !resolvedUrl.startsWith('//')\n ) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n return queryString ? `${resolvedUrl}?${queryString}` : resolvedUrl;\n }\n\n // For absolute URLs, use URL constructor\n const urlObj = new URL(resolvedUrl);\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n urlObj.searchParams.set(key, String(value));\n }\n });\n\n return urlObj.toString();\n }\n\n /**\n * Resolves a URL with the base URL if it's relative and base URL is configured\n * @param url - The URL to resolve\n * @returns The resolved URL\n * @private\n */\n private resolveUrl(url: string): string {\n // If URL is already absolute, return as-is\n if (\n url.startsWith('http://') ||\n url.startsWith('https://') ||\n url.startsWith('//')\n ) {\n return url;\n }\n\n // If no base URL is configured, return the relative URL as-is (backward compatibility)\n if (!this.baseUrl) {\n return url;\n }\n\n // Resolve relative URL with base URL\n try {\n const baseUrl = new URL(this.baseUrl);\n const resolvedUrl = new URL(url, baseUrl);\n return resolvedUrl.toString();\n } catch {\n throw new Error(\n `Invalid URL: Unable to resolve \"${url}\" with baseUrl \"${this.baseUrl}\"`,\n );\n }\n } // 🎯 PIT OF SUCCESS: Convenience methods with smart defaults\n\n /**\n * HEAD request with query parameter support.\n *\n * HEAD requests are used to retrieve metadata about a resource without downloading\n * the response body. Useful for checking if a resource exists, getting content length,\n * last modified date, etc.\n *\n * @template T - Expected response data type (will be null for HEAD requests)\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response (data will always be null)\n *\n * @example Check if resource exists:\n * ```typescript\n * const headResponse = await client.head('/api/large-file.zip');\n * if (headResponse.ok) {\n * const contentLength = headResponse.headers.get('content-length');\n * const lastModified = headResponse.headers.get('last-modified');\n * console.log(`File size: ${contentLength} bytes`);\n * }\n * ```\n *\n * @example Check with query parameters:\n * ```typescript\n * const exists = await client.head('/api/users', { id: 123 });\n * if (exists.status === 404) {\n * console.log('User not found');\n * }\n * ```\n */\n head<T = null>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'HEAD' });\n }\n\n /**\n * HEAD request that returns useful metadata about a resource.\n *\n * This is a convenience method that extracts common metadata from HEAD responses\n * for easier consumption.\n *\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to response with extracted metadata\n *\n * @example Get resource metadata:\n * ```typescript\n * const metadata = await client.headMetadata('/api/large-file.zip');\n * if (metadata.ok) {\n * console.log('File exists:', metadata.exists);\n * console.log('Content type:', metadata.contentType);\n * console.log('Size:', metadata.contentLength, 'bytes');\n * console.log('Last modified:', metadata.lastModified);\n * }\n * ```\n */\n async headMetadata(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<\n FetchResponse<null> & {\n exists: boolean;\n contentType: string | undefined;\n contentLength: number | undefined;\n lastModified: Date | undefined;\n etag: string | undefined;\n cacheControl: string | undefined;\n }\n > {\n const response = await this.head(url, params);\n\n const contentLengthHeader = response.headers.get('content-length');\n const lastModifiedHeader = response.headers.get('last-modified');\n\n return {\n ...response,\n exists: response.ok,\n contentType: response.headers.get('content-type') || undefined,\n contentLength: contentLengthHeader\n ? parseInt(contentLengthHeader, 10)\n : undefined,\n lastModified: lastModifiedHeader\n ? new Date(lastModifiedHeader)\n : undefined,\n etag: response.headers.get('etag') || undefined,\n cacheControl: response.headers.get('cache-control') || undefined,\n };\n }\n\n /**\n * GET request with query parameter support.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const users = await client.get<User[]>('/api/users');\n * const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });\n * if (users.ok) console.log(users.data);\n * ```\n */\n get<T>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'GET' });\n }\n\n /**\n * POST request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const result = await client.post<User>('/api/users', { name: 'John' });\n * ```\n */\n post<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'POST',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * PUT request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n */\n put<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'PUT',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * PATCH request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n */\n patch<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'PATCH',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * DELETE request with query parameter support.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const result = await client.del('/api/users/123');\n * const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });\n * if (result.ok) console.log('Deleted successfully');\n * ```\n */\n del<T>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'DELETE' });\n }\n}\n","/**\n * @fileoverview Authentication middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { AuthenticationOptions } from './types';\n\n/**\n * Checks if a URL should skip authentication based on configured patterns.\n */\nfunction shouldSkipAuth(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Checks if a URL should include authentication based on configured patterns.\n */\nfunction shouldIncludeAuth(\n url: string,\n includePatterns?: (RegExp | string)[],\n): boolean {\n if (!includePatterns || includePatterns.length === 0) {\n return true; // Include by default if no patterns specified\n }\n\n return includePatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates authentication middleware with smart defaults.\n * Automatically adds Bearer tokens to requests.\n *\n * @param options - Authentication configuration options\n * @returns Authentication middleware for use with FetchClient\n *\n * @example Basic usage:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('token') || ''\n * });\n * ```\n *\n * @example Async token provider:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: async () => {\n * const token = await getAuthToken();\n * return token || '';\n * }\n * });\n * ```\n */\nexport function createAuthenticationMiddleware(\n options: AuthenticationOptions,\n): FetchMiddleware {\n const {\n tokenProvider,\n headerName = 'Authorization',\n tokenType = 'Bearer',\n skipPatterns = [],\n includePatterns,\n } = options;\n\n return async (request, next) => {\n const url = request.url || '';\n const parsedUrl = new URL(url);\n const pathname = parsedUrl.pathname;\n\n // Skip authentication if:\n // 1. URL matches a skip pattern\n // 2. URL doesn't match include patterns (if specified)\n if (\n shouldSkipAuth(pathname, skipPatterns) ||\n !shouldIncludeAuth(pathname, includePatterns)\n ) {\n return next(request);\n }\n\n try {\n // Get auth token (may be async)\n const token = await tokenProvider();\n\n // Skip if no token available\n if (!token) {\n return next(request);\n }\n\n // Add auth header to request\n const headers = new Headers(request.headers);\n headers.set(headerName, `${tokenType} ${token}`);\n\n // Create modified request with auth header\n const modifiedRequest = {\n ...request,\n headers,\n };\n\n return next(modifiedRequest);\n } catch {\n // If token provider fails, proceed without auth\n // This ensures network requests don't fail due to auth issues\n return next(request);\n }\n };\n}\n","/**\n * @fileoverview Authentication middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { AuthenticationOptions } from './types';\nimport { createAuthenticationMiddleware } from './authentication';\n\n// Re-export types for convenience\nexport type { AuthenticationOptions, AuthTokenProvider } from './types';\nexport { createAuthenticationMiddleware } from './authentication';\n\n/**\n * \"Pit of success\" API for adding authentication to a FetchClient.\n * Automatically adds Bearer tokens to requests.\n *\n * @param client - The FetchClient to add authentication to\n * @param options - Authentication configuration\n * @returns A new FetchClient with authentication middleware\n *\n * @example Basic token from localStorage:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * });\n * ```\n *\n * @example Async token with refresh:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: async () => {\n * let token = localStorage.getItem('auth-token');\n * if (!token || isExpired(token)) {\n * token = await refreshToken();\n * }\n * return token || '';\n * }\n * });\n * ```\n */\nexport function useAuthentication(\n client: FetchClient,\n options: AuthenticationOptions,\n): FetchClient {\n return client.use(createAuthenticationMiddleware(options));\n}\n","/**\n * @fileoverview Authorization middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type {\n AuthorizationOptions,\n RedirectAuthorizationConfig,\n UnauthorizedHandler,\n} from './types';\n\n/**\n * Creates a smart default redirect handler for unauthorized responses.\n * Redirects to login with a return URL parameter.\n */\nfunction createRedirectHandler(config: RedirectAuthorizationConfig = {}) {\n const {\n redirectPath = '/login',\n returnUrlParam = 'return_url',\n includeReturnUrl = true,\n } = config;\n\n return () => {\n let redirectUrl = redirectPath;\n\n if (includeReturnUrl && typeof window !== 'undefined') {\n const currentUrl = encodeURIComponent(window.location.href);\n const separator = redirectPath.includes('?') ? '&' : '?';\n redirectUrl = `${redirectPath}${separator}${returnUrlParam}=${currentUrl}`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl;\n }\n };\n}\n\n/**\n * Selects the appropriate unauthorized handler based on provided options.\n * Priority: explicit onUnauthorized > redirectConfig > smart default\n */\nfunction selectUnauthorizedHandler(\n providedHandler?: UnauthorizedHandler,\n redirectConfig?: RedirectAuthorizationConfig,\n): UnauthorizedHandler {\n if (providedHandler) {\n return providedHandler;\n }\n\n return createRedirectHandler(redirectConfig);\n}\n\n/**\n * Checks if a URL should skip authorization handling based on configured patterns.\n */\nfunction shouldSkipAuth(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n // Extract pathname from URL for pattern matching\n let pathname: string;\n try {\n pathname = new URL(url).pathname;\n } catch {\n pathname = url; // fallback if not a valid URL\n }\n\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return pathname.includes(pattern);\n }\n return pattern.test(pathname);\n });\n}\n\n/**\n * Creates authorization middleware with smart defaults.\n * Handles 401/403 responses by calling configured handlers.\n *\n * @param options - Authorization configuration options (optional)\n * @returns Authorization middleware for use with FetchClient\n *\n * @example Smart defaults (no configuration needed):\n * ```typescript\n * const authzClient = useAuthorization(client);\n * // Redirects to '/login?return_url=current-page' on 401\n * ```\n *\n * @example Custom redirect configuration:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * redirectConfig: {\n * redirectPath: '/signin',\n * returnUrlParam: 'redirect_to'\n * }\n * });\n * ```\n *\n * @example Manual handler (full control):\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onUnauthorized: () => window.location.href = '/login'\n * });\n * ```\n *\n * @example Handle both 401 and 403:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onForbidden: () => showAccessDeniedMessage(),\n * statusCodes: [401, 403]\n * });\n * ```\n */\nexport function createAuthorizationMiddleware(\n options: AuthorizationOptions = {},\n): FetchMiddleware {\n const {\n onUnauthorized: providedOnUnauthorized,\n redirectConfig,\n onForbidden,\n skipPatterns = [],\n statusCodes = [401],\n } = options;\n\n const onUnauthorized = selectUnauthorizedHandler(\n providedOnUnauthorized,\n redirectConfig,\n );\n\n return async (request, next) => {\n const url = request.url || '';\n\n // Skip authorization handling if URL matches skip patterns\n if (shouldSkipAuth(url, skipPatterns)) {\n return next(request);\n }\n\n // Execute the request\n const response = await next(request);\n\n // Check if response status requires handling\n if (statusCodes.includes(response.status)) {\n try {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized(response, request);\n } else if (response.status === 403 && onForbidden) {\n await onForbidden(response, request);\n } else if (onUnauthorized) {\n // For any other configured status codes, use the first available handler\n await onUnauthorized(response, request);\n }\n } catch (error) {\n // If handler fails, log but don't break the response chain\n // eslint-disable-next-line no-console\n console.warn('Authorization handler failed:', error);\n }\n }\n\n return response;\n };\n}\n","/**\n * @fileoverview Authorization middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { AuthorizationOptions } from './types';\nimport { createAuthorizationMiddleware } from './authorization';\n\n// Re-export types for convenience\nexport type {\n AuthorizationOptions,\n UnauthorizedHandler,\n RedirectAuthorizationConfig,\n} from './types';\nexport { createAuthorizationMiddleware } from './authorization';\n\n/**\n * \"Pit of success\" API for adding authorization handling to a FetchClient.\n * Automatically handles 401 Unauthorized responses.\n *\n * @param client - The FetchClient to add authorization handling to\n * @param options - Authorization configuration (optional)\n * @returns A new FetchClient with authorization middleware\n *\n * @example Smart defaults - no configuration needed:\n * ```typescript\n * const authzClient = useAuthorization(client);\n * // Redirects to '/login?return_url=current-page' on 401\n * ```\n *\n * @example Custom redirect path:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * redirectConfig: { redirectPath: '/signin', returnUrlParam: 'redirect_to' }\n * });\n * ```\n *\n * @example Manual handler (full control):\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onUnauthorized: () => {\n * localStorage.removeItem('auth-token');\n * window.location.href = '/login';\n * }\n * });\n * ```\n *\n * @example Handle multiple status codes:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onForbidden: () => showAccessDenied(),\n * statusCodes: [401, 403]\n * });\n * ```\n */\nexport function useAuthorization(\n client: FetchClient,\n options: AuthorizationOptions = {},\n): FetchClient {\n return client.use(createAuthorizationMiddleware(options));\n}\n","/**\n * @fileoverview Cache middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { FetchResponse } from '../../client/types';\nimport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './types';\n\n/**\n * Default in-memory cache storage implementation.\n */\nexport class MemoryStorage implements CacheStorage {\n private cache = new Map<string, CacheEntry>();\n\n async get(key: string): Promise<CacheEntry | null> {\n const entry = this.cache.get(key);\n if (!entry) {\n return null;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry;\n }\n\n async getWithExpiry(\n key: string,\n ): Promise<{ entry: CacheEntry | null; isExpired: boolean }> {\n const entry = this.cache.get(key);\n if (!entry) {\n return { entry: null, isExpired: false };\n }\n\n const isExpired = Date.now() > entry.expiresAt;\n // Don't delete expired entries when using getWithExpiry - let the caller decide\n return { entry, isExpired };\n }\n\n async set(key: string, entry: CacheEntry): Promise<void> {\n this.cache.set(key, entry);\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n}\n\n/**\n * Default cache key generator.\n */\nconst defaultKeyGenerator: CacheKeyGenerator = (request) => {\n const url = request.url || '';\n const method = request.method || 'GET';\n const headers = request.headers ? JSON.stringify(request.headers) : '';\n return `${method}:${url}:${headers}`;\n};\n\n/**\n * Checks if a URL should skip caching based on configured patterns.\n */\nfunction shouldSkipCache(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates cache middleware with smart defaults.\n * Caches GET responses for faster subsequent requests.\n *\n * @param options - Cache configuration options\n * @returns Cache middleware for use with FetchClient\n *\n * @example Basic caching:\n * ```typescript\n * const cachedClient = useCache(client);\n * // GET requests will be cached for 5 minutes\n * ```\n *\n * @example Custom TTL:\n * ```typescript\n * const cachedClient = useCache(client, {\n * ttl: 10 * 60 * 1000 // 10 minutes\n * });\n * ```\n */\nexport function createCacheMiddleware(\n options: CacheOptions = {},\n): FetchMiddleware {\n const {\n ttl = 5 * 60 * 1000, // 5 minutes\n methods = ['GET'],\n storage = new MemoryStorage(),\n keyGenerator = defaultKeyGenerator,\n skipPatterns = [],\n staleWhileRevalidate = false,\n } = options;\n\n return async (request, next) => {\n const method = (request.method || 'GET').toUpperCase();\n const url = request.url || '';\n\n // Skip caching if:\n // 1. Method is not in cached methods list\n // 2. URL matches a skip pattern\n if (!methods.includes(method) || shouldSkipCache(url, skipPatterns)) {\n return next(request);\n }\n\n const cacheKey = keyGenerator(request);\n\n try {\n // Try to get cached response with expiry info\n const { entry: cached, isExpired } = storage.getWithExpiry\n ? await storage.getWithExpiry(cacheKey)\n : await (async () => {\n const entry = await storage.get(cacheKey);\n return { entry, isExpired: false };\n })();\n\n if (cached && !isExpired) {\n // Return fresh cached response\n return {\n ...cached.response,\n headers: new Headers(cached.response.headers),\n data: cached.response.data,\n } as FetchResponse<unknown>;\n }\n\n // If stale-while-revalidate and we have cached data (even expired), return it immediately\n // and update in background\n if (cached && staleWhileRevalidate) {\n // Return cached data immediately (even if stale)\n const cachedResponse = {\n ...cached.response,\n headers: new Headers(cached.response.headers),\n data: cached.response.data,\n } as FetchResponse<unknown>;\n\n // Update cache in background if expired\n if (isExpired) {\n next(request)\n .then(async (freshResponse) => {\n const headersObj: Record<string, string> = {};\n freshResponse.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n\n const cacheEntry: CacheEntry = {\n response: {\n status: freshResponse.status,\n statusText: freshResponse.statusText,\n headers: headersObj,\n data: freshResponse.data,\n },\n timestamp: Date.now(),\n expiresAt: Date.now() + ttl,\n };\n await storage.set(cacheKey, cacheEntry);\n })\n .catch(() => {\n // Ignore background update errors\n });\n }\n\n return cachedResponse;\n }\n\n // No cached data or not using stale-while-revalidate\n const response = await next(request);\n\n // Cache successful responses\n if (response.ok) {\n try {\n const headersObj: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n\n const cacheEntry: CacheEntry = {\n response: {\n status: response.status,\n statusText: response.statusText,\n headers: headersObj,\n data: response.data,\n },\n timestamp: Date.now(),\n expiresAt: Date.now() + ttl,\n };\n\n await storage.set(cacheKey, cacheEntry);\n } catch {\n // Ignore cache storage errors, but still return the response\n }\n }\n\n return response;\n } catch (error) {\n // Only catch cache retrieval errors, let network errors through\n if (error && typeof error === 'object' && 'message' in error) {\n const errorMessage = (error as { message: string }).message;\n if (\n errorMessage.includes('Network') ||\n errorMessage.includes('fetch')\n ) {\n throw error; // Re-throw network errors\n }\n }\n\n // If cache retrieval fails, just proceed with the request\n return next(request);\n }\n };\n}\n","/**\n * @fileoverview Cache middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { CacheOptions } from './types';\nimport { createCacheMiddleware } from './cache';\n\n// Re-export types for convenience\nexport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './types';\nexport { createCacheMiddleware, MemoryStorage } from './cache';\n\n/**\n * \"Pit of success\" API for adding response caching to a FetchClient.\n * Caches GET responses for faster subsequent requests.\n *\n * @param client - The FetchClient to add caching to\n * @param options - Cache configuration options\n * @returns A new FetchClient with cache middleware\n *\n * @example Basic caching (5 minute TTL):\n * ```typescript\n * const cachedClient = useCache(client);\n *\n * // First call hits the network\n * await cachedClient.get('/api/data');\n *\n * // Second call returns cached data\n * await cachedClient.get('/api/data');\n * ```\n *\n * @example Custom TTL and methods:\n * ```typescript\n * const cachedClient = useCache(client, {\n * ttl: 10 * 60 * 1000, // 10 minutes\n * methods: ['GET', 'HEAD']\n * });\n * ```\n *\n * @example Stale-while-revalidate:\n * ```typescript\n * const cachedClient = useCache(client, {\n * staleWhileRevalidate: true\n * });\n * // Returns stale data immediately, updates cache in background\n * ```\n */\nexport function useCache(\n client: FetchClient,\n options: CacheOptions = {},\n): FetchClient {\n return client.use(createCacheMiddleware(options));\n}\n","/**\n * @fileoverview CSRF protection middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { CSRFOptions } from './types';\n\n/**\n * Default CSRF token provider that extracts token from XSRF-TOKEN cookie.\n * This follows the standard convention used by Rails, Laravel, and many other frameworks.\n */\nfunction getTokenFromCookie(cookieName: string = 'XSRF-TOKEN'): string {\n if (typeof document === 'undefined') {\n return ''; // Server-side, no cookies available\n }\n\n const name = `${cookieName}=`;\n const decodedCookie = decodeURIComponent(document.cookie);\n const cookies = decodedCookie.split(';');\n\n for (const cookie of cookies) {\n const c = cookie.trim();\n if (c.indexOf(name) === 0) {\n return c.substring(name.length);\n }\n }\n\n return '';\n}\n\n/**\n * Checks if a URL should skip CSRF protection based on configured patterns.\n */\nfunction shouldSkipCSRF(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates CSRF protection middleware with smart defaults.\n * Automatically adds CSRF tokens to state-changing requests.\n *\n * @param options - CSRF configuration options (all optional for \"pit of success\")\n * @returns CSRF middleware for use with FetchClient\n *\n * @example Basic usage (uses cookies automatically):\n * ```typescript\n * const client = new FetchClient();\n * const csrfClient = useCSRF(client);\n * ```\n *\n * @example Custom token provider:\n * ```typescript\n * const csrfClient = useCSRF(client, {\n * tokenProvider: () => localStorage.getItem('csrf-token') || ''\n * });\n * ```\n *\n * @example Skip external APIs:\n * ```typescript\n * const csrfClient = useCSRF(client, {\n * skipPatterns: [/^https:\\/\\/api\\.external\\.com\\//, '/webhook/']\n * });\n * ```\n */\nexport function createCSRFMiddleware(\n options: CSRFOptions = {},\n): FetchMiddleware {\n // Smart defaults for \"pit of success\"\n const {\n headerName = 'X-XSRF-TOKEN',\n cookieName = 'XSRF-TOKEN',\n protectedMethods = ['POST', 'PUT', 'PATCH', 'DELETE'],\n skipPatterns = [],\n tokenProvider = () => getTokenFromCookie(cookieName),\n } = options;\n\n return async (request, next) => {\n const method = (request.method || 'GET').toUpperCase();\n const url = request.url || '';\n\n // Skip CSRF protection if:\n // 1. Method is not in protected methods list\n // 2. URL matches a skip pattern\n if (\n !protectedMethods.includes(method) ||\n shouldSkipCSRF(url, skipPatterns)\n ) {\n return next(request);\n }\n\n // Get CSRF token\n const token = tokenProvider();\n\n // Skip if no token available (let the server handle the error)\n if (!token) {\n return next(request);\n }\n\n // Add CSRF token to request headers\n const headers = new Headers(request.headers);\n headers.set(headerName, token);\n\n // Create modified request with CSRF header\n const modifiedRequest = {\n ...request,\n headers,\n };\n\n return next(modifiedRequest);\n };\n}\n","/**\n * @fileoverview CSRF protection middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { CSRFOptions } from './types';\nimport { createCSRFMiddleware } from './csrf';\n\n// Re-export types for convenience\nexport type { CSRFOptions, CSRFTokenProvider } from './types';\nexport { createCSRFMiddleware } from './csrf';\n\n/**\n * \"Pit of success\" API for adding CSRF protection to a FetchClient.\n * Uses smart defaults that work with most web frameworks out of the box.\n *\n * Default behavior:\n * - Reads CSRF token from XSRF-TOKEN cookie\n * - Adds X-XSRF-TOKEN header to POST, PUT, PATCH, DELETE requests\n * - Skips GET/HEAD requests (they don't need CSRF protection)\n *\n * @param client - The FetchClient to add CSRF protection to\n * @param options - Optional CSRF configuration\n * @returns A new FetchClient with CSRF protection\n *\n * @example Basic usage (automatic cookie-based CSRF):\n * ```typescript\n * const client = new FetchClient();\n * const protectedClient = useCSRF(client);\n *\n * // CSRF token automatically added to POST requests\n * await protectedClient.post('/api/users', { name: 'John' });\n * ```\n *\n * @example Custom token provider:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * tokenProvider: () => localStorage.getItem('csrf-token') || ''\n * });\n * ```\n *\n * @example Custom header and cookie names:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * headerName: 'X-CSRF-Token',\n * cookieName: 'csrf-token'\n * });\n * ```\n *\n * @example Skip patterns for external APIs:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * skipPatterns: [\n * /^https:\\/\\/api\\.external\\.com\\//, // Skip external API\n * '/webhook/', // Skip webhook endpoints\n * '/public-api/' // Skip public API endpoints\n * ]\n * });\n * ```\n */\nexport function useCSRF(\n client: FetchClient,\n options: CSRFOptions = {},\n): FetchClient {\n return client.use(createCSRFMiddleware(options));\n}\n","/**\n * @fileoverview Logging middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { LoggingOptions, Logger, LogEntry, LogLevel } from './types';\n\n/**\n * Default console logger implementation.\n */\nconst defaultLogger: Logger = {\n // eslint-disable-next-line no-console -- allow console.debug in logger implementation\n debug: (message: string, data?: unknown) => console.debug(message, data),\n // eslint-disable-next-line no-console -- allow console.info in logger implementation\n info: (message: string, data?: unknown) => console.info(message, data),\n // eslint-disable-next-line no-console -- allow console.warn in logger implementation\n warn: (message: string, data?: unknown) => console.warn(message, data),\n // eslint-disable-next-line no-console -- allow console.error in logger implementation\n error: (message: string, data?: unknown) => console.error(message, data),\n};\n\n/**\n * Log level priority for filtering.\n */\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Default log formatter.\n */\nconst defaultFormatter = (entry: LogEntry): string => {\n const { method, url, status, duration } = entry;\n let message = `${method} ${url}`;\n\n if (status) {\n message += ` β†’ ${status}`;\n }\n\n if (duration) {\n message += ` (${duration}ms)`;\n }\n\n return message;\n};\n\n/**\n * Checks if a URL should skip logging based on configured patterns.\n */\nfunction shouldSkipLogging(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates logging middleware with smart defaults.\n * Logs HTTP requests and responses for debugging and monitoring.\n *\n * @param options - Logging configuration options\n * @returns Logging middleware for use with FetchClient\n *\n * @example Basic logging:\n * ```typescript\n * const loggedClient = useLogging(client);\n * // Logs all requests to console\n * ```\n *\n * @example Custom logger:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * logger: winston.createLogger({...}),\n * level: 'debug',\n * includeRequestHeaders: true\n * });\n * ```\n */\nexport function createLoggingMiddleware(\n options: LoggingOptions = {},\n): FetchMiddleware {\n const {\n level = 'info',\n logger = defaultLogger,\n includeRequestHeaders = false,\n includeResponseHeaders = false,\n includeRequestBody = false,\n includeResponseBody = false,\n skipPatterns = [],\n formatter = defaultFormatter,\n } = options;\n\n const minLevel = LOG_LEVELS[level];\n\n return async (request, next) => {\n const url = request.url || '';\n const method = (request.method || 'GET').toUpperCase();\n\n // Skip logging if URL matches skip patterns\n if (shouldSkipLogging(url, skipPatterns)) {\n return next(request);\n }\n\n const startTime = Date.now();\n\n // Log request start (debug level)\n if (LOG_LEVELS.debug >= minLevel) {\n const requestHeaders = includeRequestHeaders\n ? getHeadersObject(\n request.headers as Headers | Record<string, string> | undefined,\n )\n : undefined;\n const requestBody = includeRequestBody ? request.body : undefined;\n\n const requestEntry: LogEntry = {\n level: 'debug',\n timestamp: startTime,\n method,\n url,\n ...(requestHeaders && { requestHeaders }),\n ...(requestBody && { requestBody }),\n };\n\n logger.debug(`β†’ ${formatter(requestEntry)}`, requestEntry);\n }\n\n try {\n const response = await next(request);\n const duration = Date.now() - startTime;\n\n // Determine log level based on response status\n const logLevel: LogLevel = response.status >= 400 ? 'error' : 'info';\n\n // Log response (info/error level)\n if (LOG_LEVELS[logLevel] >= minLevel) {\n const responseHeaders = includeResponseHeaders\n ? getHeadersObject(response.headers)\n : undefined;\n const responseBody = includeResponseBody ? response.data : undefined;\n\n const responseEntry: LogEntry = {\n level: logLevel,\n timestamp: Date.now(),\n method,\n url,\n status: response.status,\n duration,\n ...(responseHeaders ? { responseHeaders } : {}),\n ...(responseBody !== undefined ? { responseBody } : {}),\n };\n\n const logMessage = `← ${formatter(responseEntry)}`;\n\n if (logLevel === 'error') {\n logger.error(logMessage, responseEntry);\n } else {\n logger.info(logMessage, responseEntry);\n }\n }\n\n return response;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n // Log error\n if (LOG_LEVELS.error >= minLevel) {\n const errorEntry: LogEntry = {\n level: 'error',\n timestamp: Date.now(),\n method,\n url,\n duration,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n\n logger.error(`βœ— ${formatter(errorEntry)}`, errorEntry);\n }\n\n throw error;\n }\n };\n}\n\n/**\n * Convert Headers object to plain object.\n */\nfunction getHeadersObject(\n headers: Headers | Record<string, string> | undefined,\n): Record<string, string> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const obj: Record<string, string> = {};\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n obj[key] = value;\n });\n return obj;\n } else {\n // It's already a Record<string, string>\n return headers;\n }\n}\n","/**\n * @fileoverview Logging middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { LoggingOptions } from './types';\nimport { createLoggingMiddleware } from './logging';\n\n// Re-export types for convenience\nexport type { LoggingOptions, Logger, LogEntry, LogLevel } from './types';\nexport { createLoggingMiddleware } from './logging';\n\n/**\n * \"Pit of success\" API for adding logging to a FetchClient.\n * Logs HTTP requests and responses for debugging and monitoring.\n *\n * @param client - The FetchClient to add logging to\n * @param options - Logging configuration options\n * @returns A new FetchClient with logging middleware\n *\n * @example Basic logging to console:\n * ```typescript\n * const loggedClient = useLogging(client);\n *\n * // Logs: β†’ GET /api/users\n * // Logs: ← GET /api/users β†’ 200 (245ms)\n * await loggedClient.get('/api/users');\n * ```\n *\n * @example Custom log level and headers:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * level: 'debug',\n * includeRequestHeaders: true,\n * includeResponseHeaders: true\n * });\n * ```\n *\n * @example Skip health check endpoints:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * skipPatterns: ['/health', '/metrics', '/ping']\n * });\n * ```\n */\nexport function useLogging(\n client: FetchClient,\n options: LoggingOptions = {},\n): FetchClient {\n return client.use(createLoggingMiddleware(options));\n}\n","/**\n * @fileoverview Rate limiting middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { RateLimitOptions } from './types';\n\n/**\n * Simple token bucket implementation for rate limiting.\n */\nclass TokenBucket {\n private tokens: number;\n private lastRefill: number;\n\n constructor(\n private maxTokens: number,\n private refillRate: number, // tokens per millisecond\n private timeProvider: () => number = () => Date.now(),\n ) {\n this.tokens = maxTokens;\n this.lastRefill = this.timeProvider();\n }\n\n tryConsume(): { allowed: boolean; retryAfter?: number } {\n this.refill();\n\n if (this.tokens >= 1) {\n this.tokens--;\n return { allowed: true };\n }\n\n // Calculate when next token will be available\n const retryAfter = (1 - this.tokens) / this.refillRate;\n return { allowed: false, retryAfter: Math.ceil(retryAfter) };\n }\n\n private refill() {\n const now = this.timeProvider();\n const timePassed = now - this.lastRefill;\n const tokensToAdd = timePassed * this.refillRate;\n\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n this.lastRefill = now;\n }\n}\n\n/**\n * Creates rate limiting middleware - mainly for API quota management.\n * Note: Rate limiting is typically a server concern, but this can help with:\n * - Respecting API provider limits\n * - Preventing runaway requests in bulk operations\n * - Cost management for pay-per-request APIs\n */\nexport function createRateLimitMiddleware(\n options: RateLimitOptions = {},\n): FetchMiddleware {\n const {\n maxRequests = 60,\n windowMs = 60000,\n keyGenerator = () => 'default',\n skipPatterns = [],\n onRateLimitExceeded,\n } = options;\n\n const buckets = new Map<string, TokenBucket>();\n const refillRate = maxRequests / windowMs;\n\n return async (request, next) => {\n const url = request.url || '';\n\n // Skip rate limiting if URL matches skip patterns\n if (\n skipPatterns.some((pattern) =>\n typeof pattern === 'string' ? url.includes(pattern) : pattern.test(url),\n )\n ) {\n return next(request);\n }\n\n const key = keyGenerator(request);\n\n if (!buckets.has(key)) {\n buckets.set(key, new TokenBucket(maxRequests, refillRate));\n }\n\n const bucket = buckets.get(key)!;\n const result = bucket.tryConsume();\n\n if (!result.allowed) {\n if (onRateLimitExceeded) {\n const customResponse = await onRateLimitExceeded(\n result.retryAfter || 0,\n request,\n );\n // If the custom handler returns a response, use it\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return a 429 Too Many Requests response instead of throwing\n return {\n data: null,\n status: 429,\n statusText: 'Too Many Requests',\n headers: new Headers({\n 'Retry-After': Math.ceil((result.retryAfter || 0) / 1000).toString(),\n }),\n url: request.url || '',\n ok: false,\n error: {\n message: `Rate limit exceeded. Retry after ${result.retryAfter}ms`,\n body: { retryAfter: result.retryAfter },\n },\n };\n }\n\n return next(request);\n };\n}\n","/**\n * @fileoverview Rate limiting middleware - specialized use cases.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { RateLimitOptions } from './types';\nimport { createRateLimitMiddleware } from './rate-limit';\n\n// Re-export types for convenience\nexport type { RateLimitOptions, RateLimitAlgorithm } from './types';\nexport { createRateLimitMiddleware } from './rate-limit';\n\n/**\n * Rate limiting middleware - mainly for API quota management.\n * Note: This is primarily useful for specific scenarios like:\n * - Respecting third-party API limits\n * - Bulk operations that need throttling\n * - Pay-per-request API cost management\n */\nexport function useRateLimit(\n client: FetchClient,\n options: RateLimitOptions = {},\n): FetchClient {\n return client.use(createRateLimitMiddleware(options));\n}\n","/**\n * @fileoverview Retry middleware implementation with enhanced architecture.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { FetchResponse } from '../../client/types';\nimport type { RetryOptions } from './types';\n\n/**\n * Default retry condition - retry on network errors and 5xx server errors.\n */\nconst defaultShouldRetry = (response: {\n status: number;\n ok: boolean;\n}): boolean => {\n // Network errors (status 0) or server errors (5xx)\n return (\n response.status === 0 || (response.status >= 500 && response.status < 600)\n );\n};\n\n/**\n * Calculate delay for retry attempt based on backoff strategy.\n */\nconst calculateDelay = (\n attempt: number,\n baseDelay: number,\n backoff: 'exponential' | 'linear' | 'fixed',\n maxDelay: number,\n): number => {\n let delay: number;\n\n switch (backoff) {\n case 'exponential':\n delay = baseDelay * Math.pow(2, attempt - 1);\n break;\n case 'linear':\n delay = baseDelay * attempt;\n break;\n case 'fixed':\n default:\n delay = baseDelay;\n break;\n }\n\n return Math.min(delay, maxDelay);\n};\n\n/**\n * Sleep for specified duration.\n */\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Creates a retry middleware with smart defaults.\n *\n * 🎯 PIT OF SUCCESS: Works great with no config, customizable when needed.\n *\n * Features:\n * - βœ… Preserves full middleware chain on retries (unlike old implementation)\n * - βœ… Exponential backoff with jitter\n * - βœ… Smart retry conditions (network errors + 5xx)\n * - βœ… Configurable but sensible defaults\n * - βœ… Type-safe configuration\n *\n * @param options - Retry configuration (all optional)\n * @returns Middleware function\n *\n * @example Basic usage:\n * ```typescript\n * const client = new FetchClient();\n * client.use(createRetryMiddleware()); // 3 retries with exponential backoff\n * ```\n *\n * @example Custom configuration:\n * ```typescript\n * const client = new FetchClient();\n * client.use(createRetryMiddleware({\n * maxRetries: 5,\n * delay: 500,\n * backoff: 'linear',\n * onRetry: (attempt, delay) => console.log(`Retry ${attempt} in ${delay}ms`)\n * }));\n * ```\n */\nexport function createRetryMiddleware(\n options: RetryOptions = {},\n): FetchMiddleware {\n const {\n maxRetries = 3,\n delay = 1000,\n backoff = 'exponential',\n maxDelay = 30000,\n shouldRetry = defaultShouldRetry,\n onRetry,\n } = options;\n\n return async (request, next) => {\n let lastResponse: FetchResponse<unknown>;\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n // Execute the request through the middleware chain\n const response = await next(request);\n\n // If successful, return immediately\n if (response.ok) {\n return response;\n }\n\n // Check if we should retry this response with current attempt count\n if (\n !shouldRetry(\n { status: response.status, ok: response.ok },\n attempt + 1,\n )\n ) {\n return response;\n }\n\n // If we've reached max retries, return the response\n if (attempt >= maxRetries) {\n return response;\n }\n\n // Store the failed response and increment attempt counter\n lastResponse = response;\n attempt++;\n\n // Calculate delay for next attempt\n const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);\n\n // Call onRetry callback if provided\n if (onRetry) {\n onRetry(attempt, retryDelay, {\n status: response.status,\n statusText: response.statusText,\n });\n }\n\n // Wait before retrying\n await sleep(retryDelay);\n } catch (error) {\n // Handle unexpected errors - treat as network error (status 0)\n const errorResponse: FetchResponse<unknown> = {\n data: null,\n status: 0,\n statusText: 'Network Error',\n headers: new Headers(),\n url: request.url || '',\n ok: false,\n error: {\n message: error instanceof Error ? error.message : 'Unknown error',\n body: error,\n },\n };\n\n // If shouldn't retry, return error immediately\n if (!shouldRetry(errorResponse, attempt + 1)) {\n return errorResponse;\n }\n\n // If we've reached max retries, return the error\n if (attempt >= maxRetries) {\n return errorResponse;\n }\n\n lastResponse = errorResponse;\n attempt++;\n\n // Calculate delay for next attempt\n const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);\n\n if (onRetry) {\n onRetry(attempt, retryDelay, {\n status: errorResponse.status,\n statusText: errorResponse.statusText,\n });\n }\n\n await sleep(retryDelay);\n }\n }\n\n // Return the last response if we've exhausted all retries\n return lastResponse!;\n };\n}\n","ο»Ώimport type { FetchClient } from '../../client/fetch-client';\nimport type { RetryOptions } from './types';\nimport { createRetryMiddleware } from './retry';\n\nexport type { RetryOptions } from './types';\nexport { createRetryMiddleware } from './retry';\n\nexport function useRetry(\n client: FetchClient,\n options: RetryOptions = {},\n): FetchClient {\n return client.use(createRetryMiddleware(options));\n}\n","/**\n * @fileoverview Complete middleware collection for FetchClient - \"pit of success\" APIs.\n *\n * This module provides a comprehensive set of middleware for common HTTP client concerns:\n * - πŸ” Authentication: Bearer token injection\n * - πŸ›‘οΈ Authorization: 401/403 response handling\n * - πŸ’Ύ Cache: Response caching with TTL\n * - πŸ”’ CSRF: Cross-site request forgery protection\n * - πŸ“ Logging: Request/response logging\n * - 🚦 Rate Limiting: Request rate limiting with token bucket\n * - πŸ”„ Retry: Automatic retry with backoff\n *\n * Each middleware follows the \"pit of success\" pattern with:\n * - Smart defaults for common scenarios\n * - Simple `use{Middleware}()` convenience functions\n * - Advanced `create{Middleware}Middleware()` for custom scenarios\n * - Comprehensive TypeScript support\n *\n * @example Quick setup with multiple middleware:\n * ```typescript\n * import { FetchClient } from '@fgrzl/fetch';\n * import { useAuthentication, useRetry, useLogging } from '@fgrzl/fetch/middleware';\n *\n * const client = new FetchClient();\n * const enhancedClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * })\n * .pipe(useRetry, { retries: 3 })\n * .pipe(useLogging);\n * ```\n */\n\n// πŸ” Authentication middleware\nexport type {\n AuthenticationOptions,\n AuthTokenProvider,\n} from './authentication';\n\nexport {\n useAuthentication,\n createAuthenticationMiddleware,\n} from './authentication';\n\n// πŸ›‘οΈ Authorization middleware\nexport type {\n AuthorizationOptions,\n UnauthorizedHandler,\n} from './authorization';\n\nexport {\n useAuthorization,\n createAuthorizationMiddleware,\n} from './authorization';\n\n// πŸ’Ύ Cache middleware\nexport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './cache';\n\nexport { useCache, createCacheMiddleware } from './cache';\n\n// πŸ”’ CSRF middleware\nexport { useCSRF } from './csrf';\n\n// πŸ“ Logging middleware\nexport type { LoggingOptions, Logger, LogLevel } from './logging';\n\nexport { useLogging, createLoggingMiddleware } from './logging';\n\n// 🚦 Rate limiting middleware\nexport type { RateLimitOptions, RateLimitAlgorithm } from './rate-limit';\n\nexport { useRateLimit, createRateLimitMiddleware } from './rate-limit';\n\n// πŸ”„ Retry middleware\nexport type { RetryOptions } from './retry';\n\nexport { useRetry, createRetryMiddleware } from './retry';\n\n/**\n * Common middleware combinations for typical use cases.\n * These provide pre-configured middleware stacks for common scenarios.\n */\n\nimport type { FetchClient } from '../client/fetch-client';\nimport { useAuthentication } from './authentication';\nimport { useRetry } from './retry';\nimport { useLogging } from './logging';\nimport { useCache } from './cache';\nimport { useRateLimit } from './rate-limit';\n\n/**\n * Production-ready middleware stack with authentication, retry, logging, and caching.\n * Perfect for API clients that need reliability and observability.\n *\n * @param client - The FetchClient to enhance\n * @param config - Configuration for each middleware\n * @returns Enhanced FetchClient with production middleware stack\n *\n * @example\n * ```typescript\n * const apiClient = useProductionStack(new FetchClient(), {\n * auth: { tokenProvider: () => getAuthToken() },\n * cache: { ttl: 5 * 60 * 1000 }, // 5 minutes\n * logging: { level: 'info' }\n * });\n * ```\n */\nexport function useProductionStack(\n client: FetchClient,\n config: {\n auth?: Parameters<typeof useAuthentication>[1];\n retry?: Parameters<typeof useRetry>[1];\n cache?: Parameters<typeof useCache>[1];\n logging?: Parameters<typeof useLogging>[1];\n rateLimit?: Parameters<typeof useRateLimit>[1];\n } = {},\n): FetchClient {\n let enhanced = client;\n\n // Apply middleware in order: auth β†’ cache β†’ retry β†’ rate-limit β†’ logging\n if (config.auth) {\n enhanced = useAuthentication(enhanced, config.auth);\n }\n\n if (config.cache !== undefined) {\n enhanced = useCache(enhanced, config.cache);\n }\n\n if (config.retry !== undefined) {\n enhanced = useRetry(enhanced, config.retry);\n }\n\n if (config.rateLimit !== undefined) {\n enhanced = useRateLimit(enhanced, config.rateLimit);\n }\n\n if (config.logging !== undefined) {\n enhanced = useLogging(enhanced, config.logging);\n }\n\n return enhanced;\n}\n\n/**\n * Development-friendly middleware stack with comprehensive logging and retries.\n * Perfect for local development and debugging.\n *\n * @param client - The FetchClient to enhance\n * @param config - Configuration for development middleware\n * @returns Enhanced FetchClient with development middleware stack\n *\n * @example\n * ```typescript\n * const devClient = useDevelopmentStack(new FetchClient(), {\n * auth: { tokenProvider: () => 'dev-token' }\n * });\n * ```\n */\nexport function useDevelopmentStack(\n client: FetchClient,\n config: {\n auth?: Parameters<typeof useAuthentication>[1];\n } = {},\n): FetchClient {\n let enhanced = client;\n\n if (config.auth) {\n enhanced = useAuthentication(enhanced, config.auth);\n }\n\n // Development-optimized settings\n enhanced = useRetry(enhanced, {\n maxRetries: 1,\n delay: 100,\n });\n\n enhanced = useLogging(enhanced, {\n level: 'debug',\n includeRequestHeaders: true,\n includeResponseHeaders: true,\n includeRequestBody: true,\n includeResponseBody: true,\n });\n\n return enhanced;\n}\n\n/**\n * Basic middleware stack with just authentication and retry.\n * Perfect for simple API clients that need minimal overhead.\n *\n * @param client - The FetchClient to enhance\n * @param config - Basic configuration\n * @returns Enhanced FetchClient with basic middleware stack\n *\n * @example\n * ```typescript\n * const basicClient = useBasicStack(new FetchClient(), {\n * auth: { tokenProvider: () => getToken() }\n * });\n * ```\n */\nexport function useBasicStack(\n client: FetchClient,\n config: {\n auth: Parameters<typeof useAuthentication>[1];\n },\n): FetchClient {\n return useRetry(useAuthentication(client, config.auth), { maxRetries: 2 });\n}\n","/**\n * @fileoverview Custom error classes - \"Pit of Success\" pattern.\n *\n * 🎯 LEVEL 1: HttpError, NetworkError - Most common error types you'll catch\n * 🎯 LEVEL 2: FetchError - Base error class for advanced error handling\n *\n * @example\n * ```typescript\n * try {\n * await client.get('/api/data');\n * } catch (error) {\n * if (error instanceof HttpError) {\n * console.log(`HTTP ${error.status}: ${error.statusText}`);\n * } else if (error instanceof NetworkError) {\n * console.log('Network connection failed');\n * }\n * }\n * ```\n */\n\n// 🎯 LEVEL 2: Base error class (for advanced use cases)\n\n/**\n * Base error class for all fetch client errors.\n */\nexport class FetchError extends Error {\n /** Optional underlying cause */\n public readonly cause?: Error;\n\n /**\n * Creates a new FetchError.\n * @param message - Error message\n * @param cause - Optional underlying cause\n */\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'FetchError';\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n\n// 🎯 LEVEL 1: Most commonly used error types\n\n/**\n * Error thrown when an HTTP request fails with a non-2xx status code.\n */\nexport class HttpError extends FetchError {\n /** The HTTP status code */\n public readonly status: number;\n /** The HTTP status text */\n public readonly statusText: string;\n /** The response body (if available) */\n public readonly body: unknown;\n\n /**\n * Creates a new HttpError.\n * @param status - HTTP status code\n * @param statusText - HTTP status text\n * @param body - Response body\n * @param url - The request URL\n */\n constructor(status: number, statusText: string, body: unknown, url: string) {\n super(`HTTP ${status} ${statusText} at ${url}`);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.body = body;\n }\n}\n\n/**\n * Error thrown when a network request fails completely.\n */\nexport class NetworkError extends FetchError {\n /**\n * Creates a new NetworkError.\n * @param message - Error message\n * @param url - The request URL\n * @param cause - The underlying network error\n */\n constructor(message: string, url: string, cause?: Error) {\n super(`Network error for ${url}: ${message}`, cause);\n this.name = 'NetworkError';\n }\n}\n"],"mappings":"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","names":["shouldSkipAuth"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/client/fetch-client.ts","../../src/middleware/authentication/authentication.ts","../../src/middleware/authentication/index.ts","../../src/middleware/authorization/authorization.ts","../../src/middleware/authorization/index.ts","../../src/middleware/cache/cache.ts","../../src/middleware/cache/index.ts","../../src/middleware/csrf/csrf.ts","../../src/middleware/csrf/index.ts","../../src/middleware/logging/logging.ts","../../src/middleware/logging/index.ts","../../src/middleware/rate-limit/rate-limit.ts","../../src/middleware/rate-limit/index.ts","../../src/middleware/retry/retry.ts","../../src/middleware/retry/index.ts","../../src/middleware/index.ts","../../src/errors/index.ts","../../src/client/query.ts"],"sourcesContent":["/**\n * @fileoverview Main library entry point with \"pit of success\" architecture.\n *\n * This module exports everything users need in order of discoverability:\n * 1. Pre-configured client with smart defaults (80% of users start here)\n * 2. FetchClient for custom configurations\n * 3. Individual middleware functions for specific needs\n * 4. Pre-built middleware stacks for common scenarios\n * 5. Types for TypeScript users\n */\n\nimport { FetchClient } from './client/fetch-client';\nimport { useProductionStack } from './middleware';\n\n/**\n * 🎯 PIT OF SUCCESS: Pre-configured fetch client (Level 1 - 80% of users)\n *\n * This client is ready to use out of the box with production-ready middleware:\n * - Authentication support (configure your token provider)\n * - Automatic retries with exponential backoff\n * - Response caching for GET requests\n * - Request/response logging\n * - Rate limiting protection\n * - Same-origin credentials for session-based auth (cookies)\n *\n * @example Just import and use:\n * ```typescript\n * import api from '@fgrzl/fetch';\n *\n * // Works immediately - no setup required!\n * const users = await api.get('/api/users');\n * const newUser = await api.post('/api/users', { name: 'John' });\n *\n * // With query parameters\n * const activeUsers = await api.get('/api/users', { status: 'active', limit: 10 });\n * ```\n *\n * @example Set base URL for API-specific clients:\n * ```typescript\n * import api from '@fgrzl/fetch';\n *\n * // Configure base URL dynamically\n * api.setBaseUrl('https://api.example.com');\n *\n * // Now all relative URLs are prefixed automatically\n * const users = await api.get('/users'); // β†’ GET https://api.example.com/users\n * const posts = await api.get('/posts'); // β†’ GET https://api.example.com/posts\n * ```\n *\n * @example Configure authentication:\n * ```typescript\n * import api from '@fgrzl/fetch';\n * import { useAuthentication } from '@fgrzl/fetch/middleware';\n *\n * const authClient = useAuthentication(api, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * });\n * ```\n *\n * @example For token-only auth (no cookies):\n * ```typescript\n * import { FetchClient, useAuthentication } from '@fgrzl/fetch';\n *\n * const tokenClient = useAuthentication(new FetchClient({\n * credentials: 'omit' // Don't send cookies\n * }), {\n * tokenProvider: () => getJWTToken()\n * });\n * ```\n *\n * @example Production-ready API client with base URL:\n * ```typescript\n * import { FetchClient, useProductionStack } from '@fgrzl/fetch';\n *\n * // One-liner production setup with base URL\n * const apiClient = useProductionStack(new FetchClient(), {\n * auth: { tokenProvider: () => getAuthToken() },\n * retry: { maxRetries: 3 },\n * logging: { level: 'info' }\n * }).setBaseUrl(process.env.API_BASE_URL || 'https://api.example.com');\n *\n * // Ready to use with full production features\n * const users = await apiClient.get('/users');\n * ```\n */\nconst api = useProductionStack(\n new FetchClient({\n // Smart default: include cookies for session-based auth\n // Can be overridden by creating a custom FetchClient\n credentials: 'same-origin',\n }),\n {\n // Smart defaults - users can override as needed\n retry: {\n maxRetries: 2,\n delay: 1000,\n },\n cache: {\n ttl: 5 * 60 * 1000, // 5 minutes\n methods: ['GET'],\n },\n logging: {\n level: 'info',\n },\n rateLimit: {\n maxRequests: 100,\n windowMs: 60 * 1000, // 100 requests per minute\n },\n },\n);\n\n// 🎯 LEVEL 1: Export the production-ready client as default\nexport default api;\n\n// 🎯 LEVEL 2: FetchClient for custom configurations\nexport { FetchClient } from './client/fetch-client';\nexport { FetchError, HttpError, NetworkError } from './errors';\n\n// 🎯 LEVEL 2.5: Query utilities for advanced URL building\nexport { buildQueryParams, appendQueryParams } from './client/query';\n\n// 🎯 LEVEL 3: Individual middleware functions (import from our comprehensive middleware index)\nexport {\n // Authentication\n useAuthentication,\n createAuthenticationMiddleware,\n // Authorization\n useAuthorization,\n createAuthorizationMiddleware,\n // Cache\n useCache,\n createCacheMiddleware,\n // CSRF\n useCSRF,\n // Logging\n useLogging,\n createLoggingMiddleware,\n // Rate Limiting\n useRateLimit,\n createRateLimitMiddleware,\n // Retry\n useRetry,\n createRetryMiddleware,\n} from './middleware';\n\n// 🎯 LEVEL 4: Pre-built middleware stacks for common scenarios\nexport {\n useProductionStack,\n useDevelopmentStack,\n useBasicStack,\n} from './middleware';\n\n// 🎯 LEVEL 5: Types for TypeScript users\nexport type { FetchMiddleware as InterceptMiddleware } from './client/fetch-client';\nexport type { FetchResponse, FetchClientOptions } from './client/types';\n\n// Query utility types\nexport type { QueryParams, QueryValue } from './client/query';\n\n// Middleware types (re-exported from middleware index)\nexport type {\n // Authentication types\n AuthenticationOptions,\n AuthTokenProvider,\n // Authorization types\n AuthorizationOptions,\n UnauthorizedHandler,\n // Cache types\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n // Logging types\n LoggingOptions,\n Logger,\n LogLevel,\n // Rate limiting types\n RateLimitOptions,\n RateLimitAlgorithm,\n // Retry types\n RetryOptions,\n} from './middleware';\n","/**\n * @fileoverview Enhanced fetch client with intercept middleware architecture.\n */\n\nimport type { FetchResponse, FetchClientOptions } from './types';\n\n/**\n * Intercept middleware type that allows full control over request/response cycle.\n * Middleware can modify requests, handle responses, implement retries, etc.\n */\nexport type FetchMiddleware = (\n request: RequestInit & { url?: string },\n next: (\n modifiedRequest?: RequestInit & { url?: string },\n ) => Promise<FetchResponse<unknown>>,\n) => Promise<FetchResponse<unknown>>;\n\n/**\n * Enhanced HTTP client with intercept middleware architecture.\n *\n * Features:\n * - 🎯 Smart defaults (JSON content-type, same-origin credentials)\n * - πŸ”§ Powerful middleware system for cross-cutting concerns\n * - πŸ›‘οΈ Consistent error handling (never throws, always returns response)\n * - πŸ“¦ TypeScript-first with full type inference\n * - πŸš€ Modern async/await API\n *\n * @example Basic usage:\n * ```typescript\n * const client = new FetchClient();\n *\n * // GET request - just works\n * const users = await client.get<User[]>('/api/users');\n * if (users.ok) {\n * console.log(users.data); // Type is User[]\n * }\n *\n * // POST request - JSON by default\n * const result = await client.post('/api/users', { name: 'John' });\n * ```\n *\n * @example With middleware:\n * ```typescript\n * const client = new FetchClient();\n *\n * // Add auth middleware\n * client.use((request, next) => {\n * request.headers = { ...request.headers, Authorization: 'Bearer token' };\n * return next(request);\n * });\n *\n * // Now all requests include auth\n * const data = await client.get('/api/protected');\n * ```\n */\nexport class FetchClient {\n private middlewares: FetchMiddleware[] = [];\n private credentials: RequestCredentials;\n private baseUrl: string | undefined;\n\n constructor(config: FetchClientOptions = {}) {\n this.credentials = config.credentials ?? 'same-origin';\n this.baseUrl = config.baseUrl;\n }\n\n use(middleware: FetchMiddleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n /**\n * Set or update the base URL for this client instance.\n *\n * When a base URL is set, relative URLs will be resolved against it.\n * Absolute URLs will continue to work unchanged.\n *\n * @param baseUrl - The base URL to set, or undefined to clear it\n * @returns The client instance for method chaining\n *\n * @example Set base URL:\n * ```typescript\n * const client = new FetchClient();\n * client.setBaseUrl('https://api.example.com');\n *\n * // Now relative URLs work\n * await client.get('/users'); // β†’ GET https://api.example.com/users\n * ```\n *\n * @example Chain with middleware:\n * ```typescript\n * const client = useProductionStack(new FetchClient())\n * .setBaseUrl(process.env.API_BASE_URL);\n * ```\n */\n setBaseUrl(baseUrl?: string): this {\n this.baseUrl = baseUrl;\n return this;\n }\n\n async request<T = unknown>(\n url: string,\n init: RequestInit = {},\n ): Promise<FetchResponse<T>> {\n // Resolve URL against baseUrl if relative\n const resolvedUrl = this.resolveUrl(url);\n\n // Create the execution chain\n let index = 0;\n\n const execute = async (\n request?: RequestInit & { url?: string },\n ): Promise<FetchResponse<unknown>> => {\n // Use provided request or fall back to original\n const currentRequest = request || { ...init, url: resolvedUrl };\n const currentUrl = currentRequest.url || resolvedUrl;\n\n if (index >= this.middlewares.length) {\n // Core fetch - end of middleware chain\n const { url: _, ...requestInit } = currentRequest; // Remove url from request init\n return this.coreFetch(requestInit, currentUrl);\n }\n\n const middleware = this.middlewares[index++];\n if (!middleware) {\n const { url: _, ...requestInit } = currentRequest;\n return this.coreFetch(requestInit, currentUrl);\n }\n return middleware(currentRequest, execute);\n };\n\n const result = await execute();\n return result as FetchResponse<T>;\n }\n\n private async coreFetch(\n request: RequestInit,\n url: string,\n ): Promise<FetchResponse<unknown>> {\n try {\n const finalInit = {\n credentials: this.credentials,\n ...request,\n };\n\n // Convert Headers object to plain object for better compatibility\n if (finalInit.headers instanceof Headers) {\n const headersObj: Record<string, string> = {};\n finalInit.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n finalInit.headers = headersObj;\n }\n\n const response = await fetch(url, finalInit);\n const data = await this.parseResponse(response);\n\n return {\n data: response.ok ? data : null,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url,\n ok: response.ok,\n ...(response.ok\n ? {}\n : {\n error: {\n message: response.statusText,\n body: data,\n },\n }),\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return {\n data: null,\n status: 0,\n statusText: 'Network Error',\n headers: new Headers(),\n url,\n ok: false,\n error: {\n message: 'Failed to fetch',\n body: error,\n },\n };\n }\n throw error;\n }\n }\n\n private async parseResponse(res: Response): Promise<unknown> {\n const contentType = res.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n return res.json();\n }\n\n if (contentType.includes('text/')) {\n return res.text();\n }\n\n if (\n contentType.includes('application/octet-stream') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ) {\n return res.blob();\n }\n\n if (res.body) {\n const text = await res.text();\n return text || null;\n }\n\n return null;\n }\n\n // Helper method to build URL with query parameters\n private buildUrlWithParams(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): string {\n if (!params) {\n return url;\n }\n\n // Resolve the URL first (handles baseUrl if needed)\n const resolvedUrl = this.resolveUrl(url);\n\n // If the resolved URL is still relative (no base URL configured),\n // manually build query parameters\n if (\n !resolvedUrl.startsWith('http://') &&\n !resolvedUrl.startsWith('https://') &&\n !resolvedUrl.startsWith('//')\n ) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n return queryString ? `${resolvedUrl}?${queryString}` : resolvedUrl;\n }\n\n // For absolute URLs, use URL constructor\n const urlObj = new URL(resolvedUrl);\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n urlObj.searchParams.set(key, String(value));\n }\n });\n\n return urlObj.toString();\n }\n\n /**\n * Resolves a URL with the base URL if it's relative and base URL is configured\n * @param url - The URL to resolve\n * @returns The resolved URL\n * @private\n */\n private resolveUrl(url: string): string {\n // If URL is already absolute, return as-is\n if (\n url.startsWith('http://') ||\n url.startsWith('https://') ||\n url.startsWith('//')\n ) {\n return url;\n }\n\n // If no base URL is configured, return the relative URL as-is (backward compatibility)\n if (!this.baseUrl) {\n return url;\n }\n\n // Resolve relative URL with base URL\n try {\n const baseUrl = new URL(this.baseUrl);\n const resolvedUrl = new URL(url, baseUrl);\n return resolvedUrl.toString();\n } catch {\n throw new Error(\n `Invalid URL: Unable to resolve \"${url}\" with baseUrl \"${this.baseUrl}\"`,\n );\n }\n } // 🎯 PIT OF SUCCESS: Convenience methods with smart defaults\n\n /**\n * HEAD request with query parameter support.\n *\n * HEAD requests are used to retrieve metadata about a resource without downloading\n * the response body. Useful for checking if a resource exists, getting content length,\n * last modified date, etc.\n *\n * @template T - Expected response data type (will be null for HEAD requests)\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response (data will always be null)\n *\n * @example Check if resource exists:\n * ```typescript\n * const headResponse = await client.head('/api/large-file.zip');\n * if (headResponse.ok) {\n * const contentLength = headResponse.headers.get('content-length');\n * const lastModified = headResponse.headers.get('last-modified');\n * console.log(`File size: ${contentLength} bytes`);\n * }\n * ```\n *\n * @example Check with query parameters:\n * ```typescript\n * const exists = await client.head('/api/users', { id: 123 });\n * if (exists.status === 404) {\n * console.log('User not found');\n * }\n * ```\n */\n head<T = null>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'HEAD' });\n }\n\n /**\n * HEAD request that returns useful metadata about a resource.\n *\n * This is a convenience method that extracts common metadata from HEAD responses\n * for easier consumption.\n *\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to response with extracted metadata\n *\n * @example Get resource metadata:\n * ```typescript\n * const metadata = await client.headMetadata('/api/large-file.zip');\n * if (metadata.ok) {\n * console.log('File exists:', metadata.exists);\n * console.log('Content type:', metadata.contentType);\n * console.log('Size:', metadata.contentLength, 'bytes');\n * console.log('Last modified:', metadata.lastModified);\n * }\n * ```\n */\n async headMetadata(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<\n FetchResponse<null> & {\n exists: boolean;\n contentType: string | undefined;\n contentLength: number | undefined;\n lastModified: Date | undefined;\n etag: string | undefined;\n cacheControl: string | undefined;\n }\n > {\n const response = await this.head(url, params);\n\n const contentLengthHeader = response.headers.get('content-length');\n const lastModifiedHeader = response.headers.get('last-modified');\n\n return {\n ...response,\n exists: response.ok,\n contentType: response.headers.get('content-type') || undefined,\n contentLength: contentLengthHeader\n ? parseInt(contentLengthHeader, 10)\n : undefined,\n lastModified: lastModifiedHeader\n ? new Date(lastModifiedHeader)\n : undefined,\n etag: response.headers.get('etag') || undefined,\n cacheControl: response.headers.get('cache-control') || undefined,\n };\n }\n\n /**\n * GET request with query parameter support.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const users = await client.get<User[]>('/api/users');\n * const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });\n * if (users.ok) console.log(users.data);\n * ```\n */\n get<T>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'GET' });\n }\n\n /**\n * POST request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const result = await client.post<User>('/api/users', { name: 'John' });\n * ```\n */\n post<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'POST',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * PUT request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n */\n put<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'PUT',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * PATCH request with automatic JSON serialization.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param body - Request body (auto-serialized to JSON)\n * @param headers - Additional headers (Content-Type: application/json is default)\n * @returns Promise resolving to typed response\n */\n patch<T>(\n url: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<FetchResponse<T>> {\n const requestHeaders = {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n };\n\n return this.request<T>(url, {\n method: 'PATCH',\n headers: requestHeaders,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n }\n\n /**\n * DELETE request with query parameter support.\n *\n * @template T - Expected response data type\n * @param url - Request URL\n * @param params - Query parameters to append to URL\n * @returns Promise resolving to typed response\n *\n * @example\n * ```typescript\n * const result = await client.del('/api/users/123');\n * const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });\n * if (result.ok) console.log('Deleted successfully');\n * ```\n */\n del<T>(\n url: string,\n params?: Record<string, string | number | boolean | undefined>,\n ): Promise<FetchResponse<T>> {\n const finalUrl = this.buildUrlWithParams(url, params);\n return this.request<T>(finalUrl, { method: 'DELETE' });\n }\n}\n","/**\n * @fileoverview Authentication middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { AuthenticationOptions } from './types';\n\n/**\n * Checks if a URL should skip authentication based on configured patterns.\n */\nfunction shouldSkipAuth(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Checks if a URL should include authentication based on configured patterns.\n */\nfunction shouldIncludeAuth(\n url: string,\n includePatterns?: (RegExp | string)[],\n): boolean {\n if (!includePatterns || includePatterns.length === 0) {\n return true; // Include by default if no patterns specified\n }\n\n return includePatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates authentication middleware with smart defaults.\n * Automatically adds Bearer tokens to requests.\n *\n * @param options - Authentication configuration options\n * @returns Authentication middleware for use with FetchClient\n *\n * @example Basic usage:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('token') || ''\n * });\n * ```\n *\n * @example Async token provider:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: async () => {\n * const token = await getAuthToken();\n * return token || '';\n * }\n * });\n * ```\n */\nexport function createAuthenticationMiddleware(\n options: AuthenticationOptions,\n): FetchMiddleware {\n const {\n tokenProvider,\n headerName = 'Authorization',\n tokenType = 'Bearer',\n skipPatterns = [],\n includePatterns,\n } = options;\n\n return async (request, next) => {\n const url = request.url || '';\n const parsedUrl = new URL(url);\n const pathname = parsedUrl.pathname;\n\n // Skip authentication if:\n // 1. URL matches a skip pattern\n // 2. URL doesn't match include patterns (if specified)\n if (\n shouldSkipAuth(pathname, skipPatterns) ||\n !shouldIncludeAuth(pathname, includePatterns)\n ) {\n return next(request);\n }\n\n try {\n // Get auth token (may be async)\n const token = await tokenProvider();\n\n // Skip if no token available\n if (!token) {\n return next(request);\n }\n\n // Add auth header to request\n const headers = new Headers(request.headers);\n headers.set(headerName, `${tokenType} ${token}`);\n\n // Create modified request with auth header\n const modifiedRequest = {\n ...request,\n headers,\n };\n\n return next(modifiedRequest);\n } catch {\n // If token provider fails, proceed without auth\n // This ensures network requests don't fail due to auth issues\n return next(request);\n }\n };\n}\n","/**\n * @fileoverview Authentication middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { AuthenticationOptions } from './types';\nimport { createAuthenticationMiddleware } from './authentication';\n\n// Re-export types for convenience\nexport type { AuthenticationOptions, AuthTokenProvider } from './types';\nexport { createAuthenticationMiddleware } from './authentication';\n\n/**\n * \"Pit of success\" API for adding authentication to a FetchClient.\n * Automatically adds Bearer tokens to requests.\n *\n * @param client - The FetchClient to add authentication to\n * @param options - Authentication configuration\n * @returns A new FetchClient with authentication middleware\n *\n * @example Basic token from localStorage:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * });\n * ```\n *\n * @example Async token with refresh:\n * ```typescript\n * const authClient = useAuthentication(client, {\n * tokenProvider: async () => {\n * let token = localStorage.getItem('auth-token');\n * if (!token || isExpired(token)) {\n * token = await refreshToken();\n * }\n * return token || '';\n * }\n * });\n * ```\n */\nexport function useAuthentication(\n client: FetchClient,\n options: AuthenticationOptions,\n): FetchClient {\n return client.use(createAuthenticationMiddleware(options));\n}\n","/**\n * @fileoverview Authorization middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type {\n AuthorizationOptions,\n RedirectAuthorizationConfig,\n UnauthorizedHandler,\n} from './types';\n\n/**\n * Creates a smart default redirect handler for unauthorized responses.\n * Redirects to login with a return URL parameter.\n */\nfunction createRedirectHandler(config: RedirectAuthorizationConfig = {}) {\n const {\n redirectPath = '/login',\n returnUrlParam = 'return_url',\n includeReturnUrl = true,\n } = config;\n\n return () => {\n let redirectUrl = redirectPath;\n\n if (includeReturnUrl && typeof window !== 'undefined') {\n const currentUrl = encodeURIComponent(window.location.href);\n const separator = redirectPath.includes('?') ? '&' : '?';\n redirectUrl = `${redirectPath}${separator}${returnUrlParam}=${currentUrl}`;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = redirectUrl;\n }\n };\n}\n\n/**\n * Selects the appropriate unauthorized handler based on provided options.\n * Priority: explicit onUnauthorized > redirectConfig > smart default\n */\nfunction selectUnauthorizedHandler(\n providedHandler?: UnauthorizedHandler,\n redirectConfig?: RedirectAuthorizationConfig,\n): UnauthorizedHandler {\n if (providedHandler) {\n return providedHandler;\n }\n\n return createRedirectHandler(redirectConfig);\n}\n\n/**\n * Checks if a URL should skip authorization handling based on configured patterns.\n */\nfunction shouldSkipAuth(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n // Extract pathname from URL for pattern matching\n let pathname: string;\n try {\n pathname = new URL(url).pathname;\n } catch {\n pathname = url; // fallback if not a valid URL\n }\n\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return pathname.includes(pattern);\n }\n return pattern.test(pathname);\n });\n}\n\n/**\n * Creates authorization middleware with smart defaults.\n * Handles 401/403 responses by calling configured handlers.\n *\n * @param options - Authorization configuration options (optional)\n * @returns Authorization middleware for use with FetchClient\n *\n * @example Smart defaults (no configuration needed):\n * ```typescript\n * const authzClient = useAuthorization(client);\n * // Redirects to '/login?return_url=current-page' on 401\n * ```\n *\n * @example Custom redirect configuration:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * redirectConfig: {\n * redirectPath: '/signin',\n * returnUrlParam: 'redirect_to'\n * }\n * });\n * ```\n *\n * @example Manual handler (full control):\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onUnauthorized: () => window.location.href = '/login'\n * });\n * ```\n *\n * @example Handle both 401 and 403:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onForbidden: () => showAccessDeniedMessage(),\n * statusCodes: [401, 403]\n * });\n * ```\n */\nexport function createAuthorizationMiddleware(\n options: AuthorizationOptions = {},\n): FetchMiddleware {\n const {\n onUnauthorized: providedOnUnauthorized,\n redirectConfig,\n onForbidden,\n skipPatterns = [],\n statusCodes = [401],\n } = options;\n\n const onUnauthorized = selectUnauthorizedHandler(\n providedOnUnauthorized,\n redirectConfig,\n );\n\n return async (request, next) => {\n const url = request.url || '';\n\n // Skip authorization handling if URL matches skip patterns\n if (shouldSkipAuth(url, skipPatterns)) {\n return next(request);\n }\n\n // Execute the request\n const response = await next(request);\n\n // Check if response status requires handling\n if (statusCodes.includes(response.status)) {\n try {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized(response, request);\n } else if (response.status === 403 && onForbidden) {\n await onForbidden(response, request);\n } else if (onUnauthorized) {\n // For any other configured status codes, use the first available handler\n await onUnauthorized(response, request);\n }\n } catch (error) {\n // If handler fails, log but don't break the response chain\n // eslint-disable-next-line no-console\n console.warn('Authorization handler failed:', error);\n }\n }\n\n return response;\n };\n}\n","/**\n * @fileoverview Authorization middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { AuthorizationOptions } from './types';\nimport { createAuthorizationMiddleware } from './authorization';\n\n// Re-export types for convenience\nexport type {\n AuthorizationOptions,\n UnauthorizedHandler,\n RedirectAuthorizationConfig,\n} from './types';\nexport { createAuthorizationMiddleware } from './authorization';\n\n/**\n * \"Pit of success\" API for adding authorization handling to a FetchClient.\n * Automatically handles 401 Unauthorized responses.\n *\n * @param client - The FetchClient to add authorization handling to\n * @param options - Authorization configuration (optional)\n * @returns A new FetchClient with authorization middleware\n *\n * @example Smart defaults - no configuration needed:\n * ```typescript\n * const authzClient = useAuthorization(client);\n * // Redirects to '/login?return_url=current-page' on 401\n * ```\n *\n * @example Custom redirect path:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * redirectConfig: { redirectPath: '/signin', returnUrlParam: 'redirect_to' }\n * });\n * ```\n *\n * @example Manual handler (full control):\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onUnauthorized: () => {\n * localStorage.removeItem('auth-token');\n * window.location.href = '/login';\n * }\n * });\n * ```\n *\n * @example Handle multiple status codes:\n * ```typescript\n * const authzClient = useAuthorization(client, {\n * onForbidden: () => showAccessDenied(),\n * statusCodes: [401, 403]\n * });\n * ```\n */\nexport function useAuthorization(\n client: FetchClient,\n options: AuthorizationOptions = {},\n): FetchClient {\n return client.use(createAuthorizationMiddleware(options));\n}\n","/**\n * @fileoverview Cache middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { FetchResponse } from '../../client/types';\nimport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './types';\n\n/**\n * Default in-memory cache storage implementation.\n */\nexport class MemoryStorage implements CacheStorage {\n private cache = new Map<string, CacheEntry>();\n\n async get(key: string): Promise<CacheEntry | null> {\n const entry = this.cache.get(key);\n if (!entry) {\n return null;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry;\n }\n\n async getWithExpiry(\n key: string,\n ): Promise<{ entry: CacheEntry | null; isExpired: boolean }> {\n const entry = this.cache.get(key);\n if (!entry) {\n return { entry: null, isExpired: false };\n }\n\n const isExpired = Date.now() > entry.expiresAt;\n // Don't delete expired entries when using getWithExpiry - let the caller decide\n return { entry, isExpired };\n }\n\n async set(key: string, entry: CacheEntry): Promise<void> {\n this.cache.set(key, entry);\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n}\n\n/**\n * Default cache key generator.\n */\nconst defaultKeyGenerator: CacheKeyGenerator = (request) => {\n const url = request.url || '';\n const method = request.method || 'GET';\n const headers = request.headers ? JSON.stringify(request.headers) : '';\n return `${method}:${url}:${headers}`;\n};\n\n/**\n * Checks if a URL should skip caching based on configured patterns.\n */\nfunction shouldSkipCache(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates cache middleware with smart defaults.\n * Caches GET responses for faster subsequent requests.\n *\n * @param options - Cache configuration options\n * @returns Cache middleware for use with FetchClient\n *\n * @example Basic caching:\n * ```typescript\n * const cachedClient = useCache(client);\n * // GET requests will be cached for 5 minutes\n * ```\n *\n * @example Custom TTL:\n * ```typescript\n * const cachedClient = useCache(client, {\n * ttl: 10 * 60 * 1000 // 10 minutes\n * });\n * ```\n */\nexport function createCacheMiddleware(\n options: CacheOptions = {},\n): FetchMiddleware {\n const {\n ttl = 5 * 60 * 1000, // 5 minutes\n methods = ['GET'],\n storage = new MemoryStorage(),\n keyGenerator = defaultKeyGenerator,\n skipPatterns = [],\n staleWhileRevalidate = false,\n } = options;\n\n return async (request, next) => {\n const method = (request.method || 'GET').toUpperCase();\n const url = request.url || '';\n\n // Skip caching if:\n // 1. Method is not in cached methods list\n // 2. URL matches a skip pattern\n if (!methods.includes(method) || shouldSkipCache(url, skipPatterns)) {\n return next(request);\n }\n\n const cacheKey = keyGenerator(request);\n\n try {\n // Try to get cached response with expiry info\n const { entry: cached, isExpired } = storage.getWithExpiry\n ? await storage.getWithExpiry(cacheKey)\n : await (async () => {\n const entry = await storage.get(cacheKey);\n return { entry, isExpired: false };\n })();\n\n if (cached && !isExpired) {\n // Return fresh cached response\n return {\n ...cached.response,\n headers: new Headers(cached.response.headers),\n data: cached.response.data,\n } as FetchResponse<unknown>;\n }\n\n // If stale-while-revalidate and we have cached data (even expired), return it immediately\n // and update in background\n if (cached && staleWhileRevalidate) {\n // Return cached data immediately (even if stale)\n const cachedResponse = {\n ...cached.response,\n headers: new Headers(cached.response.headers),\n data: cached.response.data,\n } as FetchResponse<unknown>;\n\n // Update cache in background if expired\n if (isExpired) {\n next(request)\n .then(async (freshResponse) => {\n const headersObj: Record<string, string> = {};\n freshResponse.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n\n const cacheEntry: CacheEntry = {\n response: {\n status: freshResponse.status,\n statusText: freshResponse.statusText,\n headers: headersObj,\n data: freshResponse.data,\n },\n timestamp: Date.now(),\n expiresAt: Date.now() + ttl,\n };\n await storage.set(cacheKey, cacheEntry);\n })\n .catch(() => {\n // Ignore background update errors\n });\n }\n\n return cachedResponse;\n }\n\n // No cached data or not using stale-while-revalidate\n const response = await next(request);\n\n // Cache successful responses\n if (response.ok) {\n try {\n const headersObj: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headersObj[key] = value;\n });\n\n const cacheEntry: CacheEntry = {\n response: {\n status: response.status,\n statusText: response.statusText,\n headers: headersObj,\n data: response.data,\n },\n timestamp: Date.now(),\n expiresAt: Date.now() + ttl,\n };\n\n await storage.set(cacheKey, cacheEntry);\n } catch {\n // Ignore cache storage errors, but still return the response\n }\n }\n\n return response;\n } catch (error) {\n // Only catch cache retrieval errors, let network errors through\n if (error && typeof error === 'object' && 'message' in error) {\n const errorMessage = (error as { message: string }).message;\n if (\n errorMessage.includes('Network') ||\n errorMessage.includes('fetch')\n ) {\n throw error; // Re-throw network errors\n }\n }\n\n // If cache retrieval fails, just proceed with the request\n return next(request);\n }\n };\n}\n","/**\n * @fileoverview Cache middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { CacheOptions } from './types';\nimport { createCacheMiddleware } from './cache';\n\n// Re-export types for convenience\nexport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './types';\nexport { createCacheMiddleware, MemoryStorage } from './cache';\n\n/**\n * \"Pit of success\" API for adding response caching to a FetchClient.\n * Caches GET responses for faster subsequent requests.\n *\n * @param client - The FetchClient to add caching to\n * @param options - Cache configuration options\n * @returns A new FetchClient with cache middleware\n *\n * @example Basic caching (5 minute TTL):\n * ```typescript\n * const cachedClient = useCache(client);\n *\n * // First call hits the network\n * await cachedClient.get('/api/data');\n *\n * // Second call returns cached data\n * await cachedClient.get('/api/data');\n * ```\n *\n * @example Custom TTL and methods:\n * ```typescript\n * const cachedClient = useCache(client, {\n * ttl: 10 * 60 * 1000, // 10 minutes\n * methods: ['GET', 'HEAD']\n * });\n * ```\n *\n * @example Stale-while-revalidate:\n * ```typescript\n * const cachedClient = useCache(client, {\n * staleWhileRevalidate: true\n * });\n * // Returns stale data immediately, updates cache in background\n * ```\n */\nexport function useCache(\n client: FetchClient,\n options: CacheOptions = {},\n): FetchClient {\n return client.use(createCacheMiddleware(options));\n}\n","/**\n * @fileoverview CSRF protection middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { CSRFOptions } from './types';\n\n/**\n * Default CSRF token provider that extracts token from XSRF-TOKEN cookie.\n * This follows the standard convention used by Rails, Laravel, and many other frameworks.\n */\nfunction getTokenFromCookie(cookieName: string = 'XSRF-TOKEN'): string {\n if (typeof document === 'undefined') {\n return ''; // Server-side, no cookies available\n }\n\n const name = `${cookieName}=`;\n const decodedCookie = decodeURIComponent(document.cookie);\n const cookies = decodedCookie.split(';');\n\n for (const cookie of cookies) {\n const c = cookie.trim();\n if (c.indexOf(name) === 0) {\n return c.substring(name.length);\n }\n }\n\n return '';\n}\n\n/**\n * Checks if a URL should skip CSRF protection based on configured patterns.\n */\nfunction shouldSkipCSRF(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates CSRF protection middleware with smart defaults.\n * Automatically adds CSRF tokens to state-changing requests.\n *\n * @param options - CSRF configuration options (all optional for \"pit of success\")\n * @returns CSRF middleware for use with FetchClient\n *\n * @example Basic usage (uses cookies automatically):\n * ```typescript\n * const client = new FetchClient();\n * const csrfClient = useCSRF(client);\n * ```\n *\n * @example Custom token provider:\n * ```typescript\n * const csrfClient = useCSRF(client, {\n * tokenProvider: () => localStorage.getItem('csrf-token') || ''\n * });\n * ```\n *\n * @example Skip external APIs:\n * ```typescript\n * const csrfClient = useCSRF(client, {\n * skipPatterns: [/^https:\\/\\/api\\.external\\.com\\//, '/webhook/']\n * });\n * ```\n */\nexport function createCSRFMiddleware(\n options: CSRFOptions = {},\n): FetchMiddleware {\n // Smart defaults for \"pit of success\"\n const {\n headerName = 'X-XSRF-TOKEN',\n cookieName = 'XSRF-TOKEN',\n protectedMethods = ['POST', 'PUT', 'PATCH', 'DELETE'],\n skipPatterns = [],\n tokenProvider = () => getTokenFromCookie(cookieName),\n } = options;\n\n return async (request, next) => {\n const method = (request.method || 'GET').toUpperCase();\n const url = request.url || '';\n\n // Skip CSRF protection if:\n // 1. Method is not in protected methods list\n // 2. URL matches a skip pattern\n if (\n !protectedMethods.includes(method) ||\n shouldSkipCSRF(url, skipPatterns)\n ) {\n return next(request);\n }\n\n // Get CSRF token\n const token = tokenProvider();\n\n // Skip if no token available (let the server handle the error)\n if (!token) {\n return next(request);\n }\n\n // Add CSRF token to request headers\n const headers = new Headers(request.headers);\n headers.set(headerName, token);\n\n // Create modified request with CSRF header\n const modifiedRequest = {\n ...request,\n headers,\n };\n\n return next(modifiedRequest);\n };\n}\n","/**\n * @fileoverview CSRF protection middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { CSRFOptions } from './types';\nimport { createCSRFMiddleware } from './csrf';\n\n// Re-export types for convenience\nexport type { CSRFOptions, CSRFTokenProvider } from './types';\nexport { createCSRFMiddleware } from './csrf';\n\n/**\n * \"Pit of success\" API for adding CSRF protection to a FetchClient.\n * Uses smart defaults that work with most web frameworks out of the box.\n *\n * Default behavior:\n * - Reads CSRF token from XSRF-TOKEN cookie\n * - Adds X-XSRF-TOKEN header to POST, PUT, PATCH, DELETE requests\n * - Skips GET/HEAD requests (they don't need CSRF protection)\n *\n * @param client - The FetchClient to add CSRF protection to\n * @param options - Optional CSRF configuration\n * @returns A new FetchClient with CSRF protection\n *\n * @example Basic usage (automatic cookie-based CSRF):\n * ```typescript\n * const client = new FetchClient();\n * const protectedClient = useCSRF(client);\n *\n * // CSRF token automatically added to POST requests\n * await protectedClient.post('/api/users', { name: 'John' });\n * ```\n *\n * @example Custom token provider:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * tokenProvider: () => localStorage.getItem('csrf-token') || ''\n * });\n * ```\n *\n * @example Custom header and cookie names:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * headerName: 'X-CSRF-Token',\n * cookieName: 'csrf-token'\n * });\n * ```\n *\n * @example Skip patterns for external APIs:\n * ```typescript\n * const protectedClient = useCSRF(client, {\n * skipPatterns: [\n * /^https:\\/\\/api\\.external\\.com\\//, // Skip external API\n * '/webhook/', // Skip webhook endpoints\n * '/public-api/' // Skip public API endpoints\n * ]\n * });\n * ```\n */\nexport function useCSRF(\n client: FetchClient,\n options: CSRFOptions = {},\n): FetchClient {\n return client.use(createCSRFMiddleware(options));\n}\n","/**\n * @fileoverview Logging middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { LoggingOptions, Logger, LogEntry, LogLevel } from './types';\n\n/**\n * Default console logger implementation.\n */\nconst defaultLogger: Logger = {\n // eslint-disable-next-line no-console -- allow console.debug in logger implementation\n debug: (message: string, data?: unknown) => console.debug(message, data),\n // eslint-disable-next-line no-console -- allow console.info in logger implementation\n info: (message: string, data?: unknown) => console.info(message, data),\n // eslint-disable-next-line no-console -- allow console.warn in logger implementation\n warn: (message: string, data?: unknown) => console.warn(message, data),\n // eslint-disable-next-line no-console -- allow console.error in logger implementation\n error: (message: string, data?: unknown) => console.error(message, data),\n};\n\n/**\n * Log level priority for filtering.\n */\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Default log formatter.\n */\nconst defaultFormatter = (entry: LogEntry): string => {\n const { method, url, status, duration } = entry;\n let message = `${method} ${url}`;\n\n if (status) {\n message += ` β†’ ${status}`;\n }\n\n if (duration) {\n message += ` (${duration}ms)`;\n }\n\n return message;\n};\n\n/**\n * Checks if a URL should skip logging based on configured patterns.\n */\nfunction shouldSkipLogging(\n url: string,\n skipPatterns: (RegExp | string)[] = [],\n): boolean {\n return skipPatterns.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return pattern.test(url);\n });\n}\n\n/**\n * Creates logging middleware with smart defaults.\n * Logs HTTP requests and responses for debugging and monitoring.\n *\n * @param options - Logging configuration options\n * @returns Logging middleware for use with FetchClient\n *\n * @example Basic logging:\n * ```typescript\n * const loggedClient = useLogging(client);\n * // Logs all requests to console\n * ```\n *\n * @example Custom logger:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * logger: winston.createLogger({...}),\n * level: 'debug',\n * includeRequestHeaders: true\n * });\n * ```\n */\nexport function createLoggingMiddleware(\n options: LoggingOptions = {},\n): FetchMiddleware {\n const {\n level = 'info',\n logger = defaultLogger,\n includeRequestHeaders = false,\n includeResponseHeaders = false,\n includeRequestBody = false,\n includeResponseBody = false,\n skipPatterns = [],\n formatter = defaultFormatter,\n } = options;\n\n const minLevel = LOG_LEVELS[level];\n\n return async (request, next) => {\n const url = request.url || '';\n const method = (request.method || 'GET').toUpperCase();\n\n // Skip logging if URL matches skip patterns\n if (shouldSkipLogging(url, skipPatterns)) {\n return next(request);\n }\n\n const startTime = Date.now();\n\n // Log request start (debug level)\n if (LOG_LEVELS.debug >= minLevel) {\n const requestHeaders = includeRequestHeaders\n ? getHeadersObject(\n request.headers as Headers | Record<string, string> | undefined,\n )\n : undefined;\n const requestBody = includeRequestBody ? request.body : undefined;\n\n const requestEntry: LogEntry = {\n level: 'debug',\n timestamp: startTime,\n method,\n url,\n ...(requestHeaders && { requestHeaders }),\n ...(requestBody && { requestBody }),\n };\n\n logger.debug(`β†’ ${formatter(requestEntry)}`, requestEntry);\n }\n\n try {\n const response = await next(request);\n const duration = Date.now() - startTime;\n\n // Determine log level based on response status\n const logLevel: LogLevel = response.status >= 400 ? 'error' : 'info';\n\n // Log response (info/error level)\n if (LOG_LEVELS[logLevel] >= minLevel) {\n const responseHeaders = includeResponseHeaders\n ? getHeadersObject(response.headers)\n : undefined;\n const responseBody = includeResponseBody ? response.data : undefined;\n\n const responseEntry: LogEntry = {\n level: logLevel,\n timestamp: Date.now(),\n method,\n url,\n status: response.status,\n duration,\n ...(responseHeaders ? { responseHeaders } : {}),\n ...(responseBody !== undefined ? { responseBody } : {}),\n };\n\n const logMessage = `← ${formatter(responseEntry)}`;\n\n if (logLevel === 'error') {\n logger.error(logMessage, responseEntry);\n } else {\n logger.info(logMessage, responseEntry);\n }\n }\n\n return response;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n // Log error\n if (LOG_LEVELS.error >= minLevel) {\n const errorEntry: LogEntry = {\n level: 'error',\n timestamp: Date.now(),\n method,\n url,\n duration,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n\n logger.error(`βœ— ${formatter(errorEntry)}`, errorEntry);\n }\n\n throw error;\n }\n };\n}\n\n/**\n * Convert Headers object to plain object.\n */\nfunction getHeadersObject(\n headers: Headers | Record<string, string> | undefined,\n): Record<string, string> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const obj: Record<string, string> = {};\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n obj[key] = value;\n });\n return obj;\n } else {\n // It's already a Record<string, string>\n return headers;\n }\n}\n","/**\n * @fileoverview Logging middleware - \"pit of success\" API.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { LoggingOptions } from './types';\nimport { createLoggingMiddleware } from './logging';\n\n// Re-export types for convenience\nexport type { LoggingOptions, Logger, LogEntry, LogLevel } from './types';\nexport { createLoggingMiddleware } from './logging';\n\n/**\n * \"Pit of success\" API for adding logging to a FetchClient.\n * Logs HTTP requests and responses for debugging and monitoring.\n *\n * @param client - The FetchClient to add logging to\n * @param options - Logging configuration options\n * @returns A new FetchClient with logging middleware\n *\n * @example Basic logging to console:\n * ```typescript\n * const loggedClient = useLogging(client);\n *\n * // Logs: β†’ GET /api/users\n * // Logs: ← GET /api/users β†’ 200 (245ms)\n * await loggedClient.get('/api/users');\n * ```\n *\n * @example Custom log level and headers:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * level: 'debug',\n * includeRequestHeaders: true,\n * includeResponseHeaders: true\n * });\n * ```\n *\n * @example Skip health check endpoints:\n * ```typescript\n * const loggedClient = useLogging(client, {\n * skipPatterns: ['/health', '/metrics', '/ping']\n * });\n * ```\n */\nexport function useLogging(\n client: FetchClient,\n options: LoggingOptions = {},\n): FetchClient {\n return client.use(createLoggingMiddleware(options));\n}\n","/**\n * @fileoverview Rate limiting middleware implementation.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { RateLimitOptions } from './types';\n\n/**\n * Simple token bucket implementation for rate limiting.\n */\nclass TokenBucket {\n private tokens: number;\n private lastRefill: number;\n\n constructor(\n private maxTokens: number,\n private refillRate: number, // tokens per millisecond\n private timeProvider: () => number = () => Date.now(),\n ) {\n this.tokens = maxTokens;\n this.lastRefill = this.timeProvider();\n }\n\n tryConsume(): { allowed: boolean; retryAfter?: number } {\n this.refill();\n\n if (this.tokens >= 1) {\n this.tokens--;\n return { allowed: true };\n }\n\n // Calculate when next token will be available\n const retryAfter = (1 - this.tokens) / this.refillRate;\n return { allowed: false, retryAfter: Math.ceil(retryAfter) };\n }\n\n private refill() {\n const now = this.timeProvider();\n const timePassed = now - this.lastRefill;\n const tokensToAdd = timePassed * this.refillRate;\n\n this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n this.lastRefill = now;\n }\n}\n\n/**\n * Creates rate limiting middleware - mainly for API quota management.\n * Note: Rate limiting is typically a server concern, but this can help with:\n * - Respecting API provider limits\n * - Preventing runaway requests in bulk operations\n * - Cost management for pay-per-request APIs\n */\nexport function createRateLimitMiddleware(\n options: RateLimitOptions = {},\n): FetchMiddleware {\n const {\n maxRequests = 60,\n windowMs = 60000,\n keyGenerator = () => 'default',\n skipPatterns = [],\n onRateLimitExceeded,\n } = options;\n\n const buckets = new Map<string, TokenBucket>();\n const refillRate = maxRequests / windowMs;\n\n return async (request, next) => {\n const url = request.url || '';\n\n // Skip rate limiting if URL matches skip patterns\n if (\n skipPatterns.some((pattern) =>\n typeof pattern === 'string' ? url.includes(pattern) : pattern.test(url),\n )\n ) {\n return next(request);\n }\n\n const key = keyGenerator(request);\n\n if (!buckets.has(key)) {\n buckets.set(key, new TokenBucket(maxRequests, refillRate));\n }\n\n const bucket = buckets.get(key)!;\n const result = bucket.tryConsume();\n\n if (!result.allowed) {\n if (onRateLimitExceeded) {\n const customResponse = await onRateLimitExceeded(\n result.retryAfter || 0,\n request,\n );\n // If the custom handler returns a response, use it\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return a 429 Too Many Requests response instead of throwing\n return {\n data: null,\n status: 429,\n statusText: 'Too Many Requests',\n headers: new Headers({\n 'Retry-After': Math.ceil((result.retryAfter || 0) / 1000).toString(),\n }),\n url: request.url || '',\n ok: false,\n error: {\n message: `Rate limit exceeded. Retry after ${result.retryAfter}ms`,\n body: { retryAfter: result.retryAfter },\n },\n };\n }\n\n return next(request);\n };\n}\n","/**\n * @fileoverview Rate limiting middleware - specialized use cases.\n */\n\nimport type { FetchClient } from '../../client/fetch-client';\nimport type { RateLimitOptions } from './types';\nimport { createRateLimitMiddleware } from './rate-limit';\n\n// Re-export types for convenience\nexport type { RateLimitOptions, RateLimitAlgorithm } from './types';\nexport { createRateLimitMiddleware } from './rate-limit';\n\n/**\n * Rate limiting middleware - mainly for API quota management.\n * Note: This is primarily useful for specific scenarios like:\n * - Respecting third-party API limits\n * - Bulk operations that need throttling\n * - Pay-per-request API cost management\n */\nexport function useRateLimit(\n client: FetchClient,\n options: RateLimitOptions = {},\n): FetchClient {\n return client.use(createRateLimitMiddleware(options));\n}\n","/**\n * @fileoverview Retry middleware implementation with enhanced architecture.\n */\n\nimport type { FetchMiddleware } from '../../client/fetch-client';\nimport type { FetchResponse } from '../../client/types';\nimport type { RetryOptions } from './types';\n\n/**\n * Default retry condition - retry on network errors and 5xx server errors.\n */\nconst defaultShouldRetry = (response: {\n status: number;\n ok: boolean;\n}): boolean => {\n // Network errors (status 0) or server errors (5xx)\n return (\n response.status === 0 || (response.status >= 500 && response.status < 600)\n );\n};\n\n/**\n * Calculate delay for retry attempt based on backoff strategy.\n */\nconst calculateDelay = (\n attempt: number,\n baseDelay: number,\n backoff: 'exponential' | 'linear' | 'fixed',\n maxDelay: number,\n): number => {\n let delay: number;\n\n switch (backoff) {\n case 'exponential':\n delay = baseDelay * Math.pow(2, attempt - 1);\n break;\n case 'linear':\n delay = baseDelay * attempt;\n break;\n case 'fixed':\n default:\n delay = baseDelay;\n break;\n }\n\n return Math.min(delay, maxDelay);\n};\n\n/**\n * Sleep for specified duration.\n */\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Creates a retry middleware with smart defaults.\n *\n * 🎯 PIT OF SUCCESS: Works great with no config, customizable when needed.\n *\n * Features:\n * - βœ… Preserves full middleware chain on retries (unlike old implementation)\n * - βœ… Exponential backoff with jitter\n * - βœ… Smart retry conditions (network errors + 5xx)\n * - βœ… Configurable but sensible defaults\n * - βœ… Type-safe configuration\n *\n * @param options - Retry configuration (all optional)\n * @returns Middleware function\n *\n * @example Basic usage:\n * ```typescript\n * const client = new FetchClient();\n * client.use(createRetryMiddleware()); // 3 retries with exponential backoff\n * ```\n *\n * @example Custom configuration:\n * ```typescript\n * const client = new FetchClient();\n * client.use(createRetryMiddleware({\n * maxRetries: 5,\n * delay: 500,\n * backoff: 'linear',\n * onRetry: (attempt, delay) => console.log(`Retry ${attempt} in ${delay}ms`)\n * }));\n * ```\n */\nexport function createRetryMiddleware(\n options: RetryOptions = {},\n): FetchMiddleware {\n const {\n maxRetries = 3,\n delay = 1000,\n backoff = 'exponential',\n maxDelay = 30000,\n shouldRetry = defaultShouldRetry,\n onRetry,\n } = options;\n\n return async (request, next) => {\n let lastResponse: FetchResponse<unknown>;\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n // Execute the request through the middleware chain\n const response = await next(request);\n\n // If successful, return immediately\n if (response.ok) {\n return response;\n }\n\n // Check if we should retry this response with current attempt count\n if (\n !shouldRetry(\n { status: response.status, ok: response.ok },\n attempt + 1,\n )\n ) {\n return response;\n }\n\n // If we've reached max retries, return the response\n if (attempt >= maxRetries) {\n return response;\n }\n\n // Store the failed response and increment attempt counter\n lastResponse = response;\n attempt++;\n\n // Calculate delay for next attempt\n const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);\n\n // Call onRetry callback if provided\n if (onRetry) {\n onRetry(attempt, retryDelay, {\n status: response.status,\n statusText: response.statusText,\n });\n }\n\n // Wait before retrying\n await sleep(retryDelay);\n } catch (error) {\n // Handle unexpected errors - treat as network error (status 0)\n const errorResponse: FetchResponse<unknown> = {\n data: null,\n status: 0,\n statusText: 'Network Error',\n headers: new Headers(),\n url: request.url || '',\n ok: false,\n error: {\n message: error instanceof Error ? error.message : 'Unknown error',\n body: error,\n },\n };\n\n // If shouldn't retry, return error immediately\n if (!shouldRetry(errorResponse, attempt + 1)) {\n return errorResponse;\n }\n\n // If we've reached max retries, return the error\n if (attempt >= maxRetries) {\n return errorResponse;\n }\n\n lastResponse = errorResponse;\n attempt++;\n\n // Calculate delay for next attempt\n const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);\n\n if (onRetry) {\n onRetry(attempt, retryDelay, {\n status: errorResponse.status,\n statusText: errorResponse.statusText,\n });\n }\n\n await sleep(retryDelay);\n }\n }\n\n // Return the last response if we've exhausted all retries\n return lastResponse!;\n };\n}\n","ο»Ώimport type { FetchClient } from '../../client/fetch-client';\nimport type { RetryOptions } from './types';\nimport { createRetryMiddleware } from './retry';\n\nexport type { RetryOptions } from './types';\nexport { createRetryMiddleware } from './retry';\n\nexport function useRetry(\n client: FetchClient,\n options: RetryOptions = {},\n): FetchClient {\n return client.use(createRetryMiddleware(options));\n}\n","/**\n * @fileoverview Complete middleware collection for FetchClient - \"pit of success\" APIs.\n *\n * This module provides a comprehensive set of middleware for common HTTP client concerns:\n * - πŸ” Authentication: Bearer token injection\n * - πŸ›‘οΈ Authorization: 401/403 response handling\n * - πŸ’Ύ Cache: Response caching with TTL\n * - πŸ”’ CSRF: Cross-site request forgery protection\n * - πŸ“ Logging: Request/response logging\n * - 🚦 Rate Limiting: Request rate limiting with token bucket\n * - πŸ”„ Retry: Automatic retry with backoff\n *\n * Each middleware follows the \"pit of success\" pattern with:\n * - Smart defaults for common scenarios\n * - Simple `use{Middleware}()` convenience functions\n * - Advanced `create{Middleware}Middleware()` for custom scenarios\n * - Comprehensive TypeScript support\n *\n * @example Quick setup with multiple middleware:\n * ```typescript\n * import { FetchClient } from '@fgrzl/fetch';\n * import { useAuthentication, useRetry, useLogging } from '@fgrzl/fetch/middleware';\n *\n * const client = new FetchClient();\n * const enhancedClient = useAuthentication(client, {\n * tokenProvider: () => localStorage.getItem('auth-token') || ''\n * })\n * .pipe(useRetry, { retries: 3 })\n * .pipe(useLogging);\n * ```\n */\n\n// πŸ” Authentication middleware\nexport type {\n AuthenticationOptions,\n AuthTokenProvider,\n} from './authentication';\n\nexport {\n useAuthentication,\n createAuthenticationMiddleware,\n} from './authentication';\n\n// πŸ›‘οΈ Authorization middleware\nexport type {\n AuthorizationOptions,\n UnauthorizedHandler,\n} from './authorization';\n\nexport {\n useAuthorization,\n createAuthorizationMiddleware,\n} from './authorization';\n\n// πŸ’Ύ Cache middleware\nexport type {\n CacheOptions,\n CacheStorage,\n CacheEntry,\n CacheKeyGenerator,\n} from './cache';\n\nexport { useCache, createCacheMiddleware } from './cache';\n\n// πŸ”’ CSRF middleware\nexport { useCSRF } from './csrf';\n\n// πŸ“ Logging middleware\nexport type { LoggingOptions, Logger, LogLevel } from './logging';\n\nexport { useLogging, createLoggingMiddleware } from './logging';\n\n// 🚦 Rate limiting middleware\nexport type { RateLimitOptions, RateLimitAlgorithm } from './rate-limit';\n\nexport { useRateLimit, createRateLimitMiddleware } from './rate-limit';\n\n// πŸ”„ Retry middleware\nexport type { RetryOptions } from './retry';\n\nexport { useRetry, createRetryMiddleware } from './retry';\n\n/**\n * Common middleware combinations for typical use cases.\n * These provide pre-configured middleware stacks for common scenarios.\n */\n\nimport type { FetchClient } from '../client/fetch-client';\nimport { useAuthentication } from './authentication';\nimport { useRetry } from './retry';\nimport { useLogging } from './logging';\nimport { useCache } from './cache';\nimport { useRateLimit } from './rate-limit';\n\n/**\n * Production-ready middleware stack with authentication, retry, logging, and caching.\n * Perfect for API clients that need reliability and observability.\n *\n * @param client - The FetchClient to enhance\n * @param config - Configuration for each middleware\n * @returns Enhanced FetchClient with production middleware stack\n *\n * @example\n * ```typescript\n * const apiClient = useProductionStack(new FetchClient(), {\n * auth: { tokenProvider: () => getAuthToken() },\n * cache: { ttl: 5 * 60 * 1000 }, // 5 minutes\n * logging: { level: 'info' }\n * });\n * ```\n */\nexport function useProductionStack(\n client: FetchClient,\n config: {\n auth?: Parameters<typeof useAuthentication>[1];\n retry?: Parameters<typeof useRetry>[1];\n cache?: Parameters<typeof useCache>[1];\n logging?: Parameters<typeof useLogging>[1];\n rateLimit?: Parameters<typeof useRateLimit>[1];\n } = {},\n): FetchClient {\n let enhanced = client;\n\n // Apply middleware in order: auth β†’ cache β†’ retry β†’ rate-limit β†’ logging\n if (config.auth) {\n enhanced = useAuthentication(enhanced, config.auth);\n }\n\n if (config.cache !== undefined) {\n enhanced = useCache(enhanced, config.cache);\n }\n\n if (config.retry !== undefined) {\n enhanced = useRetry(enhanced, config.retry);\n }\n\n if (config.rateLimit !== undefined) {\n enhanced = useRateLimit(enhanced, config.rateLimit);\n }\n\n if (config.logging !== undefined) {\n enhanced = useLogging(enhanced, config.logging);\n }\n\n return enhanced;\n}\n\n/**\n * Development-friendly middleware stack with comprehensive logging and retries.\n * Perfect for local development and debugging.\n *\n * @param client - The FetchClient to enhance\n * @param config - Configuration for development middleware\n * @returns Enhanced FetchClient with development middleware stack\n *\n * @example\n * ```typescript\n * const devClient = useDevelopmentStack(new FetchClient(), {\n * auth: { tokenProvider: () => 'dev-token' }\n * });\n * ```\n */\nexport function useDevelopmentStack(\n client: FetchClient,\n config: {\n auth?: Parameters<typeof useAuthentication>[1];\n } = {},\n): FetchClient {\n let enhanced = client;\n\n if (config.auth) {\n enhanced = useAuthentication(enhanced, config.auth);\n }\n\n // Development-optimized settings\n enhanced = useRetry(enhanced, {\n maxRetries: 1,\n delay: 100,\n });\n\n enhanced = useLogging(enhanced, {\n level: 'debug',\n includeRequestHeaders: true,\n includeResponseHeaders: true,\n includeRequestBody: true,\n includeResponseBody: true,\n });\n\n return enhanced;\n}\n\n/**\n * Basic middleware stack with just authentication and retry.\n * Perfect for simple API clients that need minimal overhead.\n *\n * @param client - The FetchClient to enhance\n * @param config - Basic configuration\n * @returns Enhanced FetchClient with basic middleware stack\n *\n * @example\n * ```typescript\n * const basicClient = useBasicStack(new FetchClient(), {\n * auth: { tokenProvider: () => getToken() }\n * });\n * ```\n */\nexport function useBasicStack(\n client: FetchClient,\n config: {\n auth: Parameters<typeof useAuthentication>[1];\n },\n): FetchClient {\n return useRetry(useAuthentication(client, config.auth), { maxRetries: 2 });\n}\n","/**\n * @fileoverview Custom error classes - \"Pit of Success\" pattern.\n *\n * 🎯 LEVEL 1: HttpError, NetworkError - Most common error types you'll catch\n * 🎯 LEVEL 2: FetchError - Base error class for advanced error handling\n *\n * @example\n * ```typescript\n * try {\n * await client.get('/api/data');\n * } catch (error) {\n * if (error instanceof HttpError) {\n * console.log(`HTTP ${error.status}: ${error.statusText}`);\n * } else if (error instanceof NetworkError) {\n * console.log('Network connection failed');\n * }\n * }\n * ```\n */\n\n// 🎯 LEVEL 2: Base error class (for advanced use cases)\n\n/**\n * Base error class for all fetch client errors.\n */\nexport class FetchError extends Error {\n /** Optional underlying cause */\n public readonly cause?: Error;\n\n /**\n * Creates a new FetchError.\n * @param message - Error message\n * @param cause - Optional underlying cause\n */\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'FetchError';\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n\n// 🎯 LEVEL 1: Most commonly used error types\n\n/**\n * Error thrown when an HTTP request fails with a non-2xx status code.\n */\nexport class HttpError extends FetchError {\n /** The HTTP status code */\n public readonly status: number;\n /** The HTTP status text */\n public readonly statusText: string;\n /** The response body (if available) */\n public readonly body: unknown;\n\n /**\n * Creates a new HttpError.\n * @param status - HTTP status code\n * @param statusText - HTTP status text\n * @param body - Response body\n * @param url - The request URL\n */\n constructor(status: number, statusText: string, body: unknown, url: string) {\n super(`HTTP ${status} ${statusText} at ${url}`);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.body = body;\n }\n}\n\n/**\n * Error thrown when a network request fails completely.\n */\nexport class NetworkError extends FetchError {\n /**\n * Creates a new NetworkError.\n * @param message - Error message\n * @param url - The request URL\n * @param cause - The underlying network error\n */\n constructor(message: string, url: string, cause?: Error) {\n super(`Network error for ${url}: ${message}`, cause);\n this.name = 'NetworkError';\n }\n}\n","/**\n * @fileoverview Query parameter utilities for FetchClient\n *\n * Provides utilities for building URL query strings from JavaScript objects\n * with proper handling of arrays, undefined values, and URL encoding.\n */\n\n/**\n * Query parameter value types that can be converted to URL parameters.\n * Arrays are handled specially with multiple parameter entries.\n */\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | QueryValue[];\n\n/**\n * Object representing query parameters for URL construction.\n */\nexport type QueryParams = Record<string, QueryValue>;\n\n/**\n * Builds a URL query string from a JavaScript object.\n *\n * Features:\n * - βœ… Proper URL encoding via native URLSearchParams\n * - βœ… Array handling with multiple parameter entries\n * - βœ… Undefined value filtering (excluded from output)\n * - βœ… Type coercion to strings for all values\n *\n * @param query - Object containing query parameters\n * @returns URL-encoded query string (without leading '?')\n *\n * @example Basic usage:\n * ```typescript\n * buildQueryParams({ name: 'John', age: 30 })\n * // β†’ \"name=John&age=30\"\n * ```\n *\n * @example Array handling:\n * ```typescript\n * buildQueryParams({ tags: ['typescript', 'javascript'], active: true })\n * // β†’ \"tags=typescript&tags=javascript&active=true\"\n * ```\n *\n * @example Undefined filtering:\n * ```typescript\n * buildQueryParams({ name: 'John', email: undefined, age: null })\n * // β†’ \"name=John&age=null\" (undefined excluded, null converted to string)\n * ```\n *\n * @example Real-world API usage:\n * ```typescript\n * const filters = {\n * status: ['active', 'pending'],\n * limit: 50,\n * offset: 0,\n * search: searchTerm || undefined // Conditionally included\n * };\n *\n * const queryString = buildQueryParams(filters);\n * // β†’ \"status=active&status=pending&limit=50&offset=0\"\n * // (search excluded if searchTerm is undefined)\n * ```\n */\nexport function buildQueryParams(query: QueryParams): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) {\n if (Array.isArray(value)) {\n // Handle arrays properly with multiple entries\n value.forEach((item) => {\n if (item !== undefined) {\n params.append(key, String(item));\n }\n });\n } else {\n params.set(key, String(value));\n }\n }\n }\n\n return params.toString();\n}\n\n/**\n * Appends query parameters to a URL, handling existing query strings properly.\n *\n * @param baseUrl - The base URL to append parameters to\n * @param query - Object containing query parameters\n * @returns Complete URL with query parameters appended\n *\n * @example Basic URL building:\n * ```typescript\n * appendQueryParams('/api/users', { limit: 10, active: true })\n * // β†’ \"/api/users?limit=10&active=true\"\n * ```\n *\n * @example Existing query parameters:\n * ```typescript\n * appendQueryParams('/api/users?sort=name', { limit: 10 })\n * // β†’ \"/api/users?sort=name&limit=10\"\n * ```\n *\n * @example Empty query object:\n * ```typescript\n * appendQueryParams('/api/users', {})\n * // β†’ \"/api/users\" (no change)\n * ```\n */\nexport function appendQueryParams(baseUrl: string, query: QueryParams): string {\n const queryString = buildQueryParams(query);\n\n if (!queryString) {\n return baseUrl;\n }\n\n // Handle URLs with fragments (hash)\n const fragmentIndex = baseUrl.indexOf('#');\n if (fragmentIndex !== -1) {\n const urlPart = baseUrl.substring(0, fragmentIndex);\n const fragmentPart = baseUrl.substring(fragmentIndex);\n const separator = urlPart.includes('?') ? '&' : '?';\n return `${urlPart}${separator}${queryString}${fragmentPart}`;\n }\n\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACuDO,IAAM,cAAN,MAAkB;AAAA,EAKvB,YAAY,SAA6B,CAAC,GAAG;AAJ7C,SAAQ,cAAiC,CAAC;AAKxC,SAAK,cAAc,OAAO,eAAe;AACzC,SAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EAEA,IAAI,YAAmC;AACrC,SAAK,YAAY,KAAK,UAAU;AAChC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,WAAW,SAAwB;AACjC,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QACJ,KACA,OAAoB,CAAC,GACM;AAE3B,UAAM,cAAc,KAAK,WAAW,GAAG;AAGvC,QAAI,QAAQ;AAEZ,UAAM,UAAU,OACd,YACoC;AAEpC,YAAM,iBAAiB,WAAW,EAAE,GAAG,MAAM,KAAK,YAAY;AAC9D,YAAM,aAAa,eAAe,OAAO;AAEzC,UAAI,SAAS,KAAK,YAAY,QAAQ;AAEpC,cAAM,EAAE,KAAK,GAAG,GAAG,YAAY,IAAI;AACnC,eAAO,KAAK,UAAU,aAAa,UAAU;AAAA,MAC/C;AAEA,YAAM,aAAa,KAAK,YAAY,OAAO;AAC3C,UAAI,CAAC,YAAY;AACf,cAAM,EAAE,KAAK,GAAG,GAAG,YAAY,IAAI;AACnC,eAAO,KAAK,UAAU,aAAa,UAAU;AAAA,MAC/C;AACA,aAAO,WAAW,gBAAgB,OAAO;AAAA,IAC3C;AAEA,UAAM,SAAS,MAAM,QAAQ;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,UACZ,SACA,KACiC;AACjC,QAAI;AACF,YAAM,YAAY;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,GAAG;AAAA,MACL;AAGA,UAAI,UAAU,mBAAmB,SAAS;AACxC,cAAM,aAAqC,CAAC;AAC5C,kBAAU,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACxC,qBAAW,GAAG,IAAI;AAAA,QACpB,CAAC;AACD,kBAAU,UAAU;AAAA,MACtB;AAEA,YAAM,WAAW,MAAM,MAAM,KAAK,SAAS;AAC3C,YAAM,OAAO,MAAM,KAAK,cAAc,QAAQ;AAE9C,aAAO;AAAA,QACL,MAAM,SAAS,KAAK,OAAO;AAAA,QAC3B,QAAQ,SAAS;AAAA,QACjB,YAAY,SAAS;AAAA,QACrB,SAAS,SAAS;AAAA,QAClB,KAAK,SAAS;AAAA,QACd,IAAI,SAAS;AAAA,QACb,GAAI,SAAS,KACT,CAAC,IACD;AAAA,UACE,OAAO;AAAA,YACL,SAAS,SAAS;AAAA,YAClB,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACN;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa,MAAM,QAAQ,SAAS,OAAO,GAAG;AACjE,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,SAAS,IAAI,QAAQ;AAAA,UACrB;AAAA,UACA,IAAI;AAAA,UACJ,OAAO;AAAA,YACL,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,KAAiC;AAC3D,UAAM,cAAc,IAAI,QAAQ,IAAI,cAAc,KAAK;AAEvD,QAAI,YAAY,SAAS,kBAAkB,GAAG;AAC5C,aAAO,IAAI,KAAK;AAAA,IAClB;AAEA,QAAI,YAAY,SAAS,OAAO,GAAG;AACjC,aAAO,IAAI,KAAK;AAAA,IAClB;AAEA,QACE,YAAY,SAAS,0BAA0B,KAC/C,YAAY,SAAS,QAAQ,KAC7B,YAAY,SAAS,QAAQ,KAC7B,YAAY,SAAS,QAAQ,GAC7B;AACA,aAAO,IAAI,KAAK;AAAA,IAClB;AAEA,QAAI,IAAI,MAAM;AACZ,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,aAAO,QAAQ;AAAA,IACjB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,mBACN,KACA,QACQ;AACR,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,KAAK,WAAW,GAAG;AAIvC,QACE,CAAC,YAAY,WAAW,SAAS,KACjC,CAAC,YAAY,WAAW,UAAU,KAClC,CAAC,YAAY,WAAW,IAAI,GAC5B;AACA,YAAM,eAAe,IAAI,gBAAgB;AACzC,aAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,uBAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,QACrC;AAAA,MACF,CAAC;AACD,YAAM,cAAc,aAAa,SAAS;AAC1C,aAAO,cAAc,GAAG,WAAW,IAAI,WAAW,KAAK;AAAA,IACzD;AAGA,UAAM,SAAS,IAAI,IAAI,WAAW;AAClC,WAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,UAAI,UAAU,UAAa,UAAU,MAAM;AACzC,eAAO,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,MAC5C;AAAA,IACF,CAAC;AAED,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,WAAW,KAAqB;AAEtC,QACE,IAAI,WAAW,SAAS,KACxB,IAAI,WAAW,UAAU,KACzB,IAAI,WAAW,IAAI,GACnB;AACA,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO;AAAA,IACT;AAGA,QAAI;AACF,YAAM,UAAU,IAAI,IAAI,KAAK,OAAO;AACpC,YAAM,cAAc,IAAI,IAAI,KAAK,OAAO;AACxC,aAAO,YAAY,SAAS;AAAA,IAC9B,QAAQ;AACN,YAAM,IAAI;AAAA,QACR,mCAAmC,GAAG,mBAAmB,KAAK,OAAO;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,KACE,KACA,QAC2B;AAC3B,UAAM,WAAW,KAAK,mBAAmB,KAAK,MAAM;AACpD,WAAO,KAAK,QAAW,UAAU,EAAE,QAAQ,OAAO,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,aACJ,KACA,QAUA;AACA,UAAM,WAAW,MAAM,KAAK,KAAK,KAAK,MAAM;AAE5C,UAAM,sBAAsB,SAAS,QAAQ,IAAI,gBAAgB;AACjE,UAAM,qBAAqB,SAAS,QAAQ,IAAI,eAAe;AAE/D,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,aAAa,SAAS,QAAQ,IAAI,cAAc,KAAK;AAAA,MACrD,eAAe,sBACX,SAAS,qBAAqB,EAAE,IAChC;AAAA,MACJ,cAAc,qBACV,IAAI,KAAK,kBAAkB,IAC3B;AAAA,MACJ,MAAM,SAAS,QAAQ,IAAI,MAAM,KAAK;AAAA,MACtC,cAAc,SAAS,QAAQ,IAAI,eAAe,KAAK;AAAA,IACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,IACE,KACA,QAC2B;AAC3B,UAAM,WAAW,KAAK,mBAAmB,KAAK,MAAM;AACpD,WAAO,KAAK,QAAW,UAAU,EAAE,QAAQ,MAAM,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,KACE,KACA,MACA,SAC2B;AAC3B,UAAM,iBAAiB;AAAA,MACrB,gBAAgB;AAAA,MAChB,GAAI,WAAW,CAAC;AAAA,IAClB;AAEA,WAAO,KAAK,QAAW,KAAK;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,GAAI,SAAS,SAAY,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IACE,KACA,MACA,SAC2B;AAC3B,UAAM,iBAAiB;AAAA,MACrB,gBAAgB;AAAA,MAChB,GAAI,WAAW,CAAC;AAAA,IAClB;AAEA,WAAO,KAAK,QAAW,KAAK;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,GAAI,SAAS,SAAY,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MACE,KACA,MACA,SAC2B;AAC3B,UAAM,iBAAiB;AAAA,MACrB,gBAAgB;AAAA,MAChB,GAAI,WAAW,CAAC;AAAA,IAClB;AAEA,WAAO,KAAK,QAAW,KAAK;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,GAAI,SAAS,SAAY,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,IACE,KACA,QAC2B;AAC3B,UAAM,WAAW,KAAK,mBAAmB,KAAK,MAAM;AACpD,WAAO,KAAK,QAAW,UAAU,EAAE,QAAQ,SAAS,CAAC;AAAA,EACvD;AACF;;;ACtfA,SAAS,eACP,KACA,eAAoC,CAAC,GAC5B;AACT,SAAO,aAAa,KAAK,CAAC,YAAY;AACpC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,SAAS,OAAO;AAAA,IAC7B;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB,CAAC;AACH;AAKA,SAAS,kBACP,KACA,iBACS;AACT,MAAI,CAAC,mBAAmB,gBAAgB,WAAW,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,SAAO,gBAAgB,KAAK,CAAC,YAAY;AACvC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,SAAS,OAAO;AAAA,IAC7B;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB,CAAC;AACH;AA0BO,SAAS,+BACd,SACiB;AACjB,QAAM;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,eAAe,CAAC;AAAA,IAChB;AAAA,EACF,IAAI;AAEJ,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,MAAM,QAAQ,OAAO;AAC3B,UAAM,YAAY,IAAI,IAAI,GAAG;AAC7B,UAAM,WAAW,UAAU;AAK3B,QACE,eAAe,UAAU,YAAY,KACrC,CAAC,kBAAkB,UAAU,eAAe,GAC5C;AACA,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,QAAI;AAEF,YAAM,QAAQ,MAAM,cAAc;AAGlC,UAAI,CAAC,OAAO;AACV,eAAO,KAAK,OAAO;AAAA,MACrB;AAGA,YAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,cAAQ,IAAI,YAAY,GAAG,SAAS,IAAI,KAAK,EAAE;AAG/C,YAAM,kBAAkB;AAAA,QACtB,GAAG;AAAA,QACH;AAAA,MACF;AAEA,aAAO,KAAK,eAAe;AAAA,IAC7B,QAAQ;AAGN,aAAO,KAAK,OAAO;AAAA,IACrB;AAAA,EACF;AACF;;;AC7EO,SAAS,kBACd,QACA,SACa;AACb,SAAO,OAAO,IAAI,+BAA+B,OAAO,CAAC;AAC3D;;;AC9BA,SAAS,sBAAsB,SAAsC,CAAC,GAAG;AACvE,QAAM;AAAA,IACJ,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,EACrB,IAAI;AAEJ,SAAO,MAAM;AACX,QAAI,cAAc;AAElB,QAAI,oBAAoB,OAAO,WAAW,aAAa;AACrD,YAAM,aAAa,mBAAmB,OAAO,SAAS,IAAI;AAC1D,YAAM,YAAY,aAAa,SAAS,GAAG,IAAI,MAAM;AACrD,oBAAc,GAAG,YAAY,GAAG,SAAS,GAAG,cAAc,IAAI,UAAU;AAAA,IAC1E;AAEA,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACF;AACF;AAMA,SAAS,0BACP,iBACA,gBACqB;AACrB,MAAI,iBAAiB;AACnB,WAAO;AAAA,EACT;AAEA,SAAO,sBAAsB,cAAc;AAC7C;AAKA,SAASA,gBACP,KACA,eAAoC,CAAC,GAC5B;AAET,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,IAAI,GAAG,EAAE;AAAA,EAC1B,QAAQ;AACN,eAAW;AAAA,EACb;AAEA,SAAO,aAAa,KAAK,CAAC,YAAY;AACpC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,SAAS,SAAS,OAAO;AAAA,IAClC;AACA,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC9B,CAAC;AACH;AAwCO,SAAS,8BACd,UAAgC,CAAC,GAChB;AACjB,QAAM;AAAA,IACJ,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,eAAe,CAAC;AAAA,IAChB,cAAc,CAAC,GAAG;AAAA,EACpB,IAAI;AAEJ,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AAEA,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,MAAM,QAAQ,OAAO;AAG3B,QAAIA,gBAAe,KAAK,YAAY,GAAG;AACrC,aAAO,KAAK,OAAO;AAAA,IACrB;AAGA,UAAM,WAAW,MAAM,KAAK,OAAO;AAGnC,QAAI,YAAY,SAAS,SAAS,MAAM,GAAG;AACzC,UAAI;AACF,YAAI,SAAS,WAAW,OAAO,gBAAgB;AAC7C,gBAAM,eAAe,UAAU,OAAO;AAAA,QACxC,WAAW,SAAS,WAAW,OAAO,aAAa;AACjD,gBAAM,YAAY,UAAU,OAAO;AAAA,QACrC,WAAW,gBAAgB;AAEzB,gBAAM,eAAe,UAAU,OAAO;AAAA,QACxC;AAAA,MACF,SAAS,OAAO;AAGd,gBAAQ,KAAK,iCAAiC,KAAK;AAAA,MACrD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACzGO,SAAS,iBACd,QACA,UAAgC,CAAC,GACpB;AACb,SAAO,OAAO,IAAI,8BAA8B,OAAO,CAAC;AAC1D;;;AC5CO,IAAM,gBAAN,MAA4C;AAAA,EAA5C;AACL,SAAQ,QAAQ,oBAAI,IAAwB;AAAA;AAAA,EAE5C,MAAM,IAAI,KAAyC;AACjD,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,IAAI,IAAI,MAAM,WAAW;AAChC,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cACJ,KAC2D;AAC3D,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,OAAO,MAAM,WAAW,MAAM;AAAA,IACzC;AAEA,UAAM,YAAY,KAAK,IAAI,IAAI,MAAM;AAErC,WAAO,EAAE,OAAO,UAAU;AAAA,EAC5B;AAAA,EAEA,MAAM,IAAI,KAAa,OAAkC;AACvD,SAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAC3B;AAAA,EAEA,MAAM,OAAO,KAA4B;AACvC,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;AAKA,IAAM,sBAAyC,CAAC,YAAY;AAC1D,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,UAAU,QAAQ,UAAU,KAAK,UAAU,QAAQ,OAAO,IAAI;AACpE,SAAO,GAAG,MAAM,IAAI,GAAG,IAAI,OAAO;AACpC;AAKA,SAAS,gBACP,KACA,eAAoC,CAAC,GAC5B;AACT,SAAO,aAAa,KAAK,CAAC,YAAY;AACpC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,SAAS,OAAO;AAAA,IAC7B;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB,CAAC;AACH;AAsBO,SAAS,sBACd,UAAwB,CAAC,GACR;AACjB,QAAM;AAAA,IACJ,MAAM,IAAI,KAAK;AAAA;AAAA,IACf,UAAU,CAAC,KAAK;AAAA,IAChB,UAAU,IAAI,cAAc;AAAA,IAC5B,eAAe;AAAA,IACf,eAAe,CAAC;AAAA,IAChB,uBAAuB;AAAA,EACzB,IAAI;AAEJ,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AACrD,UAAM,MAAM,QAAQ,OAAO;AAK3B,QAAI,CAAC,QAAQ,SAAS,MAAM,KAAK,gBAAgB,KAAK,YAAY,GAAG;AACnE,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,WAAW,aAAa,OAAO;AAErC,QAAI;AAEF,YAAM,EAAE,OAAO,QAAQ,UAAU,IAAI,QAAQ,gBACzC,MAAM,QAAQ,cAAc,QAAQ,IACpC,OAAO,YAAY;AACjB,cAAM,QAAQ,MAAM,QAAQ,IAAI,QAAQ;AACxC,eAAO,EAAE,OAAO,WAAW,MAAM;AAAA,MACnC,GAAG;AAEP,UAAI,UAAU,CAAC,WAAW;AAExB,eAAO;AAAA,UACL,GAAG,OAAO;AAAA,UACV,SAAS,IAAI,QAAQ,OAAO,SAAS,OAAO;AAAA,UAC5C,MAAM,OAAO,SAAS;AAAA,QACxB;AAAA,MACF;AAIA,UAAI,UAAU,sBAAsB;AAElC,cAAM,iBAAiB;AAAA,UACrB,GAAG,OAAO;AAAA,UACV,SAAS,IAAI,QAAQ,OAAO,SAAS,OAAO;AAAA,UAC5C,MAAM,OAAO,SAAS;AAAA,QACxB;AAGA,YAAI,WAAW;AACb,eAAK,OAAO,EACT,KAAK,OAAO,kBAAkB;AAC7B,kBAAM,aAAqC,CAAC;AAC5C,0BAAc,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC5C,yBAAW,GAAG,IAAI;AAAA,YACpB,CAAC;AAED,kBAAM,aAAyB;AAAA,cAC7B,UAAU;AAAA,gBACR,QAAQ,cAAc;AAAA,gBACtB,YAAY,cAAc;AAAA,gBAC1B,SAAS;AAAA,gBACT,MAAM,cAAc;AAAA,cACtB;AAAA,cACA,WAAW,KAAK,IAAI;AAAA,cACpB,WAAW,KAAK,IAAI,IAAI;AAAA,YAC1B;AACA,kBAAM,QAAQ,IAAI,UAAU,UAAU;AAAA,UACxC,CAAC,EACA,MAAM,MAAM;AAAA,UAEb,CAAC;AAAA,QACL;AAEA,eAAO;AAAA,MACT;AAGA,YAAM,WAAW,MAAM,KAAK,OAAO;AAGnC,UAAI,SAAS,IAAI;AACf,YAAI;AACF,gBAAM,aAAqC,CAAC;AAC5C,mBAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACvC,uBAAW,GAAG,IAAI;AAAA,UACpB,CAAC;AAED,gBAAM,aAAyB;AAAA,YAC7B,UAAU;AAAA,cACR,QAAQ,SAAS;AAAA,cACjB,YAAY,SAAS;AAAA,cACrB,SAAS;AAAA,cACT,MAAM,SAAS;AAAA,YACjB;AAAA,YACA,WAAW,KAAK,IAAI;AAAA,YACpB,WAAW,KAAK,IAAI,IAAI;AAAA,UAC1B;AAEA,gBAAM,QAAQ,IAAI,UAAU,UAAU;AAAA,QACxC,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,UAAI,SAAS,OAAO,UAAU,YAAY,aAAa,OAAO;AAC5D,cAAM,eAAgB,MAA8B;AACpD,YACE,aAAa,SAAS,SAAS,KAC/B,aAAa,SAAS,OAAO,GAC7B;AACA,gBAAM;AAAA,QACR;AAAA,MACF;AAGA,aAAO,KAAK,OAAO;AAAA,IACrB;AAAA,EACF;AACF;;;ACpLO,SAAS,SACd,QACA,UAAwB,CAAC,GACZ;AACb,SAAO,OAAO,IAAI,sBAAsB,OAAO,CAAC;AAClD;;;AC9CA,SAAS,mBAAmB,aAAqB,cAAsB;AACrE,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,GAAG,UAAU;AAC1B,QAAM,gBAAgB,mBAAmB,SAAS,MAAM;AACxD,QAAM,UAAU,cAAc,MAAM,GAAG;AAEvC,aAAW,UAAU,SAAS;AAC5B,UAAM,IAAI,OAAO,KAAK;AACtB,QAAI,EAAE,QAAQ,IAAI,MAAM,GAAG;AACzB,aAAO,EAAE,UAAU,KAAK,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,eACP,KACA,eAAoC,CAAC,GAC5B;AACT,SAAO,aAAa,KAAK,CAAC,YAAY;AACpC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,SAAS,OAAO;AAAA,IAC7B;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB,CAAC;AACH;AA6BO,SAAS,qBACd,UAAuB,CAAC,GACP;AAEjB,QAAM;AAAA,IACJ,aAAa;AAAA,IACb,aAAa;AAAA,IACb,mBAAmB,CAAC,QAAQ,OAAO,SAAS,QAAQ;AAAA,IACpD,eAAe,CAAC;AAAA,IAChB,gBAAgB,MAAM,mBAAmB,UAAU;AAAA,EACrD,IAAI;AAEJ,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AACrD,UAAM,MAAM,QAAQ,OAAO;AAK3B,QACE,CAAC,iBAAiB,SAAS,MAAM,KACjC,eAAe,KAAK,YAAY,GAChC;AACA,aAAO,KAAK,OAAO;AAAA,IACrB;AAGA,UAAM,QAAQ,cAAc;AAG5B,QAAI,CAAC,OAAO;AACV,aAAO,KAAK,OAAO;AAAA,IACrB;AAGA,UAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,YAAQ,IAAI,YAAY,KAAK;AAG7B,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH;AAAA,IACF;AAEA,WAAO,KAAK,eAAe;AAAA,EAC7B;AACF;;;AC1DO,SAAS,QACd,QACA,UAAuB,CAAC,GACX;AACb,SAAO,OAAO,IAAI,qBAAqB,OAAO,CAAC;AACjD;;;ACvDA,IAAM,gBAAwB;AAAA;AAAA,EAE5B,OAAO,CAAC,SAAiB,SAAmB,QAAQ,MAAM,SAAS,IAAI;AAAA;AAAA,EAEvE,MAAM,CAAC,SAAiB,SAAmB,QAAQ,KAAK,SAAS,IAAI;AAAA;AAAA,EAErE,MAAM,CAAC,SAAiB,SAAmB,QAAQ,KAAK,SAAS,IAAI;AAAA;AAAA,EAErE,OAAO,CAAC,SAAiB,SAAmB,QAAQ,MAAM,SAAS,IAAI;AACzE;AAKA,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAKA,IAAM,mBAAmB,CAAC,UAA4B;AACpD,QAAM,EAAE,QAAQ,KAAK,QAAQ,SAAS,IAAI;AAC1C,MAAI,UAAU,GAAG,MAAM,IAAI,GAAG;AAE9B,MAAI,QAAQ;AACV,eAAW,WAAM,MAAM;AAAA,EACzB;AAEA,MAAI,UAAU;AACZ,eAAW,KAAK,QAAQ;AAAA,EAC1B;AAEA,SAAO;AACT;AAKA,SAAS,kBACP,KACA,eAAoC,CAAC,GAC5B;AACT,SAAO,aAAa,KAAK,CAAC,YAAY;AACpC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,SAAS,OAAO;AAAA,IAC7B;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB,CAAC;AACH;AAwBO,SAAS,wBACd,UAA0B,CAAC,GACV;AACjB,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,wBAAwB;AAAA,IACxB,yBAAyB;AAAA,IACzB,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,eAAe,CAAC;AAAA,IAChB,YAAY;AAAA,EACd,IAAI;AAEJ,QAAM,WAAW,WAAW,KAAK;AAEjC,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,MAAM,QAAQ,OAAO;AAC3B,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AAGrD,QAAI,kBAAkB,KAAK,YAAY,GAAG;AACxC,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,YAAY,KAAK,IAAI;AAG3B,QAAI,WAAW,SAAS,UAAU;AAChC,YAAM,iBAAiB,wBACnB;AAAA,QACE,QAAQ;AAAA,MACV,IACA;AACJ,YAAM,cAAc,qBAAqB,QAAQ,OAAO;AAExD,YAAM,eAAyB;AAAA,QAC7B,OAAO;AAAA,QACP,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,GAAI,kBAAkB,EAAE,eAAe;AAAA,QACvC,GAAI,eAAe,EAAE,YAAY;AAAA,MACnC;AAEA,aAAO,MAAM,UAAK,UAAU,YAAY,CAAC,IAAI,YAAY;AAAA,IAC3D;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,OAAO;AACnC,YAAM,WAAW,KAAK,IAAI,IAAI;AAG9B,YAAM,WAAqB,SAAS,UAAU,MAAM,UAAU;AAG9D,UAAI,WAAW,QAAQ,KAAK,UAAU;AACpC,cAAM,kBAAkB,yBACpB,iBAAiB,SAAS,OAAO,IACjC;AACJ,cAAM,eAAe,sBAAsB,SAAS,OAAO;AAE3D,cAAM,gBAA0B;AAAA,UAC9B,OAAO;AAAA,UACP,WAAW,KAAK,IAAI;AAAA,UACpB;AAAA,UACA;AAAA,UACA,QAAQ,SAAS;AAAA,UACjB;AAAA,UACA,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,UAC7C,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,QACvD;AAEA,cAAM,aAAa,UAAK,UAAU,aAAa,CAAC;AAEhD,YAAI,aAAa,SAAS;AACxB,iBAAO,MAAM,YAAY,aAAa;AAAA,QACxC,OAAO;AACL,iBAAO,KAAK,YAAY,aAAa;AAAA,QACvC;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,WAAW,KAAK,IAAI,IAAI;AAG9B,UAAI,WAAW,SAAS,UAAU;AAChC,cAAM,aAAuB;AAAA,UAC3B,OAAO;AAAA,UACP,WAAW,KAAK,IAAI;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,UACA,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,QACjE;AAEA,eAAO,MAAM,UAAK,UAAU,UAAU,CAAC,IAAI,UAAU;AAAA,MACvD;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAKA,SAAS,iBACP,SACoC;AACpC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,MAA8B,CAAC;AAErC,MAAI,mBAAmB,SAAS;AAC9B,YAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,UAAI,GAAG,IAAI;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACT,OAAO;AAEL,WAAO;AAAA,EACT;AACF;;;ACvKO,SAAS,WACd,QACA,UAA0B,CAAC,GACd;AACb,SAAO,OAAO,IAAI,wBAAwB,OAAO,CAAC;AACpD;;;ACxCA,IAAM,cAAN,MAAkB;AAAA,EAIhB,YACU,WACA,YACA,eAA6B,MAAM,KAAK,IAAI,GACpD;AAHQ;AACA;AACA;AAER,SAAK,SAAS;AACd,SAAK,aAAa,KAAK,aAAa;AAAA,EACtC;AAAA,EAEA,aAAwD;AACtD,SAAK,OAAO;AAEZ,QAAI,KAAK,UAAU,GAAG;AACpB,WAAK;AACL,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAGA,UAAM,cAAc,IAAI,KAAK,UAAU,KAAK;AAC5C,WAAO,EAAE,SAAS,OAAO,YAAY,KAAK,KAAK,UAAU,EAAE;AAAA,EAC7D;AAAA,EAEQ,SAAS;AACf,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,aAAa,MAAM,KAAK;AAC9B,UAAM,cAAc,aAAa,KAAK;AAEtC,SAAK,SAAS,KAAK,IAAI,KAAK,WAAW,KAAK,SAAS,WAAW;AAChE,SAAK,aAAa;AAAA,EACpB;AACF;AASO,SAAS,0BACd,UAA4B,CAAC,GACZ;AACjB,QAAM;AAAA,IACJ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,eAAe,MAAM;AAAA,IACrB,eAAe,CAAC;AAAA,IAChB;AAAA,EACF,IAAI;AAEJ,QAAM,UAAU,oBAAI,IAAyB;AAC7C,QAAM,aAAa,cAAc;AAEjC,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,MAAM,QAAQ,OAAO;AAG3B,QACE,aAAa;AAAA,MAAK,CAAC,YACjB,OAAO,YAAY,WAAW,IAAI,SAAS,OAAO,IAAI,QAAQ,KAAK,GAAG;AAAA,IACxE,GACA;AACA,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,MAAM,aAAa,OAAO;AAEhC,QAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,cAAQ,IAAI,KAAK,IAAI,YAAY,aAAa,UAAU,CAAC;AAAA,IAC3D;AAEA,UAAM,SAAS,QAAQ,IAAI,GAAG;AAC9B,UAAM,SAAS,OAAO,WAAW;AAEjC,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI,qBAAqB;AACvB,cAAM,iBAAiB,MAAM;AAAA,UAC3B,OAAO,cAAc;AAAA,UACrB;AAAA,QACF;AAEA,YAAI,gBAAgB;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AAGA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS,IAAI,QAAQ;AAAA,UACnB,eAAe,KAAK,MAAM,OAAO,cAAc,KAAK,GAAI,EAAE,SAAS;AAAA,QACrE,CAAC;AAAA,QACD,KAAK,QAAQ,OAAO;AAAA,QACpB,IAAI;AAAA,QACJ,OAAO;AAAA,UACL,SAAS,oCAAoC,OAAO,UAAU;AAAA,UAC9D,MAAM,EAAE,YAAY,OAAO,WAAW;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;;;ACpGO,SAAS,aACd,QACA,UAA4B,CAAC,GAChB;AACb,SAAO,OAAO,IAAI,0BAA0B,OAAO,CAAC;AACtD;;;ACbA,IAAM,qBAAqB,CAAC,aAGb;AAEb,SACE,SAAS,WAAW,KAAM,SAAS,UAAU,OAAO,SAAS,SAAS;AAE1E;AAKA,IAAM,iBAAiB,CACrB,SACA,WACA,SACA,aACW;AACX,MAAI;AAEJ,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,cAAQ,YAAY,KAAK,IAAI,GAAG,UAAU,CAAC;AAC3C;AAAA,IACF,KAAK;AACH,cAAQ,YAAY;AACpB;AAAA,IACF,KAAK;AAAA,IACL;AACE,cAAQ;AACR;AAAA,EACJ;AAEA,SAAO,KAAK,IAAI,OAAO,QAAQ;AACjC;AAKA,IAAM,QAAQ,CAAC,OACb,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAkC3C,SAAS,sBACd,UAAwB,CAAC,GACR;AACjB,QAAM;AAAA,IACJ,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,IACd;AAAA,EACF,IAAI;AAEJ,SAAO,OAAO,SAAS,SAAS;AAC9B,QAAI;AACJ,QAAI,UAAU;AAEd,WAAO,WAAW,YAAY;AAC5B,UAAI;AAEF,cAAM,WAAW,MAAM,KAAK,OAAO;AAGnC,YAAI,SAAS,IAAI;AACf,iBAAO;AAAA,QACT;AAGA,YACE,CAAC;AAAA,UACC,EAAE,QAAQ,SAAS,QAAQ,IAAI,SAAS,GAAG;AAAA,UAC3C,UAAU;AAAA,QACZ,GACA;AACA,iBAAO;AAAA,QACT;AAGA,YAAI,WAAW,YAAY;AACzB,iBAAO;AAAA,QACT;AAGA,uBAAe;AACf;AAGA,cAAM,aAAa,eAAe,SAAS,OAAO,SAAS,QAAQ;AAGnE,YAAI,SAAS;AACX,kBAAQ,SAAS,YAAY;AAAA,YAC3B,QAAQ,SAAS;AAAA,YACjB,YAAY,SAAS;AAAA,UACvB,CAAC;AAAA,QACH;AAGA,cAAM,MAAM,UAAU;AAAA,MACxB,SAAS,OAAO;AAEd,cAAM,gBAAwC;AAAA,UAC5C,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,SAAS,IAAI,QAAQ;AAAA,UACrB,KAAK,QAAQ,OAAO;AAAA,UACpB,IAAI;AAAA,UACJ,OAAO;AAAA,YACL,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,YAClD,MAAM;AAAA,UACR;AAAA,QACF;AAGA,YAAI,CAAC,YAAY,eAAe,UAAU,CAAC,GAAG;AAC5C,iBAAO;AAAA,QACT;AAGA,YAAI,WAAW,YAAY;AACzB,iBAAO;AAAA,QACT;AAEA,uBAAe;AACf;AAGA,cAAM,aAAa,eAAe,SAAS,OAAO,SAAS,QAAQ;AAEnE,YAAI,SAAS;AACX,kBAAQ,SAAS,YAAY;AAAA,YAC3B,QAAQ,cAAc;AAAA,YACtB,YAAY,cAAc;AAAA,UAC5B,CAAC;AAAA,QACH;AAEA,cAAM,MAAM,UAAU;AAAA,MACxB;AAAA,IACF;AAGA,WAAO;AAAA,EACT;AACF;;;ACtLO,SAAS,SACd,QACA,UAAwB,CAAC,GACZ;AACb,SAAO,OAAO,IAAI,sBAAsB,OAAO,CAAC;AAClD;;;ACmGO,SAAS,mBACd,QACA,SAMI,CAAC,GACQ;AACb,MAAI,WAAW;AAGf,MAAI,OAAO,MAAM;AACf,eAAW,kBAAkB,UAAU,OAAO,IAAI;AAAA,EACpD;AAEA,MAAI,OAAO,UAAU,QAAW;AAC9B,eAAW,SAAS,UAAU,OAAO,KAAK;AAAA,EAC5C;AAEA,MAAI,OAAO,UAAU,QAAW;AAC9B,eAAW,SAAS,UAAU,OAAO,KAAK;AAAA,EAC5C;AAEA,MAAI,OAAO,cAAc,QAAW;AAClC,eAAW,aAAa,UAAU,OAAO,SAAS;AAAA,EACpD;AAEA,MAAI,OAAO,YAAY,QAAW;AAChC,eAAW,WAAW,UAAU,OAAO,OAAO;AAAA,EAChD;AAEA,SAAO;AACT;AAiBO,SAAS,oBACd,QACA,SAEI,CAAC,GACQ;AACb,MAAI,WAAW;AAEf,MAAI,OAAO,MAAM;AACf,eAAW,kBAAkB,UAAU,OAAO,IAAI;AAAA,EACpD;AAGA,aAAW,SAAS,UAAU;AAAA,IAC5B,YAAY;AAAA,IACZ,OAAO;AAAA,EACT,CAAC;AAED,aAAW,WAAW,UAAU;AAAA,IAC9B,OAAO;AAAA,IACP,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,EACvB,CAAC;AAED,SAAO;AACT;AAiBO,SAAS,cACd,QACA,QAGa;AACb,SAAO,SAAS,kBAAkB,QAAQ,OAAO,IAAI,GAAG,EAAE,YAAY,EAAE,CAAC;AAC3E;;;AC5LO,IAAM,aAAN,cAAyB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpC,YAAY,SAAiB,OAAe;AAC1C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,QAAI,UAAU,QAAW;AACvB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;AAOO,IAAM,YAAN,cAAwB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAexC,YAAY,QAAgB,YAAoB,MAAe,KAAa;AAC1E,UAAM,QAAQ,MAAM,IAAI,UAAU,OAAO,GAAG,EAAE;AAC9C,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,eAAN,cAA2B,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3C,YAAY,SAAiB,KAAa,OAAe;AACvD,UAAM,qBAAqB,GAAG,KAAK,OAAO,IAAI,KAAK;AACnD,SAAK,OAAO;AAAA,EACd;AACF;;;AClBO,SAAS,iBAAiB,OAA4B;AAC3D,QAAM,SAAS,IAAI,gBAAgB;AAEnC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,UAAU,QAAW;AACvB,UAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,cAAM,QAAQ,CAAC,SAAS;AACtB,cAAI,SAAS,QAAW;AACtB,mBAAO,OAAO,KAAK,OAAO,IAAI,CAAC;AAAA,UACjC;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,eAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,SAAS;AACzB;AA2BO,SAAS,kBAAkB,SAAiB,OAA4B;AAC7E,QAAM,cAAc,iBAAiB,KAAK;AAE1C,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB,QAAQ,QAAQ,GAAG;AACzC,MAAI,kBAAkB,IAAI;AACxB,UAAM,UAAU,QAAQ,UAAU,GAAG,aAAa;AAClD,UAAM,eAAe,QAAQ,UAAU,aAAa;AACpD,UAAMC,aAAY,QAAQ,SAAS,GAAG,IAAI,MAAM;AAChD,WAAO,GAAG,OAAO,GAAGA,UAAS,GAAG,WAAW,GAAG,YAAY;AAAA,EAC5D;AAEA,QAAM,YAAY,QAAQ,SAAS,GAAG,IAAI,MAAM;AAChD,SAAO,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW;AAC7C;;;AlB/CA,IAAM,MAAM;AAAA,EACV,IAAI,YAAY;AAAA;AAAA;AAAA,IAGd,aAAa;AAAA,EACf,CAAC;AAAA,EACD;AAAA;AAAA,IAEE,OAAO;AAAA,MACL,YAAY;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,MACL,KAAK,IAAI,KAAK;AAAA;AAAA,MACd,SAAS,CAAC,KAAK;AAAA,IACjB;AAAA,IACA,SAAS;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,MACT,aAAa;AAAA,MACb,UAAU,KAAK;AAAA;AAAA,IACjB;AAAA,EACF;AACF;AAGA,IAAO,gBAAQ;","names":["shouldSkipAuth","separator"]}