@mosano-product-framework/sdk 0.2.0 → 0.2.2

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.
@@ -20,7 +20,7 @@
20
20
  * - deciding when to proactively renew.
21
21
  *
22
22
  * NEVER gate a security-relevant branch on these values. The server is the only
23
- * authority: `hasura-authd` and `internal/go-chi-middleware-auth` verify the
23
+ * authority: `hasura-authd` and `pkg/go-chi-middleware-auth` verify the
24
24
  * signature and re-derive tenant and role from the token on every single
25
25
  * request, and a forged claim buys the attacker exactly nothing there.
26
26
  *
@@ -1,5 +1,5 @@
1
- export { TENANT_DIRECTORY_QUERY, createOAuthStateStore } from '../chunk-GPWGOYCA.js';
2
- export { REFRESH_TOKEN_SUPERSEDED, SessionManager, applyJitter, createCrossTabCoordinator, createDefaultStorage, createMemoryStorage, createSessionManager, createSessionStorage, createTenantSelection, isSupersededError } from '../chunk-7WAV52EO.js';
3
- export { DeadSessionError, MPFClaimsError, MPFUnsupportedClaimsVersionError, canSelect, clearClaimsCache, decodeAccessToken, defaultRoleForTenant, expiresAt, isDeadSession, isExpired, listTenants, registerClaimsParser, rolesForTenant, supportedClaimsVersions, tokenLifetimeSeconds, tryDecodeAccessToken } from '../chunk-AJWM5MDZ.js';
1
+ export { TENANT_DIRECTORY_QUERY, createOAuthStateStore } from '../chunk-FYUVJL4T.js';
2
+ export { REFRESH_TOKEN_SUPERSEDED, SessionManager, applyJitter, createCrossTabCoordinator, createDefaultStorage, createMemoryStorage, createSessionManager, createSessionStorage, createTenantSelection, isSupersededError } from '../chunk-NM63E6OB.js';
3
+ export { DeadSessionError, MPFClaimsError, MPFUnsupportedClaimsVersionError, canSelect, clearClaimsCache, decodeAccessToken, defaultRoleForTenant, expiresAt, isDeadSession, isExpired, listTenants, registerClaimsParser, rolesForTenant, supportedClaimsVersions, tokenLifetimeSeconds, tryDecodeAccessToken } from '../chunk-S5DKGPUY.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
- import { issueAdminToken, createTurnstileMiddleware, createAdminAuthMiddleware, AdminEmptyUserIDError, AdminEmptySecretError } from './chunk-K2ELAI2X.js';
2
- import { shouldRetryRequest, requestRetry, isRetryDisabled, isReplayableBody, getRetryAttempt, executeResponseMiddlewares, executeRequestMiddlewares, executeErrorMiddlewares, disableRetry, createTenantMiddleware, createRetryMiddleware, createHttpClient, createAuthMiddleware, clearRetryFlag, attachStandardMiddlewares, TENANT_ROLE_HEADER, TENANT_HEADER, MPFClient, MAX_REQUEST_ATTEMPTS } from './chunk-LRM6JJ63.js';
3
- import { __export, isMPFValidationError, isMPFNetworkError, isMPFError, isMPFAuthError, isMPFAPIError, MPFValidationError, MPFTimeoutError, MPFNetworkError, MPFError, MPFAuthError, MPFAPIError } from './chunk-AJWM5MDZ.js';
1
+ import { issueAdminToken, createTurnstileMiddleware, createAdminAuthMiddleware, AdminEmptyUserIDError, AdminEmptySecretError } from './chunk-B3JXAPMM.js';
2
+ import { shouldRetryRequest, requestRetry, isRetryDisabled, isReplayableBody, getRetryAttempt, executeResponseMiddlewares, executeRequestMiddlewares, executeErrorMiddlewares, disableRetry, createTenantMiddleware, createRetryMiddleware, createHttpClient, createAuthMiddleware, clearRetryFlag, attachStandardMiddlewares, TENANT_ROLE_HEADER, TENANT_HEADER, MPFClient, MAX_REQUEST_ATTEMPTS } from './chunk-3OKR4MSV.js';
3
+ import { __export, isMPFValidationError, isMPFNetworkError, isMPFError, isMPFAuthError, isMPFAPIError, MPFValidationError, MPFTimeoutError, MPFNetworkError, MPFError, MPFAuthError, MPFAPIError } from './chunk-S5DKGPUY.js';
4
4
 
5
5
  // src/client/middlewares/logging.ts
