{"version":3,"file":"grant-client-DEaSxech.cjs","names":[],"sources":["../src/utils/token-extractor.ts","../src/grant-client.ts"],"sourcesContent":["import type { GrantServerConfig } from '../types';\n\n/**\n * Extract Bearer token from Authorization header\n */\nexport function extractBearerToken(authHeader: string | undefined): string | null {\n  if (!authHeader) return null;\n\n  const parts = authHeader.trim().split(/\\s+/);\n  if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') {\n    return null;\n  }\n\n  return parts[1];\n}\n\n/**\n * Parse cookie header string into key-value pairs\n */\nfunction parseCookieHeader(cookieHeader: string): Record<string, string> {\n  const cookies: Record<string, string> = {};\n\n  cookieHeader.split(';').forEach((cookie) => {\n    const [name, ...rest] = cookie.trim().split('=');\n    if (name && rest.length > 0) {\n      cookies[name.trim()] = rest.join('=').trim();\n    }\n  });\n\n  return cookies;\n}\n\n/**\n * Extract token from cookies\n */\nexport function extractTokenFromCookies(\n  cookieHeader: string | undefined,\n  cookieName: string\n): string | null {\n  if (!cookieHeader) return null;\n\n  const cookies = parseCookieHeader(cookieHeader);\n  return cookies[cookieName] || null;\n}\n\n/**\n * Extract token from Express request\n */\nexport async function extractTokenFromRequest(\n  request: unknown,\n  config: GrantServerConfig\n): Promise<string | null> {\n  // Use custom token resolver if provided\n  if (config.getToken) {\n    const token = await config.getToken(request);\n    if (token) return token;\n  }\n\n  // Try to extract from request (Express-style or Web API / NextRequest)\n  const req = request as {\n    headers?:\n      { authorization?: string; cookie?: string } | { get: (name: string) => string | null };\n    cookies?: Record<string, string>;\n  };\n\n  if (!req?.headers) return null;\n\n  // Web API Headers (NextRequest, Request): headers.get(name)\n  const headersGet = (req.headers as { get?: (name: string) => string | null }).get;\n  if (typeof headersGet === 'function') {\n    const authHeader = headersGet.call(req.headers, 'authorization');\n    const bearerToken = extractBearerToken(authHeader ?? undefined);\n    if (bearerToken) return bearerToken;\n    const cookieName = config.cookieName || 'grant-access-token';\n    const cookieHeader = headersGet.call(req.headers, 'cookie');\n    if (cookieHeader) {\n      const cookieToken = extractTokenFromCookies(cookieHeader, cookieName);\n      if (cookieToken) return cookieToken;\n    }\n    return null;\n  }\n\n  // Express-style: headers.authorization, headers.cookie\n  const plainHeaders = req.headers as { authorization?: string; cookie?: string };\n  const authHeader = plainHeaders.authorization;\n  const bearerToken = extractBearerToken(authHeader);\n  if (bearerToken) return bearerToken;\n\n  const cookieName = config.cookieName || 'grant-access-token';\n\n  if (req.cookies?.[cookieName]) {\n    return req.cookies[cookieName];\n  }\n\n  const cookieHeader = plainHeaders.cookie;\n  if (cookieHeader) {\n    const cookieToken = extractTokenFromCookies(cookieHeader, cookieName);\n    if (cookieToken) return cookieToken;\n  }\n\n  return null;\n}\n","import type { AuthorizationResult, GrantServerConfig, PermissionCheckOptions } from './types';\nimport { extractTokenFromRequest } from './utils/token-extractor';\n\n/**\n * Grant Client for server-side applications\n *\n * Makes HTTP requests to the Grant API to check permissions.\n * Uses API-key exchanged tokens (scope in JWT claims); token-based and cookie-based extraction supported.\n * No caching - server-side caching is handled by grant-api.\n */\nexport class GrantClient {\n  public readonly config: Required<Pick<GrantServerConfig, 'apiUrl'>> & GrantServerConfig;\n\n  constructor(config: GrantServerConfig) {\n    this.config = config;\n  }\n\n  // ============================================================================\n  // Public API - Permission Checks\n  // ============================================================================\n\n  /**\n   * Check if the current user has a specific permission\n   *\n   * @example\n   * ```ts\n   * const canEdit = await grant.isGranted('document', 'update', { scope });\n   * if (canEdit) {\n   *   // Proceed with operation\n   * }\n   * ```\n   */\n  async isGranted(\n    resource: string,\n    action: string,\n    options?: PermissionCheckOptions,\n    request?: unknown\n  ): Promise<boolean> {\n    const result = await this.isAuthorized(resource, action, options, request);\n    return result.authorized;\n  }\n\n  /**\n   * Check authorization with full result details\n   *\n   * @example\n   * ```ts\n   * const result = await grant.isAuthorized('document', 'update', { scope }, request);\n   * if (!result.authorized) {\n   *   console.log('Denied:', result.reason);\n   * }\n   * ```\n   */\n  async isAuthorized(\n    resource: string,\n    action: string,\n    options?: PermissionCheckOptions,\n    request?: unknown\n  ): Promise<AuthorizationResult> {\n    try {\n      // API expects: { permission: { resource, action }, context: { resource?: any }, scope?: { tenant, id } }\n      const response = await this.fetchWithAuth(\n        '/api/auth/is-authorized',\n        {\n          method: 'POST',\n          body: JSON.stringify({\n            permission: {\n              resource,\n              action,\n            },\n            context: {\n              resource: options?.context?.resource || null,\n            },\n          }),\n        },\n        request\n      );\n\n      if (!response.ok) {\n        const error = await response.json().catch(() => ({}));\n        return {\n          authorized: false,\n          reason: error.message || `API error: ${response.status}`,\n        };\n      }\n\n      const json = await response.json();\n      // API returns { success: true, data: { authorized, ... } }\n      const result: AuthorizationResult = json.data ?? json;\n      return result;\n    } catch (error) {\n      return {\n        authorized: false,\n        reason: error instanceof Error ? error.message : 'Unknown error',\n      };\n    }\n  }\n\n  /**\n   * Extract token from a request object\n   * Useful for middleware that needs to extract token before making authorization calls\n   */\n  async getTokenFromRequest(request: unknown): Promise<string | null> {\n    return extractTokenFromRequest(request, this.config);\n  }\n\n  // ============================================================================\n  // Private - HTTP & Authentication\n  // ============================================================================\n\n  /**\n   * Make an authenticated fetch request (token from request; no refresh).\n   */\n  private async fetchWithAuth(\n    url: string,\n    init?: RequestInit,\n    request?: unknown\n  ): Promise<Response> {\n    return this.doFetch(url, init, request);\n  }\n\n  /**\n   * Perform the actual fetch request\n   */\n  private async doFetch(url: string, init?: RequestInit, request?: unknown): Promise<Response> {\n    const fetchFn = this.config.fetch ?? globalThis.fetch;\n    const fullUrl = url.startsWith('http') ? url : `${this.config.apiUrl}${url}`;\n\n    const headers: Record<string, string> = {\n      'Content-Type': 'application/json',\n      ...(init?.headers as Record<string, string>),\n    };\n\n    // Add authorization header if token is available\n    if (request) {\n      const token = await extractTokenFromRequest(request, this.config);\n      if (token) {\n        headers['Authorization'] = `Bearer ${token}`;\n      }\n\n      // Forward cookies if using cookie-based auth\n      const req = request as { headers?: { cookie?: string } };\n      if (req.headers?.cookie) {\n        headers['Cookie'] = req.headers.cookie;\n      }\n    }\n\n    return fetchFn(fullUrl, {\n      ...init,\n      headers,\n      // Include cookies for same-origin requests (supports cookie-based auth)\n      credentials: this.config.credentials ?? 'include',\n    });\n  }\n}\n"],"mappings":"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"}