{"version":3,"file":"fetch-B_MCWy66.cjs","names":[],"sources":["../src/fetch/fetch.ts","../src/fetch/middlewareAttachAccessToken.ts","../src/fetch/middlewareSessionRefresh.ts","../src/fetch/middlewareUpdateSessionFromResponse.ts","../src/fetch/middlewareWithAdminSession.ts","../src/fetch/middlewareWithHeaders.ts","../src/fetch/middlewareWithRole.ts"],"sourcesContent":["/**\n * Type definition for a fetch-like function.\n * Takes the same parameters as fetch and returns the same type.\n * This allows middleware to intercept and modify requests and responses.\n */\nexport type FetchFunction = (\n  url: string,\n  options?: RequestInit,\n) => Promise<Response>;\n\n/**\n * Type definition for a chain function (middleware).\n * Takes a fetch-like function and returns another fetch-like function.\n *\n * Chain functions can be used to implement:\n * - Authentication token handling\n * - Error handling and retry logic\n * - Request and response transformations\n * - Logging and metrics\n */\nexport type ChainFunction = (next: FetchFunction) => FetchFunction;\n\n/**\n * Creates an enhanced fetch function using a chain of middleware functions.\n *\n * The fetch chain executes in the order of the array, with each middleware\n * wrapping the next one in the chain. This allows each middleware to\n * intercept both the request (before calling next) and the response\n * (after calling next).\n *\n * @example\n * ```typescript\n * // Simple logging middleware\n * const loggingMiddleware: ChainFunction = (next) => {\n *   return async (url, options) => {\n *     console.log(`Request to ${url}`);\n *     const response = await next(url, options);\n *     console.log(`Response from ${url}: ${response.status}`);\n *     return response;\n *   };\n * };\n *\n * const enhancedFetch = createEnhancedFetch([loggingMiddleware]);\n * const response = await enhancedFetch('https://api.example.com/data');\n * ```\n *\n * @param chainFunctions - Array of chain functions to apply in order\n * @returns Enhanced fetch function with all middleware applied\n */\nexport function createEnhancedFetch(\n  chainFunctions: ChainFunction[] = [],\n): FetchFunction {\n  // Build the chain starting with vanilla fetch, but apply functions in reverse\n  // to achieve the desired execution order\n  return chainFunctions.reduceRight(\n    (nextInChain, chainFunction) => chainFunction(nextInChain),\n    fetch as FetchFunction,\n  );\n}\n\n/**\n * Interface representing a structured API response.\n *\n * This interface provides a consistent structure for responses across the SDK,\n * offering access to the parsed response body along with status and headers.\n *\n * @template T - The type of the response body\n */\nexport interface FetchResponse<T> {\n  /** The parsed response body */\n  body: T;\n  /** HTTP status code of the response */\n  status: number;\n  /** Response headers */\n  headers: Headers;\n}\n\nfunction extractMessage(body: unknown): string {\n  if (body && typeof body === 'string') {\n    return body;\n  }\n\n  if (body && typeof body === 'object') {\n    const typedBody = body as Record<string, unknown>;\n\n    if ('message' in typedBody && typeof typedBody['message'] === 'string') {\n      return typedBody['message'];\n    }\n\n    if ('error' in typedBody && typeof typedBody['error'] === 'string') {\n      return typedBody['error'];\n    }\n\n    if (\n      'error' in typedBody &&\n      typedBody['error'] &&\n      typeof typedBody['error'] === 'object'\n    ) {\n      const error = typedBody['error'] as Record<string, unknown>;\n      if ('message' in error && typeof error['message'] === 'string') {\n        return error['message'];\n      }\n    }\n\n    if ('errors' in typedBody && Array.isArray(typedBody['errors'])) {\n      const messages = (typedBody['errors'] as unknown[])\n        .filter(\n          (error): error is { message: string } =>\n            typeof error === 'object' &&\n            error !== null &&\n            'message' in error &&\n            typeof (error as { message: unknown })['message'] === 'string',\n        )\n        .map((error) => error['message']);\n\n      if (messages.length > 0) {\n        return messages.join(', ');\n      }\n    }\n  }\n\n  return 'An unexpected error occurred';\n}\n\n/**\n * Error class for representing fetch operation failures.\n *\n * This class extends the standard Error to include additional\n * information about failed requests, including the response body,\n * status code, and headers. The error message is automatically\n * extracted from common error response formats.\n *\n * @template T - The type of the response body\n */\nexport class FetchError<T = unknown> extends Error {\n  /** The original response body */\n  body: T;\n  /** HTTP status code of the failed response */\n  status: number;\n  /** Response headers */\n  headers: Headers;\n\n  /**\n   * Creates a new FetchError instance\n   *\n   * @param body - The response body from the failed request\n   * @param status - The HTTP status code\n   * @param headers - The response headers\n   */\n  constructor(body: T, status: number, headers: Headers) {\n    super(extractMessage(body));\n    this.body = body;\n    this.status = status;\n    this.headers = headers;\n  }\n}\n","/**\n * Authorization token attachment middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * authorization tokens to outgoing API requests, ensuring the client\n * is properly authenticated.\n */\n\nimport type { Session } from '../auth';\nimport type { SessionStorage } from '../session/storage';\nimport type { ChainFunction, FetchFunction } from './fetch';\n\n/**\n * Creates a fetch middleware that adds the Authorization header with the current access token.\n *\n * This middleware:\n * 1. Gets the current session from storage\n * 2. Adds the authorization header with the access token to outgoing requests\n *\n * This middleware should be used after the refresh middleware in the chain to\n * ensure the most recent token is used.\n *\n * @param storage - Storage implementation for retrieving session data\n * @returns A middleware function that adds Authorization headers\n */\nexport const attachAccessTokenMiddleware =\n  (storage: SessionStorage): ChainFunction =>\n  (next: FetchFunction): FetchFunction =>\n  async (url: string, options: RequestInit = {}): Promise<Response> => {\n    const headers = new Headers(options.headers || {});\n\n    // Skip if Authorization header is already set\n    if (headers.has('Authorization')) {\n      return next(url, options);\n    }\n\n    // Get current session from storage\n    const session = storage.get();\n\n    if (session?.accessToken) {\n      // Add authorization header\n      const newOptions = {\n        ...options,\n        headers: addAuthorizationHeader(headers, session),\n      };\n\n      // Continue with the fetch chain\n      return next(url, newOptions);\n    }\n\n    // No session or no access token, continue without authorization\n    return next(url, options);\n  };\n\n/**\n * Adds the Authorization header with the access token to the request headers\n *\n * @param headers - Original request headers\n * @param session - Current session containing the access token\n * @returns Modified headers with Authorization header\n */\nfunction addAuthorizationHeader(headers: Headers, session: Session): Headers {\n  if (session.accessToken) {\n    headers.set('Authorization', `Bearer ${session.accessToken}`);\n  }\n  return headers;\n}\n","/**\n * Auth token refresh middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically refresh\n * authentication tokens before they expire, ensuring seamless API access\n * without requiring manual token refresh by the application.\n */\n\nimport type { Client } from '../auth';\nimport { refreshSession } from '../session/refreshSession';\nimport type { SessionStorage } from '../session/storage';\nimport type { ChainFunction, FetchFunction } from './fetch';\n\n/**\n * Creates a fetch middleware that automatically refreshes authentication tokens.\n *\n * This middleware:\n * 1. Checks if the current token is about to expire\n * 2. If so, uses the refresh token to obtain a new access token\n *\n * The middleware handles token refresh transparently, so the application\n * doesn't need to manually refresh tokens.\n *\n * @param auth - Auth API client for token refresh operations\n * @param storage - Storage implementation for persisting session data\n * @param options - Configuration options for token refresh behavior\n * @param options.marginSeconds - Number of seconds before token expiration to trigger a refresh, default is 60 seconds\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const sessionRefreshMiddleware = (\n  auth: Client,\n  storage: SessionStorage,\n  options?: {\n    marginSeconds?: number;\n  },\n): ChainFunction => {\n  const { marginSeconds = 60 } = options || {};\n\n  // Create and return the chain function\n  return (next: FetchFunction): FetchFunction =>\n    async (url: string, options: RequestInit = {}): Promise<Response> => {\n      // Skip token handling for certain requests\n      if (shouldSkipTokenHandling(url, options)) {\n        return next(url, options);\n      }\n\n      try {\n        await refreshSession(auth, storage, marginSeconds);\n      } catch {\n        // do nothing, we still want to call the next function\n      }\n      return next(url, options);\n    };\n};\n\n/**\n * Determines if token handling should be skipped for this request\n *\n * @param url - Request URL\n * @param options - Request options\n * @returns True if token handling should be skipped, false otherwise\n */\nfunction shouldSkipTokenHandling(url: string, options: RequestInit): boolean {\n  const headers = new Headers(options.headers || {});\n\n  // If Authorization header is explicitly set, skip token handling\n  if (headers.has('Authorization')) {\n    return true;\n  }\n\n  // If calling the token endpoint, skip to avoid infinite loops\n  if (url.endsWith('/v1/token')) {\n    return true;\n  }\n\n  return false;\n}\n","/**\n * Session response middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically extract\n * and persist session information from authentication responses, ensuring\n * that new sessions are properly stored after sign-in operations.\n */\n\nimport type { Session, SessionPayload } from '../auth';\nimport type { SessionStorage } from '../session/storage';\nimport type { ChainFunction } from './fetch';\n\n/**\n * Creates a fetch middleware that automatically extracts and stores session data from API responses.\n *\n * This middleware:\n * 1. Monitors responses from authentication-related endpoints\n * 2. Extracts session information when present\n * 3. Stores the session in the provided storage implementation\n * 4. Handles session removal on sign-out\n *\n * This ensures that session data is always up-to-date in storage after operations\n * that create or invalidate sessions.\n *\n * @param storage - Storage implementation for persisting session data\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const updateSessionFromResponseMiddleware = (\n  storage: SessionStorage,\n): ChainFunction => {\n  /**\n   * Helper function to extract session data from various response formats\n   *\n   * @param body - Response data to extract session from\n   * @returns Session object if found, null otherwise\n   */\n  const sessionExtractor = (\n    body: Session | SessionPayload | string,\n  ): Session | null => {\n    if (typeof body === 'string') {\n      return null;\n    }\n\n    if ('session' in body) {\n      // SessionPayload\n      return body.session || null;\n    }\n\n    if ('accessToken' in body && 'refreshToken' in body && 'user' in body) {\n      // Session\n      return body;\n    }\n\n    return null;\n  };\n\n  return (next: (url: string, options?: RequestInit) => Promise<Response>) =>\n    async (url: string, options?: RequestInit) => {\n      // Call the next middleware in the chain\n      const response = await next(url, options);\n\n      try {\n        // Check if this is a logout request\n        if (url.endsWith('/signout')) {\n          // Remove session on sign-out\n          storage.remove();\n          return response;\n        }\n\n        // A successful password change revokes every refresh token for the\n        // user on the server (including the caller's), so the locally stored\n        // session is no longer valid. Clear it so the user is treated as\n        // signed out on the client too.\n        if (url.endsWith('/user/password') && response.ok) {\n          storage.remove();\n          return response;\n        }\n\n        // Check if this is an auth-related endpoint that might return session data\n        if (\n          url.endsWith('/token') ||\n          url.includes('/token/exchange') ||\n          url.includes('/signin/') ||\n          url.includes('/signup/')\n        ) {\n          // Clone the response to avoid consuming it\n          const clonedResponse = response.clone();\n\n          // Parse the JSON data\n          const body = (await clonedResponse.json().catch(() => null)) as\n            | Session\n            | SessionPayload;\n\n          if (body) {\n            // Extract session data from response using provided extractor\n            const session = sessionExtractor(body);\n\n            // If session data is found, store it\n            if (session?.accessToken && session.refreshToken) {\n              storage.set(session);\n            }\n          }\n        }\n      } catch (error) {\n        console.warn('Error in session response middleware:', error);\n      }\n\n      // Return the original response\n      return response;\n    };\n};\n","/**\n * Admin session middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * Hasura admin secret for admin permissions in requests.\n */\n\nimport type { ChainFunction, FetchFunction } from './fetch';\n\n/**\n * Configuration options for admin session middleware\n */\nexport interface AdminSessionOptions {\n  /**\n   * Hasura admin secret for elevated permissions (sets x-hasura-admin-secret header)\n   */\n  adminSecret: string;\n\n  /**\n   * Hasura role to use for the request (sets x-hasura-role header)\n   */\n  role?: string;\n\n  /**\n   * Additional Hasura session variables to attach to requests.\n   * Keys will be automatically prefixed with 'x-hasura-' if not already present.\n   *\n   * @example\n   * ```ts\n   * {\n   *   'user-id': '123',\n   *   'org-id': '456'\n   * }\n   * // Results in headers:\n   * // x-hasura-user-id: 123\n   * // x-hasura-org-id: 456\n   * ```\n   */\n  sessionVariables?: Record<string, string>;\n}\n\n/**\n * Creates a fetch middleware that attaches the Hasura admin secret and optional session variables to requests.\n *\n * This middleware:\n * 1. Sets the x-hasura-admin-secret header, which grants full admin access to Hasura\n * 2. Optionally sets the x-hasura-role header if a role is provided\n * 3. Optionally sets additional x-hasura-* headers for custom session variables\n *\n * **Security Warning**: Never use this middleware in client-side code or expose\n * the admin secret to end users. Admin secrets grant unrestricted access to your\n * entire database. This should only be used in trusted server-side environments.\n *\n * The middleware preserves request-specific headers when they conflict with the\n * admin session configuration.\n *\n * @param options - Admin session options including admin secret, role, and session variables\n * @returns A middleware function that can be used in the fetch chain\n *\n * @example\n * ```ts\n * // Create middleware with admin secret only\n * const adminMiddleware = withAdminSessionMiddleware({\n *   adminSecret: process.env.NHOST_ADMIN_SECRET\n * });\n *\n * // Create middleware with admin secret and role\n * const adminUserMiddleware = withAdminSessionMiddleware({\n *   adminSecret: process.env.NHOST_ADMIN_SECRET,\n *   role: 'user'\n * });\n *\n * // Create middleware with admin secret, role, and custom session variables\n * const fullMiddleware = withAdminSessionMiddleware({\n *   adminSecret: process.env.NHOST_ADMIN_SECRET,\n *   role: 'user',\n *   sessionVariables: {\n *     'user-id': '123',\n *     'org-id': '456'\n *   }\n * });\n *\n * // Use with createCustomClient for an admin client\n * const adminClient = createCustomClient({\n *   subdomain: 'myproject',\n *   region: 'eu-central-1',\n *   chainFunctions: [adminMiddleware]\n * });\n * ```\n */\nexport const withAdminSessionMiddleware =\n  (options: AdminSessionOptions): ChainFunction =>\n  (next: FetchFunction): FetchFunction =>\n  async (url: string, requestOptions: RequestInit = {}): Promise<Response> => {\n    const headers = new Headers(requestOptions.headers || {});\n\n    // Set x-hasura-admin-secret if not already present\n    if (!headers.has('x-hasura-admin-secret')) {\n      headers.set('x-hasura-admin-secret', options.adminSecret);\n    }\n\n    // Set x-hasura-role if provided and not already present\n    if (options.role && !headers.has('x-hasura-role')) {\n      headers.set('x-hasura-role', options.role);\n    }\n\n    // Set custom session variables\n    if (options.sessionVariables) {\n      for (const [key, value] of Object.entries(options.sessionVariables)) {\n        // Ensure the key has the x-hasura- prefix\n        const headerKey = key.startsWith('x-hasura-') ? key : `x-hasura-${key}`;\n\n        // Only set if not already present in the request\n        if (!headers.has(headerKey)) {\n          headers.set(headerKey, value);\n        }\n      }\n    }\n\n    return next(url, { ...requestOptions, headers });\n  };\n","/**\n * Headers middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * default headers to all outgoing requests, while allowing request-specific\n * headers to take precedence.\n */\n\nimport type { ChainFunction, FetchFunction } from './fetch';\n\n/**\n * Creates a fetch middleware that attaches default headers to requests.\n *\n * This middleware:\n * 1. Merges default headers with request-specific headers\n * 2. Preserves request-specific headers when they conflict with defaults\n *\n * The middleware ensures consistent headers across requests while allowing\n * individual requests to override defaults as needed.\n *\n * @param defaultHeaders - Default headers to attach to all requests\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const withHeadersMiddleware =\n  (defaultHeaders: HeadersInit): ChainFunction =>\n  (next: FetchFunction): FetchFunction =>\n  async (url: string, options: RequestInit = {}): Promise<Response> => {\n    const headers = new Headers(options.headers || {});\n    const defaults = new Headers(defaultHeaders);\n\n    defaults.forEach((value, key) => {\n      if (!headers.has(key)) {\n        headers.set(key, value);\n      }\n    });\n\n    return next(url, { ...options, headers });\n  };\n","/**\n * Role middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically set\n * the Hasura role for all requests. This is useful when you want to\n * make requests as a specific role without using the admin secret.\n */\n\nimport type { ChainFunction, FetchFunction } from './fetch';\n\n/**\n * Creates a fetch middleware that sets the Hasura role header.\n *\n * This middleware sets the x-hasura-role header for all requests, allowing\n * you to specify which role's permissions should be used. This works with\n * authenticated sessions where the user has access to the specified role.\n *\n * Unlike `withAdminSessionMiddleware`, this does not bypass permission rules\n * but instead uses the permission rules defined for the specified role.\n *\n * The middleware preserves request-specific headers when they conflict with\n * the role configuration.\n *\n * @param role - The Hasura role to use for requests\n * @returns A middleware function that can be used in the fetch chain\n *\n * @example\n * ```ts\n * // Use with createClient to default all requests to a specific role\n * const nhost = createClient({\n *   subdomain: 'myproject',\n *   region: 'eu-central-1',\n *   chainFunctions: [withRoleMiddleware('moderator')]\n * });\n *\n * // Use with createServerClient for server-side requests\n * const serverNhost = createServerClient({\n *   subdomain: 'myproject',\n *   region: 'eu-central-1',\n *   storage: myServerStorage,\n *   chainFunctions: [withRoleMiddleware('moderator')]\n * });\n * ```\n */\nexport const withRoleMiddleware =\n  (role: string): ChainFunction =>\n  (next: FetchFunction): FetchFunction =>\n  async (url: string, requestOptions: RequestInit = {}): Promise<Response> => {\n    const headers = new Headers(requestOptions.headers || {});\n\n    // Set x-hasura-role if not already present\n    if (!headers.has('x-hasura-role')) {\n      headers.set('x-hasura-role', role);\n    }\n\n    return next(url, { ...requestOptions, headers });\n  };\n"],"mappings":"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"}