6
6
  var DEFAULT_REDACT_HEADERS = [
@@ -335,5 +335,5 @@ __export(peer_free_exports, {
335
335
  });
336
336
 
337
337
  export { MPFGraphQLClient, buildUrl, createLoggingMiddleware, getOperationKind, isSubscription, joinPath, peer_free_exports };
338
- //# sourceMappingURL=chunk-GQJ3QQPH.js.map
339
- //# sourceMappingURL=chunk-GQJ3QQPH.js.map
338
+ //# sourceMappingURL=chunk-2WY2XQCV.js.map
339
+ //# sourceMappingURL=chunk-2WY2XQCV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/middlewares/logging.ts","../src/client/utils/url.ts","../src/client/graphql/client.ts","../src/client/graphql/operation.ts","../src/client/peer-free.ts"],"names":[],"mappings":"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","file":"chunk-GQJ3QQPH.js","sourcesContent":["import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext, ResponseContext } from '../core/types.js';\n\n/**\n * Logger interface compatible with console and custom loggers.\n */\nexport interface Logger {\n log: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Options for the logging middleware.\n */\nexport interface LoggingMiddlewareOptions {\n /**\n * Logger instance to use for output.\n * Defaults to console.\n */\n logger?: Logger;\n\n /**\n * Whether to log request/response bodies.\n * Default is false for security (bodies may contain sensitive data).\n * @default false\n */\n logBody?: boolean;\n\n /**\n * Prefix for all log messages.\n * @default '[MPF SDK]'\n */\n prefix?: string;\n\n /**\n * Whether to log request headers.\n * Sensitive headers like Authorization are always redacted.\n * @default false\n */\n logHeaders?: boolean;\n\n /**\n * List of header names to redact from logs (case-insensitive).\n * @default ['authorization', 'cookie', 'x-api-key', 'x-auth-token']\n */\n redactHeaders?: string[];\n\n /**\n * Minimum duration in ms to log. Requests faster than this are not logged.\n * Useful for reducing log volume in high-traffic scenarios.\n * @default 0 (log all requests)\n */\n minDuration?: number;\n\n /**\n * Whether to include timestamp in log messages.\n * @default true\n */\n includeTimestamp?: boolean;\n\n /**\n * Custom log formatter for requests.\n * If provided, overrides the default request logging format.\n */\n formatRequest?: (ctx: RequestContext) => string;\n\n /**\n * Custom log formatter for responses.\n * If provided, overrides the default response logging format.\n */\n formatResponse?: <T>(ctx: ResponseContext<T>) => string;\n\n /**\n * Custom log formatter for errors.\n * If provided, overrides the default error logging format.\n */\n formatError?: (error: Error, ctx: RequestContext) => string;\n}\n\n/** Default headers to redact from logs */\nconst DEFAULT_REDACT_HEADERS = [\n 'authorization',\n 'cookie',\n 'x-api-key',\n 'x-auth-token',\n 'x-access-token',\n 'set-cookie',\n];\n\n/**\n * Format headers for logging, redacting sensitive values.\n */\nfunction formatHeaders(\n headers: Headers | HeadersInit | undefined,\n redactHeaders: string[]\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (!headers) {\n return result;\n }\n\n const headersObj = headers instanceof Headers ? headers : new Headers(headers);\n const redactSet = new Set(redactHeaders.map((h) => h.toLowerCase()));\n\n headersObj.forEach((value, key) => {\n const lowerKey = key.toLowerCase();\n if (redactSet.has(lowerKey)) {\n result[key] = '[REDACTED]';\n } else {\n result[key] = value;\n }\n });\n\n return result;\n}\n\n/**\n * Get current timestamp in ISO format.\n */\nfunction getTimestamp(): string {\n return new Date().toISOString();\n}\n\n/**\n * Extract HTTP method from request init.\n */\nfunction getMethod(init: RequestInit): string {\n return (init.method ?? 'GET').toUpperCase();\n}\n\n/**\n * Truncate body for logging if too long.\n */\nfunction truncateBody(body: unknown, maxLength: number = 1000): string {\n if (body === undefined || body === null) {\n return '';\n }\n\n let bodyStr: string;\n if (typeof body === 'string') {\n bodyStr = body;\n } else if (body instanceof FormData) {\n return '[FormData]';\n } else if (body instanceof Blob) {\n return `[Blob: ${body.size} bytes]`;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n const size = body instanceof ArrayBuffer ? body.byteLength : body.byteLength;\n return `[Binary: ${size} bytes]`;\n } else if (body instanceof URLSearchParams) {\n bodyStr = body.toString();\n } else if (body instanceof ReadableStream) {\n return '[ReadableStream]';\n } else {\n try {\n bodyStr = JSON.stringify(body);\n } catch {\n return '[Unserializable]';\n }\n }\n\n if (bodyStr.length > maxLength) {\n return bodyStr.substring(0, maxLength) + `... (${bodyStr.length} chars total)`;\n }\n\n return bodyStr;\n}\n\n/**\n * Creates a logging middleware for debugging and monitoring.\n *\n * The middleware logs:\n * - Request method, URL, and optionally body/headers\n * - Response status, URL, and duration\n * - Errors with context\n *\n * Sensitive headers (Authorization, Cookie, etc.) are automatically redacted.\n *\n * @param options - Configuration options for the logging middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const loggingMiddleware = createLoggingMiddleware({\n * prefix: '[MyApp API]',\n * logBody: false,\n * logHeaders: true,\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With custom logger\n * const loggingMiddleware = createLoggingMiddleware({\n * logger: {\n * log: (msg, ...args) => myLogger.info(msg, ...args),\n * error: (msg, ...args) => myLogger.error(msg, ...args),\n * },\n * minDuration: 100, // Only log requests taking > 100ms\n * });\n * ```\n */\nexport function createLoggingMiddleware(options?: LoggingMiddlewareOptions): Middleware {\n const {\n logger = console,\n logBody = false,\n prefix = '[MPF SDK]',\n logHeaders = false,\n redactHeaders = DEFAULT_REDACT_HEADERS,\n minDuration = 0,\n includeTimestamp = true,\n formatRequest: customFormatRequest,\n formatResponse: customFormatResponse,\n formatError: customFormatError,\n } = options ?? {};\n\n /**\n * Build log prefix with optional timestamp.\n */\n function buildPrefix(): string {\n if (includeTimestamp) {\n return `${prefix} [${getTimestamp()}]`;\n }\n return prefix;\n }\n\n return {\n name: 'logging',\n\n onRequest(ctx: RequestContext): RequestContext {\n // Store start time and request info for response logging\n ctx.metadata['__requestStartTime'] = Date.now();\n ctx.metadata['__requestMethod'] = getMethod(ctx.init);\n ctx.metadata['__requestUrl'] = ctx.url;\n\n const method = ctx.metadata['__requestMethod'] as string;\n const logPrefix = buildPrefix();\n\n if (customFormatRequest) {\n logger.log(customFormatRequest(ctx));\n } else {\n const parts: string[] = [`${logPrefix} --> ${method} ${ctx.url}`];\n\n if (logHeaders && ctx.init.headers) {\n const headers = formatHeaders(ctx.init.headers, redactHeaders);\n parts.push(` Headers: ${JSON.stringify(headers)}`);\n }\n\n if (logBody && ctx.init.body) {\n const body = truncateBody(ctx.init.body);\n if (body) {\n parts.push(` Body: ${body}`);\n }\n }\n\n logger.log(parts.join('\\n'));\n }\n\n return ctx;\n },\n\n onResponse<T>(ctx: ResponseContext<T>): ResponseContext<T> {\n const startTime = ctx.metadata['__requestStartTime'] as number | undefined;\n const duration = startTime ? Date.now() - startTime : 0;\n\n // Skip logging if duration is below threshold\n if (duration < minDuration) {\n return ctx;\n }\n\n const method = (ctx.metadata['__requestMethod'] as string) || 'GET';\n const status = ctx.response.status;\n const statusText = ctx.response.statusText;\n const url = (ctx.metadata['__requestUrl'] as string) || ctx.response.url || '(unknown)';\n const logPrefix = buildPrefix();\n\n if (customFormatResponse) {\n logger.log(customFormatResponse(ctx));\n } else {\n const statusIcon = status >= 200 && status < 300 ? 'OK' : status >= 400 ? 'ERR' : 'WARN';\n const parts: string[] = [\n `${logPrefix} <-- ${method} ${url} ${status} ${statusText} (${duration}ms) [${statusIcon}]`,\n ];\n\n if (logHeaders) {\n const headers = formatHeaders(ctx.response.headers, redactHeaders);\n parts.push(` Headers: ${JSON.stringify(headers)}`);\n }\n\n if (logBody && ctx.data !== undefined) {\n const body = truncateBody(ctx.data);\n if (body) {\n parts.push(` Body: ${body}`);\n }\n }\n\n logger.log(parts.join('\\n'));\n }\n\n return ctx;\n },\n\n onError(error: Error, ctx: RequestContext): never {\n const startTime = ctx.metadata['__requestStartTime'] as number | undefined;\n const duration = startTime ? Date.now() - startTime : 0;\n const method = getMethod(ctx.init);\n const logPrefix = buildPrefix();\n\n if (customFormatError) {\n logger.error(customFormatError(error, ctx));\n } else {\n const parts: string[] = [\n `${logPrefix} <-- ${method} ${ctx.url} ERROR (${duration}ms)`,\n ` Error: ${error.name}: ${error.message}`,\n ];\n\n if (error.stack) {\n // Only include first 3 lines of stack trace\n const stackLines = error.stack.split('\\n').slice(1, 4);\n parts.push(` Stack: ${stackLines.join('\\n ')}`);\n }\n\n logger.error(parts.join('\\n'));\n }\n\n throw error;\n },\n };\n}\n","/**\n * URL building utilities for the MPF SDK\n */\n\n/**\n * Build a URL with query parameters\n *\n * @param baseUrl - The base URL\n * @param path - The path to append\n * @param params - Optional query parameters\n * @returns The full URL with query string\n */\nexport function buildUrl(\n baseUrl: string,\n path: string,\n params?: Record<string, string | number | boolean | undefined | null>\n): string {\n // Remove trailing slash from base URL\n const normalizedBase = baseUrl.replace(/\\/+$/, '');\n\n // Ensure path starts with a slash\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n\n const base = /^https?:\\/\\//.test(normalizedBase)\n ? normalizedBase\n : (typeof window !== 'undefined' ? window.location.origin : 'http://localhost');\n const url = new URL(`${normalizedBase}${normalizedPath}`, base);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n}\n\n/**\n * Join URL segments safely\n *\n * @param segments - URL segments to join\n * @returns Joined URL path\n */\nexport function joinPath(...segments: string[]): string {\n return segments\n .map((segment, index) => {\n // Remove leading slash except for first segment\n if (index > 0) {\n segment = segment.replace(/^\\/+/, '');\n }\n // Remove trailing slash except for last segment\n if (index < segments.length - 1) {\n segment = segment.replace(/\\/+$/, '');\n }\n return segment;\n })\n .filter(Boolean)\n .join('/');\n}\n","/**\n * GraphQL client that extends the base MPF client\n */\n\nimport { MPFClient } from '../core/client.js';\nimport type { ClientConfig } from '../core/types.js';\nimport type {\n TypedDocumentNode,\n GraphQLResponse,\n GraphQLRequestOptions,\n} from './types.js';\nimport { MPFAPIError } from '../core/errors.js';\n\n/**\n * Configuration options for the GraphQL client\n */\nexport interface GraphQLClientConfig extends ClientConfig {\n /**\n * GraphQL endpoint path (default: '/graphql')\n */\n endpoint?: string;\n}\n\n/**\n * GraphQL client for MPF services\n *\n * Supports both raw query strings and typed document nodes for type-safe operations.\n *\n * @example\n * ```typescript\n * const client = new MPFGraphQLClient({ baseUrl: 'https://api.example.com' });\n *\n * // Using raw query string\n * const result = await client.query(`\n * query GetUser($id: ID!) {\n * user(id: $id) { id name email }\n * }\n * `, { id: '123' });\n *\n * // Using typed document node (from codegen)\n * const typedResult = await client.query(GetUserDocument, { id: '123' });\n * ```\n */\nexport class MPFGraphQLClient extends MPFClient {\n /** The GraphQL endpoint path */\n protected graphqlEndpoint: string;\n\n constructor(config: GraphQLClientConfig) {\n super(config);\n this.graphqlEndpoint = config.endpoint ?? '/graphql';\n }\n\n /**\n * Execute a GraphQL query operation\n *\n * @param document - The GraphQL query (string or typed document node)\n * @param variables - Optional variables for the query\n * @param options - Optional request options (headers, signal)\n * @returns The query result data\n * @throws {MPFAPIError} When GraphQL errors occur or no data is returned\n */\n async query<TData, TVariables = Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n return this.executeOperation<TData, TVariables>(document, variables, options);\n }\n\n /**\n * Execute a GraphQL mutation operation\n *\n * @param document - The GraphQL mutation (string or typed document node)\n * @param variables - Optional variables for the mutation\n * @param options - Optional request options (headers, signal)\n * @returns The mutation result data\n * @throws {MPFAPIError} When GraphQL errors occur or no data is returned\n */\n async mutate<TData, TVariables = Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n return this.executeOperation<TData, TVariables>(document, variables, options);\n }\n\n /**\n * Execute a GraphQL operation (query or mutation)\n *\n * @internal\n */\n private async executeOperation<TData, TVariables>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n const query = typeof document === 'string' ? document : document.toString();\n\n const response = await this.post<GraphQLResponse<TData>>(\n this.graphqlEndpoint,\n { query, variables },\n options\n );\n\n // Handle GraphQL errors (they come in the response body, not HTTP status)\n if (response.errors && response.errors.length > 0) {\n const firstError = response.errors[0];\n const errorCode =\n (firstError.extensions?.code as string | undefined) ?? 'GRAPHQL_ERROR';\n\n throw new MPFAPIError(\n firstError.message,\n errorCode,\n 200,\n response.errors\n );\n }\n\n if (response.data === undefined || response.data === null) {\n throw new MPFAPIError(\n 'No data returned from GraphQL operation',\n 'NO_DATA',\n 200\n );\n }\n\n return response.data;\n }\n}\n","/**\n * Cheap operation-kind detection — no `graphql` parser dependency.\n *\n * The hybrid client only needs ONE bit: \"is this a subscription\". A full AST\n * parse (`graphql`'s `parse()` + `getOperationAST()`) would answer that too,\n * but it drags `graphql` into the HTTP-only path as a hard dependency, which\n * defeats the point of `graphql` staying an optional peer (see\n * `graphql/ws-client.ts`). A GraphQL document's operation keyword is always\n * the first non-trivia token — `query`/`mutation`/`subscription`, or omitted\n * entirely for the anonymous-query shorthand (`{ ... }`) — so a regex over the\n * leading trivia is exact, not a heuristic.\n */\n\n/** The three GraphQL operation kinds, plus `unknown` for an unparseable document. */\nexport type OperationKind = 'query' | 'mutation' | 'subscription' | 'unknown';\n\n/**\n * Strip GraphQL trivia (whitespace, commas, `#`-comments) from the START of a\n * document string, mirroring the lexer's own definition of \"ignored tokens\"\n * (GraphQL spec §2.1.4) closely enough to find the first real token.\n */\nfunction stripLeadingTrivia(source: string): string {\n let rest = source;\n for (;;) {\n const trimmed = rest.replace(/^[\\s,\\uFEFF]+/, '');\n if (trimmed.startsWith('#')) {\n const newline = trimmed.indexOf('\\n');\n rest = newline === -1 ? '' : trimmed.slice(newline + 1);\n continue;\n }\n if (trimmed !== rest) {\n rest = trimmed;\n continue;\n }\n return trimmed;\n }\n}\n\n/**\n * Determine a GraphQL document's operation kind from its source text.\n *\n * `{ ... }` (no keyword) is the anonymous-query shorthand and is always a\n * `query` — a `subscription` document is never allowed to omit its keyword,\n * per the GraphQL spec, so this cannot misclassify a subscription as a query.\n */\nexport function getOperationKind(document: string): OperationKind {\n const source = stripLeadingTrivia(document);\n\n if (source.startsWith('{')) {\n return 'query';\n }\n\n const match = /^(query|mutation|subscription)\\b/.exec(source);\n if (!match) {\n return 'unknown';\n }\n\n return match[1] as OperationKind;\n}\n\n/** Whether a GraphQL document is a subscription. */\nexport function isSubscription(document: string): boolean {\n return getOperationKind(document) === 'subscription';\n}\n","/**\n * The part of `./client` that reaches NO optional peer dependency.\n *\n * This file exists so the root barrel can expose a `client` namespace without\n * dragging `graphql-ws` into every consumer's module graph.\n *\n * `createGraphQLClient` (in `graphql/factory.ts`) and `createGraphQLWsTransport`\n * (in `graphql/ws-client.ts`) reach `graphql-ws`. It is only ever loaded through\n * a dynamic `import()`, so nothing breaks at runtime for an app that never\n * subscribes — but a *static* export chain from `src/index.ts` still puts those\n * modules (and the dynamic-import chunk a bundler emits for them) in the graph\n * of every consumer, including plain-HTTP ones. So they are reachable from the\n * `./client` subpath only, never from the root namespace.\n *\n * This is the same rule `./react` follows for its `react` peer. See\n * `tests/module-boundaries.test.ts` (\"depends on jose only\") for the guard.\n *\n * @packageDocumentation\n */\n\n// Core transport: client, middleware machinery, errors, shared types.\nexport * from './core/index.js';\n\n// Generic middlewares: auth, admin-auth, tenant, retry, logging, turnstile.\nexport * from './middlewares/index.js';\n\n// URL helpers.\nexport * from './utils/url.js';\n\n// GraphQL over plain HTTP. No optional peer involved: the request goes through\n// the same `fetch` path as every other client.\nexport { MPFGraphQLClient, type GraphQLClientConfig } from './graphql/client.js';\nexport type {\n TypedDocumentNode,\n GraphQLError,\n GraphQLResponse,\n GraphQLRequestOptions,\n} from './graphql/types.js';\n\n// Pure string inspection of a GraphQL document — no dependencies at all.\nexport { getOperationKind, isSubscription, type OperationKind } from './graphql/operation.js';\n"]}
1
+ {"version":3,"sources":["../src/client/middlewares/logging.ts","../src/client/utils/url.ts","../src/client/graphql/client.ts","../src/client/graphql/operation.ts","../src/client/peer-free.ts"],"names":[],"mappings":"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","file":"chunk-2WY2XQCV.js","sourcesContent":["import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext, ResponseContext } from '../core/types.js';\n\n/**\n * Logger interface compatible with console and custom loggers.\n */\nexport interface Logger {\n log: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Options for the logging middleware.\n */\nexport interface LoggingMiddlewareOptions {\n /**\n * Logger instance to use for output.\n * Defaults to console.\n */\n logger?: Logger;\n\n /**\n * Whether to log request/response bodies.\n * Default is false for security (bodies may contain sensitive data).\n * @default false\n */\n logBody?: boolean;\n\n /**\n * Prefix for all log messages.\n * @default '[MPF SDK]'\n */\n prefix?: string;\n\n /**\n * Whether to log request headers.\n * Sensitive headers like Authorization are always redacted.\n * @default false\n */\n logHeaders?: boolean;\n\n /**\n * List of header names to redact from logs (case-insensitive).\n * @default ['authorization', 'cookie', 'x-api-key', 'x-auth-token']\n */\n redactHeaders?: string[];\n\n /**\n * Minimum duration in ms to log. Requests faster than this are not logged.\n * Useful for reducing log volume in high-traffic scenarios.\n * @default 0 (log all requests)\n */\n minDuration?: number;\n\n /**\n * Whether to include timestamp in log messages.\n * @default true\n */\n includeTimestamp?: boolean;\n\n /**\n * Custom log formatter for requests.\n * If provided, overrides the default request logging format.\n */\n formatRequest?: (ctx: RequestContext) => string;\n\n /**\n * Custom log formatter for responses.\n * If provided, overrides the default response logging format.\n */\n formatResponse?: <T>(ctx: ResponseContext<T>) => string;\n\n /**\n * Custom log formatter for errors.\n * If provided, overrides the default error logging format.\n */\n formatError?: (error: Error, ctx: RequestContext) => string;\n}\n\n/** Default headers to redact from logs */\nconst DEFAULT_REDACT_HEADERS = [\n 'authorization',\n 'cookie',\n 'x-api-key',\n 'x-auth-token',\n 'x-access-token',\n 'set-cookie',\n];\n\n/**\n * Format headers for logging, redacting sensitive values.\n */\nfunction formatHeaders(\n headers: Headers | HeadersInit | undefined,\n redactHeaders: string[]\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (!headers) {\n return result;\n }\n\n const headersObj = headers instanceof Headers ? headers : new Headers(headers);\n const redactSet = new Set(redactHeaders.map((h) => h.toLowerCase()));\n\n headersObj.forEach((value, key) => {\n const lowerKey = key.toLowerCase();\n if (redactSet.has(lowerKey)) {\n result[key] = '[REDACTED]';\n } else {\n result[key] = value;\n }\n });\n\n return result;\n}\n\n/**\n * Get current timestamp in ISO format.\n */\nfunction getTimestamp(): string {\n return new Date().toISOString();\n}\n\n/**\n * Extract HTTP method from request init.\n */\nfunction getMethod(init: RequestInit): string {\n return (init.method ?? 'GET').toUpperCase();\n}\n\n/**\n * Truncate body for logging if too long.\n */\nfunction truncateBody(body: unknown, maxLength: number = 1000): string {\n if (body === undefined || body === null) {\n return '';\n }\n\n let bodyStr: string;\n if (typeof body === 'string') {\n bodyStr = body;\n } else if (body instanceof FormData) {\n return '[FormData]';\n } else if (body instanceof Blob) {\n return `[Blob: ${body.size} bytes]`;\n } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n const size = body instanceof ArrayBuffer ? body.byteLength : body.byteLength;\n return `[Binary: ${size} bytes]`;\n } else if (body instanceof URLSearchParams) {\n bodyStr = body.toString();\n } else if (body instanceof ReadableStream) {\n return '[ReadableStream]';\n } else {\n try {\n bodyStr = JSON.stringify(body);\n } catch {\n return '[Unserializable]';\n }\n }\n\n if (bodyStr.length > maxLength) {\n return bodyStr.substring(0, maxLength) + `... (${bodyStr.length} chars total)`;\n }\n\n return bodyStr;\n}\n\n/**\n * Creates a logging middleware for debugging and monitoring.\n *\n * The middleware logs:\n * - Request method, URL, and optionally body/headers\n * - Response status, URL, and duration\n * - Errors with context\n *\n * Sensitive headers (Authorization, Cookie, etc.) are automatically redacted.\n *\n * @param options - Configuration options for the logging middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const loggingMiddleware = createLoggingMiddleware({\n * prefix: '[MyApp API]',\n * logBody: false,\n * logHeaders: true,\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With custom logger\n * const loggingMiddleware = createLoggingMiddleware({\n * logger: {\n * log: (msg, ...args) => myLogger.info(msg, ...args),\n * error: (msg, ...args) => myLogger.error(msg, ...args),\n * },\n * minDuration: 100, // Only log requests taking > 100ms\n * });\n * ```\n */\nexport function createLoggingMiddleware(options?: LoggingMiddlewareOptions): Middleware {\n const {\n logger = console,\n logBody = false,\n prefix = '[MPF SDK]',\n logHeaders = false,\n redactHeaders = DEFAULT_REDACT_HEADERS,\n minDuration = 0,\n includeTimestamp = true,\n formatRequest: customFormatRequest,\n formatResponse: customFormatResponse,\n formatError: customFormatError,\n } = options ?? {};\n\n /**\n * Build log prefix with optional timestamp.\n */\n function buildPrefix(): string {\n if (includeTimestamp) {\n return `${prefix} [${getTimestamp()}]`;\n }\n return prefix;\n }\n\n return {\n name: 'logging',\n\n onRequest(ctx: RequestContext): RequestContext {\n // Store start time and request info for response logging\n ctx.metadata['__requestStartTime'] = Date.now();\n ctx.metadata['__requestMethod'] = getMethod(ctx.init);\n ctx.metadata['__requestUrl'] = ctx.url;\n\n const method = ctx.metadata['__requestMethod'] as string;\n const logPrefix = buildPrefix();\n\n if (customFormatRequest) {\n logger.log(customFormatRequest(ctx));\n } else {\n const parts: string[] = [`${logPrefix} --> ${method} ${ctx.url}`];\n\n if (logHeaders && ctx.init.headers) {\n const headers = formatHeaders(ctx.init.headers, redactHeaders);\n parts.push(` Headers: ${JSON.stringify(headers)}`);\n }\n\n if (logBody && ctx.init.body) {\n const body = truncateBody(ctx.init.body);\n if (body) {\n parts.push(` Body: ${body}`);\n }\n }\n\n logger.log(parts.join('\\n'));\n }\n\n return ctx;\n },\n\n onResponse<T>(ctx: ResponseContext<T>): ResponseContext<T> {\n const startTime = ctx.metadata['__requestStartTime'] as number | undefined;\n const duration = startTime ? Date.now() - startTime : 0;\n\n // Skip logging if duration is below threshold\n if (duration < minDuration) {\n return ctx;\n }\n\n const method = (ctx.metadata['__requestMethod'] as string) || 'GET';\n const status = ctx.response.status;\n const statusText = ctx.response.statusText;\n const url = (ctx.metadata['__requestUrl'] as string) || ctx.response.url || '(unknown)';\n const logPrefix = buildPrefix();\n\n if (customFormatResponse) {\n logger.log(customFormatResponse(ctx));\n } else {\n const statusIcon = status >= 200 && status < 300 ? 'OK' : status >= 400 ? 'ERR' : 'WARN';\n const parts: string[] = [\n `${logPrefix} <-- ${method} ${url} ${status} ${statusText} (${duration}ms) [${statusIcon}]`,\n ];\n\n if (logHeaders) {\n const headers = formatHeaders(ctx.response.headers, redactHeaders);\n parts.push(` Headers: ${JSON.stringify(headers)}`);\n }\n\n if (logBody && ctx.data !== undefined) {\n const body = truncateBody(ctx.data);\n if (body) {\n parts.push(` Body: ${body}`);\n }\n }\n\n logger.log(parts.join('\\n'));\n }\n\n return ctx;\n },\n\n onError(error: Error, ctx: RequestContext): never {\n const startTime = ctx.metadata['__requestStartTime'] as number | undefined;\n const duration = startTime ? Date.now() - startTime : 0;\n const method = getMethod(ctx.init);\n const logPrefix = buildPrefix();\n\n if (customFormatError) {\n logger.error(customFormatError(error, ctx));\n } else {\n const parts: string[] = [\n `${logPrefix} <-- ${method} ${ctx.url} ERROR (${duration}ms)`,\n ` Error: ${error.name}: ${error.message}`,\n ];\n\n if (error.stack) {\n // Only include first 3 lines of stack trace\n const stackLines = error.stack.split('\\n').slice(1, 4);\n parts.push(` Stack: ${stackLines.join('\\n ')}`);\n }\n\n logger.error(parts.join('\\n'));\n }\n\n throw error;\n },\n };\n}\n","/**\n * URL building utilities for the MPF SDK\n */\n\n/**\n * Build a URL with query parameters\n *\n * @param baseUrl - The base URL\n * @param path - The path to append\n * @param params - Optional query parameters\n * @returns The full URL with query string\n */\nexport function buildUrl(\n baseUrl: string,\n path: string,\n params?: Record<string, string | number | boolean | undefined | null>\n): string {\n // Remove trailing slash from base URL\n const normalizedBase = baseUrl.replace(/\\/+$/, '');\n\n // Ensure path starts with a slash\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n\n const base = /^https?:\\/\\//.test(normalizedBase)\n ? normalizedBase\n : (typeof window !== 'undefined' ? window.location.origin : 'http://localhost');\n const url = new URL(`${normalizedBase}${normalizedPath}`, base);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n}\n\n/**\n * Join URL segments safely\n *\n * @param segments - URL segments to join\n * @returns Joined URL path\n */\nexport function joinPath(...segments: string[]): string {\n return segments\n .map((segment, index) => {\n // Remove leading slash except for first segment\n if (index > 0) {\n segment = segment.replace(/^\\/+/, '');\n }\n // Remove trailing slash except for last segment\n if (index < segments.length - 1) {\n segment = segment.replace(/\\/+$/, '');\n }\n return segment;\n })\n .filter(Boolean)\n .join('/');\n}\n","/**\n * GraphQL client that extends the base MPF client\n */\n\nimport { MPFClient } from '../core/client.js';\nimport type { ClientConfig } from '../core/types.js';\nimport type {\n TypedDocumentNode,\n GraphQLResponse,\n GraphQLRequestOptions,\n} from './types.js';\nimport { MPFAPIError } from '../core/errors.js';\n\n/**\n * Configuration options for the GraphQL client\n */\nexport interface GraphQLClientConfig extends ClientConfig {\n /**\n * GraphQL endpoint path (default: '/graphql')\n */\n endpoint?: string;\n}\n\n/**\n * GraphQL client for MPF services\n *\n * Supports both raw query strings and typed document nodes for type-safe operations.\n *\n * @example\n * ```typescript\n * const client = new MPFGraphQLClient({ baseUrl: 'https://api.example.com' });\n *\n * // Using raw query string\n * const result = await client.query(`\n * query GetUser($id: ID!) {\n * user(id: $id) { id name email }\n * }\n * `, { id: '123' });\n *\n * // Using typed document node (from codegen)\n * const typedResult = await client.query(GetUserDocument, { id: '123' });\n * ```\n */\nexport class MPFGraphQLClient extends MPFClient {\n /** The GraphQL endpoint path */\n protected graphqlEndpoint: string;\n\n constructor(config: GraphQLClientConfig) {\n super(config);\n this.graphqlEndpoint = config.endpoint ?? '/graphql';\n }\n\n /**\n * Execute a GraphQL query operation\n *\n * @param document - The GraphQL query (string or typed document node)\n * @param variables - Optional variables for the query\n * @param options - Optional request options (headers, signal)\n * @returns The query result data\n * @throws {MPFAPIError} When GraphQL errors occur or no data is returned\n */\n async query<TData, TVariables = Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n return this.executeOperation<TData, TVariables>(document, variables, options);\n }\n\n /**\n * Execute a GraphQL mutation operation\n *\n * @param document - The GraphQL mutation (string or typed document node)\n * @param variables - Optional variables for the mutation\n * @param options - Optional request options (headers, signal)\n * @returns The mutation result data\n * @throws {MPFAPIError} When GraphQL errors occur or no data is returned\n */\n async mutate<TData, TVariables = Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n return this.executeOperation<TData, TVariables>(document, variables, options);\n }\n\n /**\n * Execute a GraphQL operation (query or mutation)\n *\n * @internal\n */\n private async executeOperation<TData, TVariables>(\n document: TypedDocumentNode<TData, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions\n ): Promise<TData> {\n const query = typeof document === 'string' ? document : document.toString();\n\n const response = await this.post<GraphQLResponse<TData>>(\n this.graphqlEndpoint,\n { query, variables },\n options\n );\n\n // Handle GraphQL errors (they come in the response body, not HTTP status)\n if (response.errors && response.errors.length > 0) {\n const firstError = response.errors[0];\n const errorCode =\n (firstError.extensions?.code as string | undefined) ?? 'GRAPHQL_ERROR';\n\n throw new MPFAPIError(\n firstError.message,\n errorCode,\n 200,\n response.errors\n );\n }\n\n if (response.data === undefined || response.data === null) {\n throw new MPFAPIError(\n 'No data returned from GraphQL operation',\n 'NO_DATA',\n 200\n );\n }\n\n return response.data;\n }\n}\n","/**\n * Cheap operation-kind detection — no `graphql` parser dependency.\n *\n * The hybrid client only needs ONE bit: \"is this a subscription\". A full AST\n * parse (`graphql`'s `parse()` + `getOperationAST()`) would answer that too,\n * but it drags `graphql` into the HTTP-only path as a hard dependency, which\n * defeats the point of `graphql` staying an optional peer (see\n * `graphql/ws-client.ts`). A GraphQL document's operation keyword is always\n * the first non-trivia token — `query`/`mutation`/`subscription`, or omitted\n * entirely for the anonymous-query shorthand (`{ ... }`) — so a regex over the\n * leading trivia is exact, not a heuristic.\n */\n\n/** The three GraphQL operation kinds, plus `unknown` for an unparseable document. */\nexport type OperationKind = 'query' | 'mutation' | 'subscription' | 'unknown';\n\n/**\n * Strip GraphQL trivia (whitespace, commas, `#`-comments) from the START of a\n * document string, mirroring the lexer's own definition of \"ignored tokens\"\n * (GraphQL spec §2.1.4) closely enough to find the first real token.\n */\nfunction stripLeadingTrivia(source: string): string {\n let rest = source;\n for (;;) {\n const trimmed = rest.replace(/^[\\s,\\uFEFF]+/, '');\n if (trimmed.startsWith('#')) {\n const newline = trimmed.indexOf('\\n');\n rest = newline === -1 ? '' : trimmed.slice(newline + 1);\n continue;\n }\n if (trimmed !== rest) {\n rest = trimmed;\n continue;\n }\n return trimmed;\n }\n}\n\n/**\n * Determine a GraphQL document's operation kind from its source text.\n *\n * `{ ... }` (no keyword) is the anonymous-query shorthand and is always a\n * `query` — a `subscription` document is never allowed to omit its keyword,\n * per the GraphQL spec, so this cannot misclassify a subscription as a query.\n */\nexport function getOperationKind(document: string): OperationKind {\n const source = stripLeadingTrivia(document);\n\n if (source.startsWith('{')) {\n return 'query';\n }\n\n const match = /^(query|mutation|subscription)\\b/.exec(source);\n if (!match) {\n return 'unknown';\n }\n\n return match[1] as OperationKind;\n}\n\n/** Whether a GraphQL document is a subscription. */\nexport function isSubscription(document: string): boolean {\n return getOperationKind(document) === 'subscription';\n}\n","/**\n * The part of `./client` that reaches NO optional peer dependency.\n *\n * This file exists so the root barrel can expose a `client` namespace without\n * dragging `graphql-ws` into every consumer's module graph.\n *\n * `createGraphQLClient` (in `graphql/factory.ts`) and `createGraphQLWsTransport`\n * (in `graphql/ws-client.ts`) reach `graphql-ws`. It is only ever loaded through\n * a dynamic `import()`, so nothing breaks at runtime for an app that never\n * subscribes — but a *static* export chain from `src/index.ts` still puts those\n * modules (and the dynamic-import chunk a bundler emits for them) in the graph\n * of every consumer, including plain-HTTP ones. So they are reachable from the\n * `./client` subpath only, never from the root namespace.\n *\n * This is the same rule `./react` follows for its `react` peer. See\n * `tests/module-boundaries.test.ts` (\"depends on jose only\") for the guard.\n *\n * @packageDocumentation\n */\n\n// Core transport: client, middleware machinery, errors, shared types.\nexport * from './core/index.js';\n\n// Generic middlewares: auth, admin-auth, tenant, retry, logging, turnstile.\nexport * from './middlewares/index.js';\n\n// URL helpers.\nexport * from './utils/url.js';\n\n// GraphQL over plain HTTP. No optional peer involved: the request goes through\n// the same `fetch` path as every other client.\nexport { MPFGraphQLClient, type GraphQLClientConfig } from './graphql/client.js';\nexport type {\n TypedDocumentNode,\n GraphQLError,\n GraphQLResponse,\n GraphQLRequestOptions,\n} from './graphql/types.js';\n\n// Pure string inspection of a GraphQL document — no dependencies at all.\nexport { getOperationKind, isSubscription, type OperationKind } from './graphql/operation.js';\n"]}
@@ -1,4 +1,4 @@
1
- import { MPFAPIError, MPFAuthError, MPFNetworkError, MPFError, tryDecodeAccessToken } from './chunk-AJWM5MDZ.js';
1
+ import { MPFAPIError, MPFAuthError, MPFNetworkError, MPFError, tryDecodeAccessToken } from './chunk-S5DKGPUY.js';
2
2
 
3
3
  // src/client/core/middleware.ts
4
4
  async function executeRequestMiddlewares(middlewares, ctx) {
@@ -612,5 +612,5 @@ function createHttpClient(options) {
612
612
  }
613
613
 
614
614
  export { MAX_REQUEST_ATTEMPTS, MPFClient, TENANT_HEADER, TENANT_ROLE_HEADER, attachStandardMiddlewares, clearRetryFlag, createAuthMiddleware, createHttpClient, createRetryMiddleware, createTenantMiddleware, disableRetry, executeErrorMiddlewares, executeRequestMiddlewares, executeResponseMiddlewares, getRetryAttempt, isReplayableBody, isRetryDisabled, requestRetry, shouldRetryRequest };
615
- //# sourceMappingURL=chunk-LRM6JJ63.js.map
616
- //# sourceMappingURL=chunk-LRM6JJ63.js.map
615
+ //# sourceMappingURL=chunk-3OKR4MSV.js.map
616
+ //# sourceMappingURL=chunk-3OKR4MSV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/core/middleware.ts","../src/client/middlewares/retry.ts","../src/client/core/client.ts","../src/client/middlewares/auth.ts","../src/client/middlewares/tenant.ts","../src/client/core/client-factory.ts"],"names":["text"],"mappings":"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","file":"chunk-LRM6JJ63.js","sourcesContent":["/**\n * Middleware system for request/response interceptors\n */\n\nimport type { RequestContext, ResponseContext } from './types.js';\n\n/**\n * Middleware interface for intercepting requests and responses\n */\nexport interface Middleware {\n /** Unique identifier for the middleware */\n name: string;\n\n /**\n * Called before the request is sent\n * Can modify the request context or throw to abort\n */\n onRequest?: (ctx: RequestContext) => Promise<RequestContext> | RequestContext;\n\n /**\n * Called after a successful response is received\n * Can modify the response context or throw to trigger error handling\n */\n onResponse?: <T>(ctx: ResponseContext<T>) => Promise<ResponseContext<T>> | ResponseContext<T>;\n\n /**\n * Called when an error occurs during the request lifecycle\n * Can transform the error or re-throw\n */\n onError?: (error: Error, ctx: RequestContext) => Promise<never> | never;\n}\n\n/**\n * Execute the request middleware chain in order\n *\n * Middlewares are executed in the order they were added.\n * Each middleware can modify the context before passing it to the next.\n *\n * @param middlewares - Array of middlewares to execute\n * @param ctx - Initial request context\n * @returns Modified request context after all middlewares\n */\nexport async function executeRequestMiddlewares(\n middlewares: Middleware[],\n ctx: RequestContext\n): Promise<RequestContext> {\n let currentCtx = ctx;\n\n for (const middleware of middlewares) {\n if (middleware.onRequest) {\n currentCtx = await middleware.onRequest(currentCtx);\n }\n }\n\n return currentCtx;\n}\n\n/**\n * Execute the response middleware chain in reverse order\n *\n * Middlewares are executed in reverse order (last added runs first).\n * This allows middlewares to \"unwrap\" their effects in the correct order.\n *\n * @param middlewares - Array of middlewares to execute\n * @param ctx - Initial response context\n * @returns Modified response context after all middlewares\n */\nexport async function executeResponseMiddlewares<T>(\n middlewares: Middleware[],\n ctx: ResponseContext<T>\n): Promise<ResponseContext<T>> {\n let currentCtx = ctx;\n\n // Execute in reverse order for response processing\n for (let i = middlewares.length - 1; i >= 0; i--) {\n const middleware = middlewares[i];\n if (middleware.onResponse) {\n currentCtx = await middleware.onResponse(currentCtx);\n }\n }\n\n return currentCtx;\n}\n\n/**\n * Execute error handlers in the middleware chain\n *\n * EVERY middleware's `onError` handler runs, in registration order. Because\n * `onError` is typed `never` it signals completion by throwing, so a thrown\n * error is its normal exit path and must NOT terminate the chain — otherwise\n * the first handler that throws (e.g. the retry middleware, which always\n * throws) would silently swallow every handler registered after it.\n *\n * A handler may transform the error by throwing a different one; the\n * transformed error is passed to the remaining handlers and is what finally\n * propagates to the caller.\n *\n * @param middlewares - Array of middlewares to try\n * @param error - The error that occurred\n * @param ctx - The request context when the error occurred\n * @throws The original or transformed error\n */\nexport async function executeErrorMiddlewares(\n middlewares: Middleware[],\n error: Error,\n ctx: RequestContext\n): Promise<never> {\n let currentError = error;\n\n for (const middleware of middlewares) {\n if (!middleware.onError) {\n continue;\n }\n\n try {\n await middleware.onError(currentError, ctx);\n } catch (thrown) {\n // Throwing is how an `onError` handler returns. Adopt a transformed\n // error (if any) and continue so later handlers still observe it.\n if (thrown instanceof Error) {\n currentError = thrown;\n }\n }\n }\n\n throw currentError;\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport { MPFError, MPFAPIError } from '../core/errors.js';\n\n/**\n * Options for the retry middleware.\n */\nexport interface RetryMiddlewareOptions {\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Base delay in milliseconds between retries.\n * With exponential backoff, actual delay = retryDelay * (backoffFactor ^ attemptNumber)\n * @default 1000\n */\n retryDelay?: number;\n\n /**\n * HTTP status codes that trigger a retry.\n * @default [408, 429, 500, 502, 503, 504]\n */\n retryOn?: number[];\n\n /**\n * Exponential backoff factor.\n * Each retry waits: retryDelay * (backoffFactor ^ attemptNumber)\n * @default 2\n */\n backoffFactor?: number;\n\n /**\n * Maximum delay in milliseconds between retries (caps exponential growth).\n * @default 30000 (30 seconds)\n */\n maxDelay?: number;\n\n /**\n * Whether to add random jitter to retry delays (prevents thundering herd).\n * When enabled, adds random jitter up to 25% of the calculated delay.\n * @default true\n */\n jitter?: boolean;\n\n /**\n * Optional callback called before each retry attempt.\n * Can be used for logging or metrics.\n */\n onRetry?: (attempt: number, error: Error, delay: number) => void | Promise<void>;\n\n /**\n * Custom function to determine if an error should trigger a retry.\n * If provided, this takes precedence over retryOn status codes.\n */\n shouldRetry?: (error: Error, attempt: number) => boolean;\n}\n\n/** Metadata key for storing retry attempt count */\nconst RETRY_ATTEMPT_KEY = '__retryAttempt';\n\n/** Metadata key set by the retry middleware to request another attempt */\nconst SHOULD_RETRY_KEY = '__shouldRetry';\n\n/**\n * Metadata key marking a request as non-retryable regardless of what any\n * middleware asks for (e.g. a one-shot streaming body that cannot be re-sent).\n */\nconst NO_RETRY_KEY = '__noRetry';\n\n/**\n * Default HTTP status codes that should trigger a retry.\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nconst DEFAULT_RETRY_STATUS_CODES = [408, 429, 500, 502, 503, 504];\n\n/**\n * Sleep for a specified duration.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay with exponential backoff and optional jitter.\n */\nfunction calculateDelay(\n attempt: number,\n baseDelay: number,\n backoffFactor: number,\n maxDelay: number,\n useJitter: boolean\n): number {\n // Calculate exponential delay: baseDelay * (factor ^ attempt)\n const exponentialDelay = baseDelay * Math.pow(backoffFactor, attempt);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter (0-25% of the delay) to prevent thundering herd\n if (useJitter) {\n const jitterFactor = 1 + Math.random() * 0.25;\n return Math.floor(cappedDelay * jitterFactor);\n }\n\n return Math.floor(cappedDelay);\n}\n\n/**\n * Creates a retry middleware with exponential backoff.\n *\n * The middleware:\n * - Automatically retries failed requests based on HTTP status codes\n * - Uses exponential backoff to space out retry attempts\n * - Optionally adds jitter to prevent thundering herd problems\n * - Respects Retry-After headers when present\n *\n * @param options - Configuration options for the retry middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const retryMiddleware = createRetryMiddleware({\n * maxRetries: 3,\n * retryDelay: 1000,\n * retryOn: [500, 502, 503, 504],\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With custom retry logic\n * const retryMiddleware = createRetryMiddleware({\n * maxRetries: 5,\n * retryDelay: 500,\n * backoffFactor: 1.5,\n * jitter: true,\n * onRetry: (attempt, error, delay) => {\n * console.log(`Retry attempt ${attempt} after ${delay}ms:`, error.message);\n * },\n * shouldRetry: (error, attempt) => {\n * // Custom retry logic\n * if (error instanceof MPFError && error.status) {\n * return error.status >= 500 && attempt < 3;\n * }\n * return false;\n * }\n * });\n * ```\n */\nexport function createRetryMiddleware(options?: RetryMiddlewareOptions): Middleware {\n const {\n maxRetries = 3,\n retryDelay = 1000,\n retryOn = DEFAULT_RETRY_STATUS_CODES,\n backoffFactor = 2,\n maxDelay = 30000,\n jitter = true,\n onRetry,\n shouldRetry: customShouldRetry,\n } = options ?? {};\n\n /**\n * Determine if an error should trigger a retry.\n */\n function shouldRetry(error: Error, attempt: number): boolean {\n // Don't retry if we've exhausted attempts\n if (attempt >= maxRetries) {\n return false;\n }\n\n // Use custom retry logic if provided\n if (customShouldRetry) {\n return customShouldRetry(error, attempt);\n }\n\n // Check if it's an MPF error with a retryable status code\n if (error instanceof MPFError && error.status !== undefined) {\n return retryOn.includes(error.status);\n }\n\n // Retry on network errors (no status code)\n if (error.name === 'TypeError' && error.message.includes('fetch')) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Get delay from Retry-After header if present.\n * Note: This requires the error to have a retryAfter property or be passed separately.\n * For MPFAPIError, we check the details for a retryAfter value.\n */\n function getRetryAfterDelay(error: Error): number | null {\n // Check if error has details with retryAfter (from API response)\n if (error instanceof MPFAPIError && error.details) {\n const details = error.details as Record<string, unknown>;\n const retryAfter = details['retryAfter'] || details['retry-after'] || details['Retry-After'];\n\n if (typeof retryAfter === 'number') {\n return retryAfter * 1000;\n }\n\n if (typeof retryAfter === 'string') {\n // Retry-After can be seconds or a date string\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n\n // Try parsing as date\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n const delay = date.getTime() - Date.now();\n return delay > 0 ? delay : null;\n }\n }\n }\n\n return null;\n }\n\n return {\n name: 'retry',\n\n onRequest(ctx: RequestContext): RequestContext {\n // Initialize retry attempt counter if not present\n if (ctx.metadata[RETRY_ATTEMPT_KEY] === undefined) {\n ctx.metadata[RETRY_ATTEMPT_KEY] = 0;\n }\n return ctx;\n },\n\n async onError(error: Error, ctx: RequestContext): Promise<never> {\n const currentAttempt = (ctx.metadata[RETRY_ATTEMPT_KEY] as number) ?? 0;\n\n if (!shouldRetry(error, currentAttempt)) {\n throw error;\n }\n\n // Calculate delay\n let delay = getRetryAfterDelay(error);\n if (delay === null) {\n delay = calculateDelay(currentAttempt, retryDelay, backoffFactor, maxDelay, jitter);\n }\n\n // Cap Retry-After delay at maxDelay\n delay = Math.min(delay, maxDelay);\n\n // Call onRetry callback if provided\n if (onRetry) {\n try {\n await onRetry(currentAttempt + 1, error, delay);\n } catch (callbackError) {\n // Log but don't fail the retry\n console.error('[MPF SDK] Error in onRetry callback:', callbackError);\n }\n }\n\n // Wait before retrying\n await sleep(delay);\n\n // Increment attempt counter\n ctx.metadata[RETRY_ATTEMPT_KEY] = currentAttempt + 1;\n\n // Mark that this request should be retried.\n // MPFClient.request() checks this flag after the error middleware chain\n // has run and starts another attempt when it is set.\n requestRetry(ctx);\n\n // Re-throw to signal the SDK to retry\n // The SDK should catch this and check __shouldRetry\n throw error;\n },\n };\n}\n\n/**\n * Check if a request context indicates a retry should be attempted.\n * Used by `MPFClient.request()` to decide whether to run another attempt.\n *\n * Returns false when the request has been marked non-retryable, even if a\n * middleware asked for a retry.\n */\nexport function shouldRetryRequest(ctx: RequestContext): boolean {\n return ctx.metadata[SHOULD_RETRY_KEY] === true && !isRetryDisabled(ctx);\n}\n\n/**\n * Ask `MPFClient.request()` to run another attempt.\n *\n * The single writer of the retry flag. Any middleware that can recover from an\n * error (the auth middleware's renew-and-retry, for instance) calls this from\n * its `onError` and then rethrows.\n *\n * The client consults the flag unconditionally, so this works whether or not\n * `createRetryMiddleware` is registered.\n */\nexport function requestRetry(ctx: RequestContext): void {\n ctx.metadata[SHOULD_RETRY_KEY] = true;\n}\n\n/**\n * Mark a request as non-retryable. Used for request bodies that cannot be\n * re-sent (a `ReadableStream` is consumed by the first attempt).\n */\nexport function disableRetry(ctx: RequestContext): void {\n ctx.metadata[NO_RETRY_KEY] = true;\n}\n\n/**\n * Whether the request has been marked non-retryable.\n */\nexport function isRetryDisabled(ctx: RequestContext): boolean {\n return ctx.metadata[NO_RETRY_KEY] === true;\n}\n\n/**\n * Whether a fetch body can be sent more than once.\n *\n * `FormData`, `Blob`, `ArrayBuffer`, `URLSearchParams` and strings are all\n * re-readable, so retrying them is safe. A `ReadableStream` is consumed by the\n * first attempt and must never be retried.\n */\nexport function isReplayableBody(body: BodyInit | null | undefined): boolean {\n if (body === null || body === undefined) {\n return true;\n }\n\n if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get the current retry attempt number from request context.\n */\nexport function getRetryAttempt(ctx: RequestContext): number {\n return (ctx.metadata[RETRY_ATTEMPT_KEY] as number) ?? 0;\n}\n\n/**\n * Clear the retry flag from the request context.\n * Should be called after a successful retry or when giving up.\n */\nexport function clearRetryFlag(ctx: RequestContext): void {\n delete ctx.metadata[SHOULD_RETRY_KEY];\n}\n","/**\n * Base HTTP client for the MPF SDK\n */\n\nimport type { ClientConfig, RequestOptions, RequestContext, ResponseContext, APIErrorResponse } from './types.js';\nimport type { Middleware } from './middleware.js';\nimport { executeRequestMiddlewares, executeResponseMiddlewares, executeErrorMiddlewares } from './middleware.js';\nimport { MPFNetworkError, MPFAPIError, MPFAuthError } from './errors.js';\nimport { shouldRetryRequest, clearRetryFlag, disableRetry, isReplayableBody } from '../middlewares/retry.js';\n\n/**\n * Hard ceiling on the number of attempts a single `request()` call may make\n * (the initial attempt plus retries).\n *\n * This is deliberately independent of any middleware's own `maxRetries`: a\n * misbehaving or misconfigured middleware can keep asking for retries, and this\n * bound guarantees the loop terminates. 4 attempts = 1 initial + 3 retries,\n * matching the retry middleware's default `maxRetries: 3`.\n */\nexport const MAX_REQUEST_ATTEMPTS = 4;\n\n/**\n * Base client for making HTTP requests with middleware support\n */\nexport class MPFClient {\n protected readonly baseUrl: string;\n protected readonly defaultHeaders: Record<string, string>;\n protected readonly middlewares: Middleware[];\n\n constructor(config: ClientConfig) {\n // Remove trailing slash from base URL for consistent URL building\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultHeaders = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n };\n this.middlewares = [...(config.middlewares ?? [])];\n }\n\n /**\n * Add a middleware to the client\n * Middlewares are executed in the order they are added for requests,\n * and in reverse order for responses.\n *\n * @param middleware - The middleware to add\n * @returns The client instance for chaining\n */\n use(middleware: Middleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n /**\n * Build a full URL with query parameters\n *\n * @param path - The API path (e.g., \"/users\" or \"users\")\n * @param params - Optional query parameters\n * @returns The full URL with query string\n */\n protected buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {\n // Ensure path starts with a slash\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n const base = /^https?:\\/\\//.test(this.baseUrl)\n ? this.baseUrl\n : (typeof window !== 'undefined' ? window.location.origin : 'http://localhost');\n const url = new URL(`${this.baseUrl}${normalizedPath}`, base);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n /**\n * Merge headers from different sources\n *\n * @param requestHeaders - Headers specific to this request\n * @returns Merged headers object\n */\n protected mergeHeaders(requestHeaders?: Record<string, string>): Record<string, string> {\n return {\n ...this.defaultHeaders,\n ...requestHeaders,\n };\n }\n\n /**\n * Build the headers for a single attempt.\n *\n * Rebuilt per attempt so request middlewares (auth, turnstile, ...) always\n * inject a fresh token instead of replaying a stale one.\n *\n * For a `FormData` body the default JSON `Content-Type` is dropped so that\n * fetch sets `multipart/form-data` with the correct boundary.\n */\n private buildAttemptHeaders(init: RequestInit): Record<string, string> {\n const headers = this.mergeHeaders(init.headers as Record<string, string> | undefined);\n\n if (typeof FormData !== 'undefined' && init.body instanceof FormData) {\n delete headers['Content-Type'];\n }\n\n return headers;\n }\n\n /**\n * Parse the response body based on content type\n *\n * @param response - The fetch Response object\n * @returns Parsed response data\n */\n protected async parseResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type') ?? '';\n\n // Handle empty responses (204 No Content, etc.)\n if (response.status === 204 || response.headers.get('content-length') === '0') {\n return undefined as T;\n }\n\n // Parse JSON responses\n if (contentType.includes('application/json')) {\n const text = await response.text();\n if (!text) {\n return undefined as T;\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new MPFAPIError(\n 'Failed to parse JSON response',\n 'PARSE_ERROR',\n response.status,\n { text }\n );\n }\n }\n\n // Return text for non-JSON responses\n const text = await response.text();\n return text as T;\n }\n\n /**\n * Handle error responses from the API\n *\n * @param response - The fetch Response object\n * @throws MPFAuthError for 401/403, MPFAPIError for other errors\n */\n protected async handleErrorResponse(response: Response): Promise<never> {\n let body: unknown;\n let errorResponse: APIErrorResponse | undefined;\n\n try {\n const text = await response.text();\n if (text) {\n body = JSON.parse(text);\n errorResponse = body as APIErrorResponse;\n }\n } catch {\n // Body is not JSON, that's fine\n }\n\n const message = errorResponse?.message ?? errorResponse?.error ?? response.statusText ?? 'Request failed';\n const code = errorResponse?.code ?? `HTTP_${response.status}`;\n const details = errorResponse?.details;\n\n // Handle authentication errors\n if (response.status === 401) {\n const authType = code.toLowerCase().includes('expired') ? 'token_expired' : 'unauthorized';\n // Preserve the server's own code: `authType` collapses distinct 401s\n // (notably REFRESH_TOKEN_SUPERSEDED) into 'unauthorized'.\n throw new MPFAuthError(message, authType, 401, details, errorResponse?.code);\n }\n\n if (response.status === 403) {\n throw new MPFAuthError(message, 'forbidden', 403, details, errorResponse?.code);\n }\n\n // Handle all other errors\n throw new MPFAPIError(message, code, response.status, details, body);\n }\n\n /**\n * Execute an HTTP request with the full middleware chain, retrying when a\n * middleware asks for it.\n *\n * Retry contract:\n * - `metadata` is created once and shared by every attempt. Middlewares keep\n * their per-request state there (retry counter, auth-renew flag); rebuilding\n * it per attempt would reset those counters and loop forever.\n * - `init.headers` are rebuilt per attempt so request middlewares re-inject a\n * fresh token rather than replaying the first attempt's headers.\n * - `MAX_REQUEST_ATTEMPTS` bounds the loop regardless of middleware config.\n * - Bodies that cannot be re-sent (`ReadableStream`) disable retrying.\n *\n * @param path - The API path\n * @param init - Fetch RequestInit options\n * @returns The parsed response data\n * @throws MPFNetworkError for network failures\n * @throws MPFAuthError for 401/403 responses\n * @throws MPFAPIError for other error responses\n */\n async request<T>(path: string, init: RequestInit = {}, params?: Record<string, string | number | boolean | undefined>, options?: RequestOptions): Promise<T> {\n const url = this.buildUrl(path, params);\n\n // Shared across every attempt — see the retry contract above.\n const metadata: Record<string, unknown> = {};\n\n for (let attempt = 0; attempt < MAX_REQUEST_ATTEMPTS; attempt++) {\n const requestCtx: RequestContext = {\n url,\n init: {\n ...init,\n headers: this.buildAttemptHeaders(init),\n },\n metadata,\n options,\n };\n\n if (!isReplayableBody(init.body)) {\n disableRetry(requestCtx);\n }\n\n try {\n return await this.attempt<T>(requestCtx);\n } catch (error) {\n // The error middleware chain already ran inside attempt(); a retry\n // middleware has had its chance to set the retry flag (and to sleep for\n // its backoff) by now.\n const isLastAttempt = attempt === MAX_REQUEST_ATTEMPTS - 1;\n\n if (isLastAttempt || !shouldRetryRequest(requestCtx)) {\n throw error;\n }\n\n clearRetryFlag(requestCtx);\n }\n }\n\n // Unreachable: the loop either returns or throws on the last attempt.\n throw new MPFNetworkError('Request retry loop exhausted');\n }\n\n /**\n * Execute a single request attempt through the middleware chain.\n *\n * On failure the error middleware chain runs before the error propagates, so\n * the caller can inspect `ctx.metadata` for a retry request.\n */\n private async attempt<T>(ctx: RequestContext): Promise<T> {\n let requestCtx = ctx;\n\n try {\n // Execute request middlewares\n requestCtx = await executeRequestMiddlewares(this.middlewares, requestCtx);\n\n // Make the actual fetch request\n let response: Response;\n try {\n response = await fetch(requestCtx.url, requestCtx.init);\n } catch (error) {\n throw new MPFNetworkError(\n error instanceof Error ? error.message : 'Network request failed',\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle error responses\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n // Parse successful response\n const data = await this.parseResponse<T>(response);\n\n // Build response context\n let responseCtx: ResponseContext<T> = {\n response,\n data,\n metadata: requestCtx.metadata,\n };\n\n // Execute response middlewares\n responseCtx = await executeResponseMiddlewares(this.middlewares, responseCtx);\n\n return responseCtx.data;\n } catch (error) {\n try {\n // Execute error middlewares if available\n if (error instanceof Error && this.middlewares.some(m => m.onError)) {\n await executeErrorMiddlewares(this.middlewares, error, requestCtx);\n }\n throw error;\n } finally {\n // A request middleware may have returned a cloned context; make sure\n // any metadata it wrote (including the retry flag) reaches the caller's\n // shared metadata object.\n if (requestCtx.metadata !== ctx.metadata) {\n Object.assign(ctx.metadata, requestCtx.metadata);\n }\n }\n }\n }\n\n /**\n * Make a GET request\n *\n * @param path - The API path\n * @param options - Request options\n * @returns The parsed response data\n */\n async get<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'GET',\n headers: options.headers,\n signal: options.signal,\n }, options.params, options);\n }\n\n /**\n * Make a POST request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async post<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a PUT request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async put<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'PUT',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a PATCH request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async patch<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a DELETE request\n *\n * @param path - The API path\n * @param body - Optional request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async delete<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'DELETE',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport { MPFError } from '../core/errors.js';\nimport { requestRetry } from './retry.js';\n\n/**\n * Metadata key: set in `onRequest` only when an Authorization header was\n * actually injected.\n *\n * This is the wrong-password guard. Without it, a 401 from `signIn` (bad\n * credentials, `skipAuth`, no token yet) is indistinguishable from a 401 caused\n * by an expired session, and every consumer ends up reimplementing the same\n * check in app code — usually by string-matching an error message. Keying off\n * \"did we send a token\" makes it structural.\n */\nconst TOKEN_ATTACHED_KEY = '__authTokenAttached';\n\n/**\n * Metadata key: set BEFORE awaiting the renew, capping renewal at one attempt\n * per logical request no matter how many times the retry loop runs.\n *\n * Set before rather than after the await because two concurrent error handlers\n * on the same request would otherwise both observe \"not attempted\" and both\n * renew — and the refresh token is single-use, so the second renew kills the\n * session it was trying to save.\n */\nconst RENEW_ATTEMPTED_KEY = '__authRenewAttempted';\n\n/**\n * Options for the auth middleware.\n */\nexport interface AuthMiddlewareOptions {\n /**\n * Function to get the current access token.\n * Can be sync or async (e.g., reading from localStorage or refreshing token).\n *\n * @returns The access token, or null if not authenticated\n */\n getAccessToken: () => string | null | Promise<string | null>;\n\n /**\n * Called when a 401 is final — i.e. a token WAS attached and renewal either\n * was not possible, failed, or had already been tried for this request.\n *\n * This is the \"log the user out\" hook. It is deliberately NOT called for a\n * 401 on a request that carried no token (a wrong password must not log you\n * out of a session you do have), nor for the first 401 when `onUnauthorized`\n * successfully renews.\n */\n onTokenExpired?: () => void | Promise<void>;\n\n /**\n * Called on the first 401 of a request that DID carry a token.\n *\n * Should attempt a session renewal and resolve `true` when a fresh token is\n * now available, `false` otherwise. On `true` the request is retried once,\n * with headers rebuilt so the new token is picked up.\n *\n * Capped at one call per logical request by `__authRenewAttempted`, so a\n * second 401 falls through to `onTokenExpired` instead of looping.\n */\n onUnauthorized?: () => Promise<boolean>;\n\n /**\n * The token type prefix for the Authorization header.\n * @default 'Bearer'\n */\n tokenType?: string;\n\n /**\n * Custom header name for the authorization token.\n * @default 'Authorization'\n */\n headerName?: string;\n}\n\n/**\n * Creates an authentication middleware that adds authorization headers to requests.\n *\n * The middleware:\n * - Adds an Authorization header with the token from getAccessToken()\n * - Calls onTokenExpired() when a 401 response is received\n *\n * @param options - Configuration options for the auth middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const authMiddleware = createAuthMiddleware({\n * getAccessToken: () => localStorage.getItem('accessToken'),\n * onTokenExpired: () => {\n * // Redirect to login or refresh token\n * window.location.href = '/login';\n * }\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With async token retrieval\n * const authMiddleware = createAuthMiddleware({\n * getAccessToken: async () => {\n * const session = await authService.getSession();\n * return session?.accessToken ?? null;\n * },\n * tokenType: 'Bearer',\n * onTokenExpired: async () => {\n * await authService.refreshToken();\n * }\n * });\n * ```\n */\nexport function createAuthMiddleware(options: AuthMiddlewareOptions): Middleware {\n const {\n getAccessToken,\n onTokenExpired,\n onUnauthorized,\n tokenType = 'Bearer',\n headerName = 'Authorization',\n } = options;\n\n return {\n name: 'auth',\n\n async onRequest(ctx: RequestContext): Promise<RequestContext> {\n if (ctx.options?.skipAuth) {\n return ctx;\n }\n\n const token = await getAccessToken();\n\n if (token) {\n // Create a new Headers object to avoid mutating the original\n const headers = new Headers(ctx.init.headers);\n headers.set(headerName, `${tokenType} ${token}`);\n ctx.init.headers = headers;\n\n // Record that THIS attempt actually carried a token.\n ctx.metadata[TOKEN_ATTACHED_KEY] = true;\n }\n\n return ctx;\n },\n\n async onError(error: Error, ctx: RequestContext): Promise<never> {\n // Key off the numeric status, not the error's classification string: the\n // classification is derived from a server-supplied code and is not a\n // reliable discriminator.\n const status = error instanceof MPFError ? error.status : undefined;\n if (status !== 401) {\n throw error;\n }\n\n // Guard 1: no token was attached, so this 401 is about the credentials in\n // the request body (wrong password, expired invite, ...) and says nothing\n // about session health. Do not renew and do not log anyone out.\n if (ctx.metadata[TOKEN_ATTACHED_KEY] !== true) {\n throw error;\n }\n\n // Guard 2: at most one renewal per logical request. Set before awaiting.\n if (onUnauthorized && ctx.metadata[RENEW_ATTEMPTED_KEY] !== true) {\n ctx.metadata[RENEW_ATTEMPTED_KEY] = true;\n\n let renewed = false;\n try {\n renewed = await onUnauthorized();\n } catch (renewError) {\n console.error('[MPF SDK] Error in onUnauthorized callback:', renewError);\n renewed = false;\n }\n\n if (renewed) {\n // Retry once. The client rebuilds headers per attempt, so the fresh\n // token is picked up automatically.\n requestRetry(ctx);\n throw error;\n }\n }\n\n // The 401 is final: renewal was impossible, failed, or already tried.\n if (onTokenExpired) {\n try {\n await onTokenExpired();\n } catch (callbackError) {\n // Log but don't swallow the original error\n console.error('[MPF SDK] Error in onTokenExpired callback:', callbackError);\n }\n }\n\n // Always re-throw the original error\n throw error;\n },\n };\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport type { MPFRole } from '../../auth/claims-types.js';\nimport type { TenantSelectionStore } from '../../auth/tenant-selection.js';\nimport { tryDecodeAccessToken } from '../../auth/claims.js';\n\n/** Header carrying the selected tenant id. */\nexport const TENANT_HEADER = 'X-MPF-Tenant';\n\n/** Header carrying the selected role within that tenant. */\nexport const TENANT_ROLE_HEADER = 'X-MPF-Tenant-Role';\n\n/**\n * Options for the tenant middleware.\n */\nexport interface TenantMiddlewareOptions {\n /**\n * The shared tenant selection. Read per request, so a `set()` takes effect on\n * the next request with no client reconstruction.\n */\n tenantProvider?: TenantSelectionStore;\n\n /**\n * Access-token getter, used ONLY for the under-scoping warning below. When\n * omitted the warning is disabled.\n *\n * Decoding is LRU-cached, and the warning fires at most once per middleware,\n * so this costs nothing in steady state.\n */\n getAccessToken?: () => string | null | Promise<string | null>;\n\n /**\n * Whether to warn once when a request goes out unscoped while the token holds\n * tenants.\n * @default true\n */\n warnOnUnscoped?: boolean;\n\n /** Logger for the warning. Defaults to `console`. */\n logger?: { warn: (message: string, ...args: unknown[]) => void };\n}\n\nconst UNSCOPED_WARNING =\n '[MPF SDK] Request sent with no tenant selected, but the access token holds tenant ' +\n 'memberships. The server will scope this request to the default (tenantless) role, ' +\n 'which usually means empty results or a 403 rather than tenant data. Wire a ' +\n 'tenantProvider (createTenantSelection()) into your client and call set(tenantId), ' +\n 'or pass `{ tenant: null }` on the request to state explicitly that it is unscoped. ' +\n 'This warning is shown once.';\n\n/**\n * Creates a middleware that puts the selected tenant on the wire.\n *\n * Resolution order for the tenant, using the three states of\n * `options.tenant`:\n *\n * | `options.tenant` | meaning |\n * |-------------------|--------------------------------------------|\n * | `undefined` | inherit the client-wide selection |\n * | `null` | deliberately unscoped for THIS request |\n * | `\"<uuid>\"` | that tenant, for THIS request |\n *\n * `options.skipTenant` bypasses the middleware entirely.\n *\n * Header rules:\n * - The tenant header is **omitted entirely** when there is no tenant. An\n * empty-string header is a 400 server-side, deliberately, so that a bug\n * cannot masquerade as the no-tenant path.\n * - The role header is omitted unless a role was specified, letting the server\n * apply that tenant's default role (its `dfr`, or `rls[0]` when it has\n * none).\n * - A per-request tenant does NOT inherit the client-wide role: the role only\n * travels with the selection it belongs to. Selecting tenant B while tenant\n * A's role is selected must not send A's role to B.\n */\nexport function createTenantMiddleware(options: TenantMiddlewareOptions = {}): Middleware {\n const {\n tenantProvider,\n getAccessToken,\n warnOnUnscoped = true,\n logger = console,\n } = options;\n\n let warned = false;\n\n async function maybeWarnUnscoped(): Promise<void> {\n if (warned || !warnOnUnscoped || !getAccessToken) {\n return;\n }\n\n // Mark first: a failure below must not turn this into a per-request cost,\n // and the warning is best-effort diagnostics.\n let token: string | null;\n try {\n token = await getAccessToken();\n } catch {\n return;\n }\n\n const claims = tryDecodeAccessToken(token);\n if (!claims || claims.tnts.length === 0) {\n return;\n }\n\n warned = true;\n logger.warn(UNSCOPED_WARNING);\n }\n\n return {\n name: 'tenant',\n\n async onRequest(ctx: RequestContext): Promise<RequestContext> {\n if (ctx.options?.skipTenant) {\n return ctx;\n }\n\n const perRequest = ctx.options?.tenant;\n const inherit = perRequest === undefined;\n const selection = inherit ? tenantProvider?.get() : undefined;\n\n const tenant: string | null = inherit ? (selection?.tenant ?? null) : perRequest;\n\n // Role travels with its own selection; see the note above.\n const role: MPFRole | undefined =\n ctx.options?.tenantRole ?? (inherit ? selection?.role : undefined);\n\n if (tenant === null || tenant === '') {\n // Warn only when the request is unscoped by OMISSION, never when the\n // caller passed `{ tenant: null }`. Explicit null is a developer stating\n // intent; `undefined` with a tenant-bearing token is the oversight we\n // are trying to catch. Warning on the deliberate case would train people\n // to ignore the warning and cost us the signal in the case that matters\n // — which is the whole reason `undefined | null | string` is three-state.\n if (inherit) {\n await maybeWarnUnscoped();\n }\n return ctx;\n }\n\n const headers = new Headers(ctx.init.headers);\n headers.set(TENANT_HEADER, tenant);\n if (role !== undefined && role !== '') {\n headers.set(TENANT_ROLE_HEADER, role);\n }\n ctx.init.headers = headers;\n\n return ctx;\n },\n };\n}\n","/**\n * Generic HTTP client factory.\n *\n * `createAuthClient`, `createStorageClient` and `createGraphQLClient` all wire\n * the SAME two middlewares (auth, tenant) by hand today, which is how they\n * drift: three copies of \"if tokenProvider, use(createAuthMiddleware(...))\".\n * This is the single place that wiring happens now; the three factories\n * become thin wrappers that just pick the right `MPFClient` subclass.\n *\n * The point of pulling this out is reuse, NOT a new concept: a `tokenProvider`\n * here is still just `{ getAccessToken, onTokenExpired?, onUnauthorized? }` —\n * typically `{ getAccessToken: () => sessionManager.getAccessToken(), ... }`\n * from ONE shared `SessionManager` (see `auth/session-manager.ts`), so every\n * client built through this factory (REST or GraphQL) shares the same\n * proactive/reactive renewal, coalesced to one network call across the whole\n * browser — not per client, not just per tab.\n */\n\nimport { MPFClient } from './client.js';\nimport type { ClientConfig, TokenProvider } from './types.js';\nimport { createAuthMiddleware } from '../middlewares/auth.js';\nimport { createTenantMiddleware } from '../middlewares/tenant.js';\nimport type { TenantSelectionStore } from '../../auth/tenant-selection.js';\n\n/**\n * Configuration shared by every client built through this factory.\n */\nexport interface HttpClientOptions extends ClientConfig {\n /**\n * Optional token provider. When provided, auto-wires the auth middleware so\n * every request carries `Authorization: Bearer <token>` and 401s trigger\n * renewal per {@link TokenProvider.onUnauthorized}.\n *\n * Share ONE instance (backed by ONE `SessionManager`) across every client an\n * app constructs — that is what makes renewal happen once per browser\n * rather than once per client.\n */\n tokenProvider?: TokenProvider;\n /**\n * Optional shared tenant selection. When provided, every request carries the\n * selected tenant headers. Construct it once with `createTenantSelection()`\n * and share the same instance across every client.\n */\n tenantProvider?: TenantSelectionStore;\n}\n\n/**\n * Attach the standard auth + tenant middlewares to an already-constructed\n * client, in the standard order (auth before tenant — the tenant middleware's\n * under-scoping warning needs a token to decode).\n *\n * Exists as its own function (not inlined in {@link createHttpClient}) so a\n * subclass-specific factory (`createAuthClient`, `createStorageClient`,\n * `createGraphQLClient`) can construct its own `MPFClient` subclass and still\n * reuse this exact wiring instead of re-deriving it.\n */\nexport function attachStandardMiddlewares(\n client: MPFClient,\n options: Pick<HttpClientOptions, 'tokenProvider' | 'tenantProvider'>,\n): void {\n const { tokenProvider, tenantProvider } = options;\n\n if (tokenProvider) {\n client.use(\n createAuthMiddleware({\n getAccessToken: tokenProvider.getAccessToken,\n onTokenExpired: tokenProvider.onTokenExpired,\n ...(tokenProvider.onUnauthorized ? { onUnauthorized: tokenProvider.onUnauthorized } : {}),\n }),\n );\n }\n\n if (tenantProvider) {\n client.use(\n createTenantMiddleware({\n tenantProvider,\n ...(tokenProvider ? { getAccessToken: tokenProvider.getAccessToken } : {}),\n }),\n );\n }\n}\n\n/**\n * Create a generic HTTP client with the standard auth + tenant middlewares\n * pre-wired.\n *\n * Use this directly for a plain REST client; `createAuthClient` and\n * `createStorageClient` use it internally for their typed `MPFClient`\n * subclasses, and `createGraphQLClient` uses it for its HTTP transport.\n */\nexport function createHttpClient(options: HttpClientOptions): MPFClient {\n const { tokenProvider, tenantProvider, ...clientConfig } = options;\n const client = new MPFClient(clientConfig);\n attachStandardMiddlewares(client, { tokenProvider, tenantProvider });\n return client;\n}\n"]}
1
+ {"version":3,"sources":["../src/client/core/middleware.ts","../src/client/middlewares/retry.ts","../src/client/core/client.ts","../src/client/middlewares/auth.ts","../src/client/middlewares/tenant.ts","../src/client/core/client-factory.ts"],"names":["text"],"mappings":"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","file":"chunk-3OKR4MSV.js","sourcesContent":["/**\n * Middleware system for request/response interceptors\n */\n\nimport type { RequestContext, ResponseContext } from './types.js';\n\n/**\n * Middleware interface for intercepting requests and responses\n */\nexport interface Middleware {\n /** Unique identifier for the middleware */\n name: string;\n\n /**\n * Called before the request is sent\n * Can modify the request context or throw to abort\n */\n onRequest?: (ctx: RequestContext) => Promise<RequestContext> | RequestContext;\n\n /**\n * Called after a successful response is received\n * Can modify the response context or throw to trigger error handling\n */\n onResponse?: <T>(ctx: ResponseContext<T>) => Promise<ResponseContext<T>> | ResponseContext<T>;\n\n /**\n * Called when an error occurs during the request lifecycle\n * Can transform the error or re-throw\n */\n onError?: (error: Error, ctx: RequestContext) => Promise<never> | never;\n}\n\n/**\n * Execute the request middleware chain in order\n *\n * Middlewares are executed in the order they were added.\n * Each middleware can modify the context before passing it to the next.\n *\n * @param middlewares - Array of middlewares to execute\n * @param ctx - Initial request context\n * @returns Modified request context after all middlewares\n */\nexport async function executeRequestMiddlewares(\n middlewares: Middleware[],\n ctx: RequestContext\n): Promise<RequestContext> {\n let currentCtx = ctx;\n\n for (const middleware of middlewares) {\n if (middleware.onRequest) {\n currentCtx = await middleware.onRequest(currentCtx);\n }\n }\n\n return currentCtx;\n}\n\n/**\n * Execute the response middleware chain in reverse order\n *\n * Middlewares are executed in reverse order (last added runs first).\n * This allows middlewares to \"unwrap\" their effects in the correct order.\n *\n * @param middlewares - Array of middlewares to execute\n * @param ctx - Initial response context\n * @returns Modified response context after all middlewares\n */\nexport async function executeResponseMiddlewares<T>(\n middlewares: Middleware[],\n ctx: ResponseContext<T>\n): Promise<ResponseContext<T>> {\n let currentCtx = ctx;\n\n // Execute in reverse order for response processing\n for (let i = middlewares.length - 1; i >= 0; i--) {\n const middleware = middlewares[i];\n if (middleware.onResponse) {\n currentCtx = await middleware.onResponse(currentCtx);\n }\n }\n\n return currentCtx;\n}\n\n/**\n * Execute error handlers in the middleware chain\n *\n * EVERY middleware's `onError` handler runs, in registration order. Because\n * `onError` is typed `never` it signals completion by throwing, so a thrown\n * error is its normal exit path and must NOT terminate the chain — otherwise\n * the first handler that throws (e.g. the retry middleware, which always\n * throws) would silently swallow every handler registered after it.\n *\n * A handler may transform the error by throwing a different one; the\n * transformed error is passed to the remaining handlers and is what finally\n * propagates to the caller.\n *\n * @param middlewares - Array of middlewares to try\n * @param error - The error that occurred\n * @param ctx - The request context when the error occurred\n * @throws The original or transformed error\n */\nexport async function executeErrorMiddlewares(\n middlewares: Middleware[],\n error: Error,\n ctx: RequestContext\n): Promise<never> {\n let currentError = error;\n\n for (const middleware of middlewares) {\n if (!middleware.onError) {\n continue;\n }\n\n try {\n await middleware.onError(currentError, ctx);\n } catch (thrown) {\n // Throwing is how an `onError` handler returns. Adopt a transformed\n // error (if any) and continue so later handlers still observe it.\n if (thrown instanceof Error) {\n currentError = thrown;\n }\n }\n }\n\n throw currentError;\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport { MPFError, MPFAPIError } from '../core/errors.js';\n\n/**\n * Options for the retry middleware.\n */\nexport interface RetryMiddlewareOptions {\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Base delay in milliseconds between retries.\n * With exponential backoff, actual delay = retryDelay * (backoffFactor ^ attemptNumber)\n * @default 1000\n */\n retryDelay?: number;\n\n /**\n * HTTP status codes that trigger a retry.\n * @default [408, 429, 500, 502, 503, 504]\n */\n retryOn?: number[];\n\n /**\n * Exponential backoff factor.\n * Each retry waits: retryDelay * (backoffFactor ^ attemptNumber)\n * @default 2\n */\n backoffFactor?: number;\n\n /**\n * Maximum delay in milliseconds between retries (caps exponential growth).\n * @default 30000 (30 seconds)\n */\n maxDelay?: number;\n\n /**\n * Whether to add random jitter to retry delays (prevents thundering herd).\n * When enabled, adds random jitter up to 25% of the calculated delay.\n * @default true\n */\n jitter?: boolean;\n\n /**\n * Optional callback called before each retry attempt.\n * Can be used for logging or metrics.\n */\n onRetry?: (attempt: number, error: Error, delay: number) => void | Promise<void>;\n\n /**\n * Custom function to determine if an error should trigger a retry.\n * If provided, this takes precedence over retryOn status codes.\n */\n shouldRetry?: (error: Error, attempt: number) => boolean;\n}\n\n/** Metadata key for storing retry attempt count */\nconst RETRY_ATTEMPT_KEY = '__retryAttempt';\n\n/** Metadata key set by the retry middleware to request another attempt */\nconst SHOULD_RETRY_KEY = '__shouldRetry';\n\n/**\n * Metadata key marking a request as non-retryable regardless of what any\n * middleware asks for (e.g. a one-shot streaming body that cannot be re-sent).\n */\nconst NO_RETRY_KEY = '__noRetry';\n\n/**\n * Default HTTP status codes that should trigger a retry.\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nconst DEFAULT_RETRY_STATUS_CODES = [408, 429, 500, 502, 503, 504];\n\n/**\n * Sleep for a specified duration.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay with exponential backoff and optional jitter.\n */\nfunction calculateDelay(\n attempt: number,\n baseDelay: number,\n backoffFactor: number,\n maxDelay: number,\n useJitter: boolean\n): number {\n // Calculate exponential delay: baseDelay * (factor ^ attempt)\n const exponentialDelay = baseDelay * Math.pow(backoffFactor, attempt);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n\n // Add jitter (0-25% of the delay) to prevent thundering herd\n if (useJitter) {\n const jitterFactor = 1 + Math.random() * 0.25;\n return Math.floor(cappedDelay * jitterFactor);\n }\n\n return Math.floor(cappedDelay);\n}\n\n/**\n * Creates a retry middleware with exponential backoff.\n *\n * The middleware:\n * - Automatically retries failed requests based on HTTP status codes\n * - Uses exponential backoff to space out retry attempts\n * - Optionally adds jitter to prevent thundering herd problems\n * - Respects Retry-After headers when present\n *\n * @param options - Configuration options for the retry middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const retryMiddleware = createRetryMiddleware({\n * maxRetries: 3,\n * retryDelay: 1000,\n * retryOn: [500, 502, 503, 504],\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With custom retry logic\n * const retryMiddleware = createRetryMiddleware({\n * maxRetries: 5,\n * retryDelay: 500,\n * backoffFactor: 1.5,\n * jitter: true,\n * onRetry: (attempt, error, delay) => {\n * console.log(`Retry attempt ${attempt} after ${delay}ms:`, error.message);\n * },\n * shouldRetry: (error, attempt) => {\n * // Custom retry logic\n * if (error instanceof MPFError && error.status) {\n * return error.status >= 500 && attempt < 3;\n * }\n * return false;\n * }\n * });\n * ```\n */\nexport function createRetryMiddleware(options?: RetryMiddlewareOptions): Middleware {\n const {\n maxRetries = 3,\n retryDelay = 1000,\n retryOn = DEFAULT_RETRY_STATUS_CODES,\n backoffFactor = 2,\n maxDelay = 30000,\n jitter = true,\n onRetry,\n shouldRetry: customShouldRetry,\n } = options ?? {};\n\n /**\n * Determine if an error should trigger a retry.\n */\n function shouldRetry(error: Error, attempt: number): boolean {\n // Don't retry if we've exhausted attempts\n if (attempt >= maxRetries) {\n return false;\n }\n\n // Use custom retry logic if provided\n if (customShouldRetry) {\n return customShouldRetry(error, attempt);\n }\n\n // Check if it's an MPF error with a retryable status code\n if (error instanceof MPFError && error.status !== undefined) {\n return retryOn.includes(error.status);\n }\n\n // Retry on network errors (no status code)\n if (error.name === 'TypeError' && error.message.includes('fetch')) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Get delay from Retry-After header if present.\n * Note: This requires the error to have a retryAfter property or be passed separately.\n * For MPFAPIError, we check the details for a retryAfter value.\n */\n function getRetryAfterDelay(error: Error): number | null {\n // Check if error has details with retryAfter (from API response)\n if (error instanceof MPFAPIError && error.details) {\n const details = error.details as Record<string, unknown>;\n const retryAfter = details['retryAfter'] || details['retry-after'] || details['Retry-After'];\n\n if (typeof retryAfter === 'number') {\n return retryAfter * 1000;\n }\n\n if (typeof retryAfter === 'string') {\n // Retry-After can be seconds or a date string\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n return seconds * 1000;\n }\n\n // Try parsing as date\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n const delay = date.getTime() - Date.now();\n return delay > 0 ? delay : null;\n }\n }\n }\n\n return null;\n }\n\n return {\n name: 'retry',\n\n onRequest(ctx: RequestContext): RequestContext {\n // Initialize retry attempt counter if not present\n if (ctx.metadata[RETRY_ATTEMPT_KEY] === undefined) {\n ctx.metadata[RETRY_ATTEMPT_KEY] = 0;\n }\n return ctx;\n },\n\n async onError(error: Error, ctx: RequestContext): Promise<never> {\n const currentAttempt = (ctx.metadata[RETRY_ATTEMPT_KEY] as number) ?? 0;\n\n if (!shouldRetry(error, currentAttempt)) {\n throw error;\n }\n\n // Calculate delay\n let delay = getRetryAfterDelay(error);\n if (delay === null) {\n delay = calculateDelay(currentAttempt, retryDelay, backoffFactor, maxDelay, jitter);\n }\n\n // Cap Retry-After delay at maxDelay\n delay = Math.min(delay, maxDelay);\n\n // Call onRetry callback if provided\n if (onRetry) {\n try {\n await onRetry(currentAttempt + 1, error, delay);\n } catch (callbackError) {\n // Log but don't fail the retry\n console.error('[MPF SDK] Error in onRetry callback:', callbackError);\n }\n }\n\n // Wait before retrying\n await sleep(delay);\n\n // Increment attempt counter\n ctx.metadata[RETRY_ATTEMPT_KEY] = currentAttempt + 1;\n\n // Mark that this request should be retried.\n // MPFClient.request() checks this flag after the error middleware chain\n // has run and starts another attempt when it is set.\n requestRetry(ctx);\n\n // Re-throw to signal the SDK to retry\n // The SDK should catch this and check __shouldRetry\n throw error;\n },\n };\n}\n\n/**\n * Check if a request context indicates a retry should be attempted.\n * Used by `MPFClient.request()` to decide whether to run another attempt.\n *\n * Returns false when the request has been marked non-retryable, even if a\n * middleware asked for a retry.\n */\nexport function shouldRetryRequest(ctx: RequestContext): boolean {\n return ctx.metadata[SHOULD_RETRY_KEY] === true && !isRetryDisabled(ctx);\n}\n\n/**\n * Ask `MPFClient.request()` to run another attempt.\n *\n * The single writer of the retry flag. Any middleware that can recover from an\n * error (the auth middleware's renew-and-retry, for instance) calls this from\n * its `onError` and then rethrows.\n *\n * The client consults the flag unconditionally, so this works whether or not\n * `createRetryMiddleware` is registered.\n */\nexport function requestRetry(ctx: RequestContext): void {\n ctx.metadata[SHOULD_RETRY_KEY] = true;\n}\n\n/**\n * Mark a request as non-retryable. Used for request bodies that cannot be\n * re-sent (a `ReadableStream` is consumed by the first attempt).\n */\nexport function disableRetry(ctx: RequestContext): void {\n ctx.metadata[NO_RETRY_KEY] = true;\n}\n\n/**\n * Whether the request has been marked non-retryable.\n */\nexport function isRetryDisabled(ctx: RequestContext): boolean {\n return ctx.metadata[NO_RETRY_KEY] === true;\n}\n\n/**\n * Whether a fetch body can be sent more than once.\n *\n * `FormData`, `Blob`, `ArrayBuffer`, `URLSearchParams` and strings are all\n * re-readable, so retrying them is safe. A `ReadableStream` is consumed by the\n * first attempt and must never be retried.\n */\nexport function isReplayableBody(body: BodyInit | null | undefined): boolean {\n if (body === null || body === undefined) {\n return true;\n }\n\n if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get the current retry attempt number from request context.\n */\nexport function getRetryAttempt(ctx: RequestContext): number {\n return (ctx.metadata[RETRY_ATTEMPT_KEY] as number) ?? 0;\n}\n\n/**\n * Clear the retry flag from the request context.\n * Should be called after a successful retry or when giving up.\n */\nexport function clearRetryFlag(ctx: RequestContext): void {\n delete ctx.metadata[SHOULD_RETRY_KEY];\n}\n","/**\n * Base HTTP client for the MPF SDK\n */\n\nimport type { ClientConfig, RequestOptions, RequestContext, ResponseContext, APIErrorResponse } from './types.js';\nimport type { Middleware } from './middleware.js';\nimport { executeRequestMiddlewares, executeResponseMiddlewares, executeErrorMiddlewares } from './middleware.js';\nimport { MPFNetworkError, MPFAPIError, MPFAuthError } from './errors.js';\nimport { shouldRetryRequest, clearRetryFlag, disableRetry, isReplayableBody } from '../middlewares/retry.js';\n\n/**\n * Hard ceiling on the number of attempts a single `request()` call may make\n * (the initial attempt plus retries).\n *\n * This is deliberately independent of any middleware's own `maxRetries`: a\n * misbehaving or misconfigured middleware can keep asking for retries, and this\n * bound guarantees the loop terminates. 4 attempts = 1 initial + 3 retries,\n * matching the retry middleware's default `maxRetries: 3`.\n */\nexport const MAX_REQUEST_ATTEMPTS = 4;\n\n/**\n * Base client for making HTTP requests with middleware support\n */\nexport class MPFClient {\n protected readonly baseUrl: string;\n protected readonly defaultHeaders: Record<string, string>;\n protected readonly middlewares: Middleware[];\n\n constructor(config: ClientConfig) {\n // Remove trailing slash from base URL for consistent URL building\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultHeaders = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n };\n this.middlewares = [...(config.middlewares ?? [])];\n }\n\n /**\n * Add a middleware to the client\n * Middlewares are executed in the order they are added for requests,\n * and in reverse order for responses.\n *\n * @param middleware - The middleware to add\n * @returns The client instance for chaining\n */\n use(middleware: Middleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n /**\n * Build a full URL with query parameters\n *\n * @param path - The API path (e.g., \"/users\" or \"users\")\n * @param params - Optional query parameters\n * @returns The full URL with query string\n */\n protected buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {\n // Ensure path starts with a slash\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n const base = /^https?:\\/\\//.test(this.baseUrl)\n ? this.baseUrl\n : (typeof window !== 'undefined' ? window.location.origin : 'http://localhost');\n const url = new URL(`${this.baseUrl}${normalizedPath}`, base);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n /**\n * Merge headers from different sources\n *\n * @param requestHeaders - Headers specific to this request\n * @returns Merged headers object\n */\n protected mergeHeaders(requestHeaders?: Record<string, string>): Record<string, string> {\n return {\n ...this.defaultHeaders,\n ...requestHeaders,\n };\n }\n\n /**\n * Build the headers for a single attempt.\n *\n * Rebuilt per attempt so request middlewares (auth, turnstile, ...) always\n * inject a fresh token instead of replaying a stale one.\n *\n * For a `FormData` body the default JSON `Content-Type` is dropped so that\n * fetch sets `multipart/form-data` with the correct boundary.\n */\n private buildAttemptHeaders(init: RequestInit): Record<string, string> {\n const headers = this.mergeHeaders(init.headers as Record<string, string> | undefined);\n\n if (typeof FormData !== 'undefined' && init.body instanceof FormData) {\n delete headers['Content-Type'];\n }\n\n return headers;\n }\n\n /**\n * Parse the response body based on content type\n *\n * @param response - The fetch Response object\n * @returns Parsed response data\n */\n protected async parseResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type') ?? '';\n\n // Handle empty responses (204 No Content, etc.)\n if (response.status === 204 || response.headers.get('content-length') === '0') {\n return undefined as T;\n }\n\n // Parse JSON responses\n if (contentType.includes('application/json')) {\n const text = await response.text();\n if (!text) {\n return undefined as T;\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new MPFAPIError(\n 'Failed to parse JSON response',\n 'PARSE_ERROR',\n response.status,\n { text }\n );\n }\n }\n\n // Return text for non-JSON responses\n const text = await response.text();\n return text as T;\n }\n\n /**\n * Handle error responses from the API\n *\n * @param response - The fetch Response object\n * @throws MPFAuthError for 401/403, MPFAPIError for other errors\n */\n protected async handleErrorResponse(response: Response): Promise<never> {\n let body: unknown;\n let errorResponse: APIErrorResponse | undefined;\n\n try {\n const text = await response.text();\n if (text) {\n body = JSON.parse(text);\n errorResponse = body as APIErrorResponse;\n }\n } catch {\n // Body is not JSON, that's fine\n }\n\n const message = errorResponse?.message ?? errorResponse?.error ?? response.statusText ?? 'Request failed';\n const code = errorResponse?.code ?? `HTTP_${response.status}`;\n const details = errorResponse?.details;\n\n // Handle authentication errors\n if (response.status === 401) {\n const authType = code.toLowerCase().includes('expired') ? 'token_expired' : 'unauthorized';\n // Preserve the server's own code: `authType` collapses distinct 401s\n // (notably REFRESH_TOKEN_SUPERSEDED) into 'unauthorized'.\n throw new MPFAuthError(message, authType, 401, details, errorResponse?.code);\n }\n\n if (response.status === 403) {\n throw new MPFAuthError(message, 'forbidden', 403, details, errorResponse?.code);\n }\n\n // Handle all other errors\n throw new MPFAPIError(message, code, response.status, details, body);\n }\n\n /**\n * Execute an HTTP request with the full middleware chain, retrying when a\n * middleware asks for it.\n *\n * Retry contract:\n * - `metadata` is created once and shared by every attempt. Middlewares keep\n * their per-request state there (retry counter, auth-renew flag); rebuilding\n * it per attempt would reset those counters and loop forever.\n * - `init.headers` are rebuilt per attempt so request middlewares re-inject a\n * fresh token rather than replaying the first attempt's headers.\n * - `MAX_REQUEST_ATTEMPTS` bounds the loop regardless of middleware config.\n * - Bodies that cannot be re-sent (`ReadableStream`) disable retrying.\n *\n * @param path - The API path\n * @param init - Fetch RequestInit options\n * @returns The parsed response data\n * @throws MPFNetworkError for network failures\n * @throws MPFAuthError for 401/403 responses\n * @throws MPFAPIError for other error responses\n */\n async request<T>(path: string, init: RequestInit = {}, params?: Record<string, string | number | boolean | undefined>, options?: RequestOptions): Promise<T> {\n const url = this.buildUrl(path, params);\n\n // Shared across every attempt — see the retry contract above.\n const metadata: Record<string, unknown> = {};\n\n for (let attempt = 0; attempt < MAX_REQUEST_ATTEMPTS; attempt++) {\n const requestCtx: RequestContext = {\n url,\n init: {\n ...init,\n headers: this.buildAttemptHeaders(init),\n },\n metadata,\n options,\n };\n\n if (!isReplayableBody(init.body)) {\n disableRetry(requestCtx);\n }\n\n try {\n return await this.attempt<T>(requestCtx);\n } catch (error) {\n // The error middleware chain already ran inside attempt(); a retry\n // middleware has had its chance to set the retry flag (and to sleep for\n // its backoff) by now.\n const isLastAttempt = attempt === MAX_REQUEST_ATTEMPTS - 1;\n\n if (isLastAttempt || !shouldRetryRequest(requestCtx)) {\n throw error;\n }\n\n clearRetryFlag(requestCtx);\n }\n }\n\n // Unreachable: the loop either returns or throws on the last attempt.\n throw new MPFNetworkError('Request retry loop exhausted');\n }\n\n /**\n * Execute a single request attempt through the middleware chain.\n *\n * On failure the error middleware chain runs before the error propagates, so\n * the caller can inspect `ctx.metadata` for a retry request.\n */\n private async attempt<T>(ctx: RequestContext): Promise<T> {\n let requestCtx = ctx;\n\n try {\n // Execute request middlewares\n requestCtx = await executeRequestMiddlewares(this.middlewares, requestCtx);\n\n // Make the actual fetch request\n let response: Response;\n try {\n response = await fetch(requestCtx.url, requestCtx.init);\n } catch (error) {\n throw new MPFNetworkError(\n error instanceof Error ? error.message : 'Network request failed',\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle error responses\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n // Parse successful response\n const data = await this.parseResponse<T>(response);\n\n // Build response context\n let responseCtx: ResponseContext<T> = {\n response,\n data,\n metadata: requestCtx.metadata,\n };\n\n // Execute response middlewares\n responseCtx = await executeResponseMiddlewares(this.middlewares, responseCtx);\n\n return responseCtx.data;\n } catch (error) {\n try {\n // Execute error middlewares if available\n if (error instanceof Error && this.middlewares.some(m => m.onError)) {\n await executeErrorMiddlewares(this.middlewares, error, requestCtx);\n }\n throw error;\n } finally {\n // A request middleware may have returned a cloned context; make sure\n // any metadata it wrote (including the retry flag) reaches the caller's\n // shared metadata object.\n if (requestCtx.metadata !== ctx.metadata) {\n Object.assign(ctx.metadata, requestCtx.metadata);\n }\n }\n }\n }\n\n /**\n * Make a GET request\n *\n * @param path - The API path\n * @param options - Request options\n * @returns The parsed response data\n */\n async get<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'GET',\n headers: options.headers,\n signal: options.signal,\n }, options.params, options);\n }\n\n /**\n * Make a POST request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async post<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a PUT request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async put<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'PUT',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a PATCH request\n *\n * @param path - The API path\n * @param body - Request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async patch<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n\n /**\n * Make a DELETE request\n *\n * @param path - The API path\n * @param body - Optional request body (will be JSON stringified)\n * @param options - Request options\n * @returns The parsed response data\n */\n async delete<T>(path: string, body?: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>(path, {\n method: 'DELETE',\n headers: options.headers,\n signal: options.signal,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }, options.params, options);\n }\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport { MPFError } from '../core/errors.js';\nimport { requestRetry } from './retry.js';\n\n/**\n * Metadata key: set in `onRequest` only when an Authorization header was\n * actually injected.\n *\n * This is the wrong-password guard. Without it, a 401 from `signIn` (bad\n * credentials, `skipAuth`, no token yet) is indistinguishable from a 401 caused\n * by an expired session, and every consumer ends up reimplementing the same\n * check in app code — usually by string-matching an error message. Keying off\n * \"did we send a token\" makes it structural.\n */\nconst TOKEN_ATTACHED_KEY = '__authTokenAttached';\n\n/**\n * Metadata key: set BEFORE awaiting the renew, capping renewal at one attempt\n * per logical request no matter how many times the retry loop runs.\n *\n * Set before rather than after the await because two concurrent error handlers\n * on the same request would otherwise both observe \"not attempted\" and both\n * renew — and the refresh token is single-use, so the second renew kills the\n * session it was trying to save.\n */\nconst RENEW_ATTEMPTED_KEY = '__authRenewAttempted';\n\n/**\n * Options for the auth middleware.\n */\nexport interface AuthMiddlewareOptions {\n /**\n * Function to get the current access token.\n * Can be sync or async (e.g., reading from localStorage or refreshing token).\n *\n * @returns The access token, or null if not authenticated\n */\n getAccessToken: () => string | null | Promise<string | null>;\n\n /**\n * Called when a 401 is final — i.e. a token WAS attached and renewal either\n * was not possible, failed, or had already been tried for this request.\n *\n * This is the \"log the user out\" hook. It is deliberately NOT called for a\n * 401 on a request that carried no token (a wrong password must not log you\n * out of a session you do have), nor for the first 401 when `onUnauthorized`\n * successfully renews.\n */\n onTokenExpired?: () => void | Promise<void>;\n\n /**\n * Called on the first 401 of a request that DID carry a token.\n *\n * Should attempt a session renewal and resolve `true` when a fresh token is\n * now available, `false` otherwise. On `true` the request is retried once,\n * with headers rebuilt so the new token is picked up.\n *\n * Capped at one call per logical request by `__authRenewAttempted`, so a\n * second 401 falls through to `onTokenExpired` instead of looping.\n */\n onUnauthorized?: () => Promise<boolean>;\n\n /**\n * The token type prefix for the Authorization header.\n * @default 'Bearer'\n */\n tokenType?: string;\n\n /**\n * Custom header name for the authorization token.\n * @default 'Authorization'\n */\n headerName?: string;\n}\n\n/**\n * Creates an authentication middleware that adds authorization headers to requests.\n *\n * The middleware:\n * - Adds an Authorization header with the token from getAccessToken()\n * - Calls onTokenExpired() when a 401 response is received\n *\n * @param options - Configuration options for the auth middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const authMiddleware = createAuthMiddleware({\n * getAccessToken: () => localStorage.getItem('accessToken'),\n * onTokenExpired: () => {\n * // Redirect to login or refresh token\n * window.location.href = '/login';\n * }\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With async token retrieval\n * const authMiddleware = createAuthMiddleware({\n * getAccessToken: async () => {\n * const session = await authService.getSession();\n * return session?.accessToken ?? null;\n * },\n * tokenType: 'Bearer',\n * onTokenExpired: async () => {\n * await authService.refreshToken();\n * }\n * });\n * ```\n */\nexport function createAuthMiddleware(options: AuthMiddlewareOptions): Middleware {\n const {\n getAccessToken,\n onTokenExpired,\n onUnauthorized,\n tokenType = 'Bearer',\n headerName = 'Authorization',\n } = options;\n\n return {\n name: 'auth',\n\n async onRequest(ctx: RequestContext): Promise<RequestContext> {\n if (ctx.options?.skipAuth) {\n return ctx;\n }\n\n const token = await getAccessToken();\n\n if (token) {\n // Create a new Headers object to avoid mutating the original\n const headers = new Headers(ctx.init.headers);\n headers.set(headerName, `${tokenType} ${token}`);\n ctx.init.headers = headers;\n\n // Record that THIS attempt actually carried a token.\n ctx.metadata[TOKEN_ATTACHED_KEY] = true;\n }\n\n return ctx;\n },\n\n async onError(error: Error, ctx: RequestContext): Promise<never> {\n // Key off the numeric status, not the error's classification string: the\n // classification is derived from a server-supplied code and is not a\n // reliable discriminator.\n const status = error instanceof MPFError ? error.status : undefined;\n if (status !== 401) {\n throw error;\n }\n\n // Guard 1: no token was attached, so this 401 is about the credentials in\n // the request body (wrong password, expired invite, ...) and says nothing\n // about session health. Do not renew and do not log anyone out.\n if (ctx.metadata[TOKEN_ATTACHED_KEY] !== true) {\n throw error;\n }\n\n // Guard 2: at most one renewal per logical request. Set before awaiting.\n if (onUnauthorized && ctx.metadata[RENEW_ATTEMPTED_KEY] !== true) {\n ctx.metadata[RENEW_ATTEMPTED_KEY] = true;\n\n let renewed = false;\n try {\n renewed = await onUnauthorized();\n } catch (renewError) {\n console.error('[MPF SDK] Error in onUnauthorized callback:', renewError);\n renewed = false;\n }\n\n if (renewed) {\n // Retry once. The client rebuilds headers per attempt, so the fresh\n // token is picked up automatically.\n requestRetry(ctx);\n throw error;\n }\n }\n\n // The 401 is final: renewal was impossible, failed, or already tried.\n if (onTokenExpired) {\n try {\n await onTokenExpired();\n } catch (callbackError) {\n // Log but don't swallow the original error\n console.error('[MPF SDK] Error in onTokenExpired callback:', callbackError);\n }\n }\n\n // Always re-throw the original error\n throw error;\n },\n };\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\nimport type { MPFRole } from '../../auth/claims-types.js';\nimport type { TenantSelectionStore } from '../../auth/tenant-selection.js';\nimport { tryDecodeAccessToken } from '../../auth/claims.js';\n\n/** Header carrying the selected tenant id. */\nexport const TENANT_HEADER = 'X-MPF-Tenant';\n\n/** Header carrying the selected role within that tenant. */\nexport const TENANT_ROLE_HEADER = 'X-MPF-Tenant-Role';\n\n/**\n * Options for the tenant middleware.\n */\nexport interface TenantMiddlewareOptions {\n /**\n * The shared tenant selection. Read per request, so a `set()` takes effect on\n * the next request with no client reconstruction.\n */\n tenantProvider?: TenantSelectionStore;\n\n /**\n * Access-token getter, used ONLY for the under-scoping warning below. When\n * omitted the warning is disabled.\n *\n * Decoding is LRU-cached, and the warning fires at most once per middleware,\n * so this costs nothing in steady state.\n */\n getAccessToken?: () => string | null | Promise<string | null>;\n\n /**\n * Whether to warn once when a request goes out unscoped while the token holds\n * tenants.\n * @default true\n */\n warnOnUnscoped?: boolean;\n\n /** Logger for the warning. Defaults to `console`. */\n logger?: { warn: (message: string, ...args: unknown[]) => void };\n}\n\nconst UNSCOPED_WARNING =\n '[MPF SDK] Request sent with no tenant selected, but the access token holds tenant ' +\n 'memberships. The server will scope this request to the default (tenantless) role, ' +\n 'which usually means empty results or a 403 rather than tenant data. Wire a ' +\n 'tenantProvider (createTenantSelection()) into your client and call set(tenantId), ' +\n 'or pass `{ tenant: null }` on the request to state explicitly that it is unscoped. ' +\n 'This warning is shown once.';\n\n/**\n * Creates a middleware that puts the selected tenant on the wire.\n *\n * Resolution order for the tenant, using the three states of\n * `options.tenant`:\n *\n * | `options.tenant` | meaning |\n * |-------------------|--------------------------------------------|\n * | `undefined` | inherit the client-wide selection |\n * | `null` | deliberately unscoped for THIS request |\n * | `\"<uuid>\"` | that tenant, for THIS request |\n *\n * `options.skipTenant` bypasses the middleware entirely.\n *\n * Header rules:\n * - The tenant header is **omitted entirely** when there is no tenant. An\n * empty-string header is a 400 server-side, deliberately, so that a bug\n * cannot masquerade as the no-tenant path.\n * - The role header is omitted unless a role was specified, letting the server\n * apply that tenant's default role (its `dfr`, or `rls[0]` when it has\n * none).\n * - A per-request tenant does NOT inherit the client-wide role: the role only\n * travels with the selection it belongs to. Selecting tenant B while tenant\n * A's role is selected must not send A's role to B.\n */\nexport function createTenantMiddleware(options: TenantMiddlewareOptions = {}): Middleware {\n const {\n tenantProvider,\n getAccessToken,\n warnOnUnscoped = true,\n logger = console,\n } = options;\n\n let warned = false;\n\n async function maybeWarnUnscoped(): Promise<void> {\n if (warned || !warnOnUnscoped || !getAccessToken) {\n return;\n }\n\n // Mark first: a failure below must not turn this into a per-request cost,\n // and the warning is best-effort diagnostics.\n let token: string | null;\n try {\n token = await getAccessToken();\n } catch {\n return;\n }\n\n const claims = tryDecodeAccessToken(token);\n if (!claims || claims.tnts.length === 0) {\n return;\n }\n\n warned = true;\n logger.warn(UNSCOPED_WARNING);\n }\n\n return {\n name: 'tenant',\n\n async onRequest(ctx: RequestContext): Promise<RequestContext> {\n if (ctx.options?.skipTenant) {\n return ctx;\n }\n\n const perRequest = ctx.options?.tenant;\n const inherit = perRequest === undefined;\n const selection = inherit ? tenantProvider?.get() : undefined;\n\n const tenant: string | null = inherit ? (selection?.tenant ?? null) : perRequest;\n\n // Role travels with its own selection; see the note above.\n const role: MPFRole | undefined =\n ctx.options?.tenantRole ?? (inherit ? selection?.role : undefined);\n\n if (tenant === null || tenant === '') {\n // Warn only when the request is unscoped by OMISSION, never when the\n // caller passed `{ tenant: null }`. Explicit null is a developer stating\n // intent; `undefined` with a tenant-bearing token is the oversight we\n // are trying to catch. Warning on the deliberate case would train people\n // to ignore the warning and cost us the signal in the case that matters\n // — which is the whole reason `undefined | null | string` is three-state.\n if (inherit) {\n await maybeWarnUnscoped();\n }\n return ctx;\n }\n\n const headers = new Headers(ctx.init.headers);\n headers.set(TENANT_HEADER, tenant);\n if (role !== undefined && role !== '') {\n headers.set(TENANT_ROLE_HEADER, role);\n }\n ctx.init.headers = headers;\n\n return ctx;\n },\n };\n}\n","/**\n * Generic HTTP client factory.\n *\n * `createAuthClient`, `createStorageClient` and `createGraphQLClient` all wire\n * the SAME two middlewares (auth, tenant) by hand today, which is how they\n * drift: three copies of \"if tokenProvider, use(createAuthMiddleware(...))\".\n * This is the single place that wiring happens now; the three factories\n * become thin wrappers that just pick the right `MPFClient` subclass.\n *\n * The point of pulling this out is reuse, NOT a new concept: a `tokenProvider`\n * here is still just `{ getAccessToken, onTokenExpired?, onUnauthorized? }` —\n * typically `{ getAccessToken: () => sessionManager.getAccessToken(), ... }`\n * from ONE shared `SessionManager` (see `auth/session-manager.ts`), so every\n * client built through this factory (REST or GraphQL) shares the same\n * proactive/reactive renewal, coalesced to one network call across the whole\n * browser — not per client, not just per tab.\n */\n\nimport { MPFClient } from './client.js';\nimport type { ClientConfig, TokenProvider } from './types.js';\nimport { createAuthMiddleware } from '../middlewares/auth.js';\nimport { createTenantMiddleware } from '../middlewares/tenant.js';\nimport type { TenantSelectionStore } from '../../auth/tenant-selection.js';\n\n/**\n * Configuration shared by every client built through this factory.\n */\nexport interface HttpClientOptions extends ClientConfig {\n /**\n * Optional token provider. When provided, auto-wires the auth middleware so\n * every request carries `Authorization: Bearer <token>` and 401s trigger\n * renewal per {@link TokenProvider.onUnauthorized}.\n *\n * Share ONE instance (backed by ONE `SessionManager`) across every client an\n * app constructs — that is what makes renewal happen once per browser\n * rather than once per client.\n */\n tokenProvider?: TokenProvider;\n /**\n * Optional shared tenant selection. When provided, every request carries the\n * selected tenant headers. Construct it once with `createTenantSelection()`\n * and share the same instance across every client.\n */\n tenantProvider?: TenantSelectionStore;\n}\n\n/**\n * Attach the standard auth + tenant middlewares to an already-constructed\n * client, in the standard order (auth before tenant — the tenant middleware's\n * under-scoping warning needs a token to decode).\n *\n * Exists as its own function (not inlined in {@link createHttpClient}) so a\n * subclass-specific factory (`createAuthClient`, `createStorageClient`,\n * `createGraphQLClient`) can construct its own `MPFClient` subclass and still\n * reuse this exact wiring instead of re-deriving it.\n */\nexport function attachStandardMiddlewares(\n client: MPFClient,\n options: Pick<HttpClientOptions, 'tokenProvider' | 'tenantProvider'>,\n): void {\n const { tokenProvider, tenantProvider } = options;\n\n if (tokenProvider) {\n client.use(\n createAuthMiddleware({\n getAccessToken: tokenProvider.getAccessToken,\n onTokenExpired: tokenProvider.onTokenExpired,\n ...(tokenProvider.onUnauthorized ? { onUnauthorized: tokenProvider.onUnauthorized } : {}),\n }),\n );\n }\n\n if (tenantProvider) {\n client.use(\n createTenantMiddleware({\n tenantProvider,\n ...(tokenProvider ? { getAccessToken: tokenProvider.getAccessToken } : {}),\n }),\n );\n }\n}\n\n/**\n * Create a generic HTTP client with the standard auth + tenant middlewares\n * pre-wired.\n *\n * Use this directly for a plain REST client; `createAuthClient` and\n * `createStorageClient` use it internally for their typed `MPFClient`\n * subclasses, and `createGraphQLClient` uses it for its HTTP transport.\n */\nexport function createHttpClient(options: HttpClientOptions): MPFClient {\n const { tokenProvider, tenantProvider, ...clientConfig } = options;\n const client = new MPFClient(clientConfig);\n attachStandardMiddlewares(client, { tokenProvider, tenantProvider });\n return client;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { createAuthMiddleware } from './chunk-LRM6JJ63.js';
1
+ import { createAuthMiddleware } from './chunk-3OKR4MSV.js';
2
2
  import { SignJWT } from 'jose';
3
3
 
4
4
  var AdminEmptySecretError = class extends Error {
@@ -60,5 +60,5 @@ function createTurnstileMiddleware(options) {
60
60
  }
61
61
 
62
62
  export { AdminEmptySecretError, AdminEmptyUserIDError, createAdminAuthMiddleware, createTurnstileMiddleware, issueAdminToken };
63
- //# sourceMappingURL=chunk-K2ELAI2X.js.map
64
- //# sourceMappingURL=chunk-K2ELAI2X.js.map
63
+ //# sourceMappingURL=chunk-B3JXAPMM.js.map
64
+ //# sourceMappingURL=chunk-B3JXAPMM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/middlewares/admin-auth.ts","../src/client/middlewares/turnstile.ts"],"names":[],"mappings":";;;AAmBO,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAC/C,WAAA,GAAc;AACZ,IAAA,KAAA,CAAM,kDAAkD,CAAA;AACxD,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EACd;AACF;AAGO,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAC/C,WAAA,GAAc;AACZ,IAAA,KAAA,CAAM,kDAAkD,CAAA;AACxD,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EACd;AACF;AA0BA,eAAsB,eAAA,CACpB,MAAA,EACA,aAAA,EACA,UAAA,EACiB;AACjB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,qBAAA,EAAsB;AAAA,EAClC;AACA,EAAA,IAAI,CAAC,cAAc,MAAA,EAAQ;AACzB,IAAA,MAAM,IAAI,qBAAA,EAAsB;AAAA,EAClC;AAEA,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAC/C,EAAA,MAAM,GAAA,GAAM,IAAI,WAAA,EAAY,CAAE,OAAO,MAAM,CAAA;AAE3C,EAAA,MAAM,QAAA,GAAuD;AAAA,IAC3D,SAAS,aAAA,CAAc,MAAA;AAAA,IACvB,GAAI,cAAc,UAAA,GAAa,EAAE,cAAc,aAAA,CAAc,UAAA,KAAe;AAAC,GAC/E;AAEA,EAAA,OAAO,IAAI,QAAQ,EAAE,gBAAA,EAAkB,UAAU,CAAA,CAC9C,mBAAmB,EAAE,GAAA,EAAK,SAAS,CAAA,CACnC,YAAY,UAAU,CAAA,CACtB,kBAAkB,UAAA,GAAa,UAAU,CAAA,CACzC,IAAA,CAAK,GAAG,CAAA;AACb;AA+CO,SAAS,0BAA0B,OAAA,EAAiD;AACzF,EAAA,MAAM,cAAA,GACJ,WAAW,OAAA,IAAW,OAAA,CAAQ,UAAU,MAAA,GACpC,MAAM,OAAA,CAAQ,KAAA,GACd,MAAM;AACJ,IAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAe,UAAA,KAAe,OAAA,CAAQ,MAAA;AACtD,IAAA,OAAO,eAAA,CAAgB,MAAA,EAAQ,aAAA,EAAe,UAAU,CAAA;AAAA,EAC1D,CAAA;AAEN,EAAA,OAAO,oBAAA,CAAqB;AAAA,IAC1B,cAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACZ,CAAA;AACH;;;ACnGO,SAAS,0BAA0B,OAAA,EAAiD;AACzF,EAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAe,GAAI,OAAA;AAErC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IAEN,MAAM,UAAU,GAAA,EAA8C;AAE5D,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,GAAA,CAAI,KAAK,kBAAkB,CAAA;AAC/C,MAAA,MAAM,WAAA,GAAc,eAAe,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAI,QAAA,CAAS,QAAA,CAAS,IAAI,CAAC,CAAA;AAE3E,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,OAAO,GAAA;AAAA,MACT;AAEA,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,EAAS;AAC7B,MAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,GAAA,CAAI,KAAK,OAAO,CAAA;AAC5C,MAAA,OAAA,CAAQ,GAAA,CAAI,qBAAqB,KAAK,CAAA;AACtC,MAAA,GAAA,CAAI,KAAK,OAAA,GAAU,OAAA;AAEnB,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,GACF;AACF","file":"chunk-B3JXAPMM.js","sourcesContent":["import { SignJWT } from 'jose';\nimport type { Middleware } from '../core/middleware.js';\nimport { createAuthMiddleware } from './auth.js';\n\n/**\n * Impersonation payload embedded in an admin token.\n *\n * Mirrors the Go `ActOnBehalfOf` struct\n * (`pkg/go-chi-middleware-auth/types.go`), which the Go verifier reads\n * from the `act_on_behalf_of` JWT claim.\n */\nexport interface AdminActOnBehalfOf {\n /** The subject (user) the admin token acts on behalf of. Required. */\n userId: string;\n /** Optionally scopes the impersonation to a tenant. */\n onTenantId?: string;\n}\n\n/** Error thrown when an admin token is minted without a signing secret. */\nexport class AdminEmptySecretError extends Error {\n constructor() {\n super('auth: admin JWT signing secret must not be empty');\n this.name = 'AdminEmptySecretError';\n }\n}\n\n/** Error thrown when an admin token is minted without a subject user id. */\nexport class AdminEmptyUserIDError extends Error {\n constructor() {\n super('auth: act_on_behalf_of.user_id must not be empty');\n this.name = 'AdminEmptyUserIDError';\n }\n}\n\n/**\n * Mints an HS256-signed Admin JWT that impersonates `actOnBehalfOf`.\n *\n * The minted token interoperates byte-for-byte with the Go verifier in\n * `pkg/go-chi-middleware-auth/auth.go` (`parseAdmin`):\n * - Protected header `{ alg: 'HS256' }`.\n * - Required `exp` claim (`now + ttlSeconds`), which the Go side enforces via\n * `jwt.WithExpirationRequired()`.\n * - An `iat` claim of `now`.\n * - An `act_on_behalf_of` object claim with `user_id` (required) and an\n * optional `on_tenant_id`, matching the Go `ActOnBehalfOf` JSON tags.\n *\n * SECURITY: Minting an admin token requires the shared `ADMIN_JWT_SECRET`.\n * This secret grants the ability to impersonate ANY user, so it MUST ONLY be\n * used server-side or by trusted backend services. NEVER ship the secret to a\n * browser or any untrusted client, and never embed it in frontend bundles.\n *\n * @param secret - The shared HS256 signing secret (`ADMIN_JWT_SECRET`).\n * @param actOnBehalfOf - The principal to impersonate.\n * @param ttlSeconds - Token lifetime in seconds (added to the current time).\n * @returns The signed compact JWT string.\n * @throws {AdminEmptySecretError} when `secret` is empty.\n * @throws {AdminEmptyUserIDError} when `actOnBehalfOf.userId` is empty.\n */\nexport async function issueAdminToken(\n secret: string,\n actOnBehalfOf: AdminActOnBehalfOf,\n ttlSeconds: number\n): Promise<string> {\n if (!secret) {\n throw new AdminEmptySecretError();\n }\n if (!actOnBehalfOf.userId) {\n throw new AdminEmptyUserIDError();\n }\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const key = new TextEncoder().encode(secret);\n\n const actClaim: { user_id: string; on_tenant_id?: string } = {\n user_id: actOnBehalfOf.userId,\n ...(actOnBehalfOf.onTenantId ? { on_tenant_id: actOnBehalfOf.onTenantId } : {}),\n };\n\n return new SignJWT({ act_on_behalf_of: actClaim })\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt(nowSeconds)\n .setExpirationTime(nowSeconds + ttlSeconds)\n .sign(key);\n}\n\n/**\n * Options for the admin auth middleware.\n *\n * Exactly one of `token` (pre-minted) or `config` (mint-per-request) must be\n * provided.\n */\nexport type AdminAuthMiddlewareOptions =\n | {\n /** A pre-minted admin JWT to attach as `Authorization: Admin <token>`. */\n token: string;\n config?: never;\n }\n | {\n token?: never;\n /**\n * Per-request minting config (analogous to Go's `AdminRoundTripper`):\n * a fresh admin token is minted for every request.\n */\n config: {\n /** The shared HS256 signing secret (`ADMIN_JWT_SECRET`). */\n secret: string;\n /** The principal to impersonate. */\n actOnBehalfOf: AdminActOnBehalfOf;\n /** Token lifetime in seconds. */\n ttlSeconds: number;\n };\n };\n\n/**\n * Creates an admin authentication middleware that stamps an\n * `Authorization: Admin <token>` header on outgoing requests.\n *\n * Reuses {@link createAuthMiddleware} with `tokenType: 'Admin'`. Two ergonomics\n * are supported:\n * - `{ token }`: attach a pre-minted admin token.\n * - `{ config }`: mint a fresh admin token per request (like Go's\n * `AdminRoundTripper`).\n *\n * SECURITY: When using `config`, the `ADMIN_JWT_SECRET` is held in memory and\n * used to mint tokens. Only construct this middleware server-side / in trusted\n * services. NEVER ship the secret to a browser.\n *\n * @param options - Either a pre-minted `token` or a minting `config`.\n * @returns A middleware instance.\n */\nexport function createAdminAuthMiddleware(options: AdminAuthMiddlewareOptions): Middleware {\n const getAccessToken =\n 'token' in options && options.token !== undefined\n ? () => options.token\n : () => {\n const { secret, actOnBehalfOf, ttlSeconds } = options.config;\n return issueAdminToken(secret, actOnBehalfOf, ttlSeconds);\n };\n\n return createAuthMiddleware({\n getAccessToken,\n tokenType: 'Admin',\n });\n}\n","import type { Middleware } from '../core/middleware.js';\nimport type { RequestContext } from '../core/types.js';\n\n/**\n * Options for the Turnstile middleware.\n */\nexport interface TurnstileMiddlewareOptions {\n /**\n * Async function that mints a fresh Turnstile token.\n * Called once per protected request. Must return a valid token string.\n * Should throw if token cannot be obtained.\n */\n getToken: () => Promise<string>;\n\n /**\n * URL path suffixes that require a Turnstile token.\n * Matched against the end of the request URL path.\n * Example: ['/sign-up-email-password', '/sign-in-email-password']\n */\n protectedPaths: string[];\n}\n\n/**\n * Creates a Cloudflare Turnstile middleware that attaches `X-Turnstile-Token`\n * headers to requests matching the configured protected paths.\n *\n * The middleware only calls `getToken()` for requests whose URL path ends\n * with one of the `protectedPaths` entries — all other requests pass through\n * untouched with zero overhead.\n *\n * @param options - Configuration options for the turnstile middleware\n * @returns A middleware instance\n *\n * @example\n * ```typescript\n * const turnstileMiddleware = createTurnstileMiddleware({\n * getToken: async () => {\n * // Render Turnstile widget and return token\n * return await turnstile.execute(siteKey);\n * },\n * protectedPaths: ['/sign-up-email-password', '/sign-in-email-password'],\n * });\n * ```\n */\nexport function createTurnstileMiddleware(options: TurnstileMiddlewareOptions): Middleware {\n const { getToken, protectedPaths } = options;\n\n return {\n name: 'turnstile',\n\n async onRequest(ctx: RequestContext): Promise<RequestContext> {\n // Check if this request URL matches any protected path\n const url = new URL(ctx.url, 'http://localhost');\n const isProtected = protectedPaths.some(path => url.pathname.endsWith(path));\n\n if (!isProtected) {\n return ctx;\n }\n\n const token = await getToken();\n const headers = new Headers(ctx.init.headers);\n headers.set('X-Turnstile-Token', token);\n ctx.init.headers = headers;\n\n return ctx;\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { isSupersededError, createTenantSelection, createSessionStorage, createSessionManager, createMemoryStorage, createDefaultStorage, createCrossTabCoordinator, applyJitter, SessionManager, REFRESH_TOKEN_SUPERSEDED } from './chunk-7WAV52EO.js';
2
- import { __export, tryDecodeAccessToken, tokenLifetimeSeconds, supportedClaimsVersions, rolesForTenant, registerClaimsParser, listTenants, isExpired, isDeadSession, expiresAt, defaultRoleForTenant, decodeAccessToken, clearClaimsCache, canSelect, MPFUnsupportedClaimsVersionError, MPFClaimsError, DeadSessionError } from './chunk-AJWM5MDZ.js';
1
+ import { isSupersededError, createTenantSelection, createSessionStorage, createSessionManager, createMemoryStorage, createDefaultStorage, createCrossTabCoordinator, applyJitter, SessionManager, REFRESH_TOKEN_SUPERSEDED } from './chunk-NM63E6OB.js';
2
+ import { __export, tryDecodeAccessToken, tokenLifetimeSeconds, supportedClaimsVersions, rolesForTenant, registerClaimsParser, listTenants, isExpired, isDeadSession, expiresAt, defaultRoleForTenant, decodeAccessToken, clearClaimsCache, canSelect, MPFUnsupportedClaimsVersionError, MPFClaimsError, DeadSessionError } from './chunk-S5DKGPUY.js';
3
3
 
4
4
  // src/auth/index.ts
5
5
  var auth_exports = {};
@@ -81,5 +81,5 @@ var TENANT_DIRECTORY_QUERY = `query MPFTenantDirectory {
81
81
  }`;
82
82
 
83
83
  export { TENANT_DIRECTORY_QUERY, auth_exports, createOAuthStateStore };
84
- //# sourceMappingURL=chunk-GPWGOYCA.js.map
85
- //# sourceMappingURL=chunk-GPWGOYCA.js.map
84
+ //# sourceMappingURL=chunk-FYUVJL4T.js.map
85
+ //# sourceMappingURL=chunk-FYUVJL4T.js.map