@weftlabs/sdk 0.26.7 → 0.26.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/facilitator/middleware/index.js +1 -1
- package/dist/facilitator/middleware/index.js.map +1 -1
- package/dist/facilitator/middleware/index.mjs +1 -1
- package/dist/facilitator/middleware/index.mjs.map +1 -1
- package/dist/index.d.mts +162 -95
- package/dist/index.d.ts +162 -95
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -0
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +1 -1
- package/dist/server.mjs.map +1 -1
- package/docs/SearchEndpointHit.md +4 -0
- package/docs/SearchHelperDocs.md +39 -0
- package/package.json +3 -2
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/facilitator/index.ts","../src/facilitator/client.ts","../src/facilitator/fee.ts","../src/facilitator/middleware/express.ts","../package.json","../src/facilitator/middleware/product.ts","../src/facilitator/middleware/handshake.ts","../src/facilitator/middleware/extensions.ts","../src/facilitator/middleware/replay.ts","../src/facilitator/middleware/settlement.ts","../src/facilitator/middleware/hono.ts"],"sourcesContent":["export * from \"@x402/core/server\";\n\nexport { createFacilitatorClient, X402_FACILITATOR_URL } from \"./facilitator\";\nexport type { WeftFacilitatorConfig } from \"./facilitator\";\nexport { getFeeInfo, invalidateFeeCache } from \"./facilitator/fee\";\nexport type { FeeInfo, FeeCacheConfig } from \"./facilitator/fee\";\nexport * from \"./facilitator/middleware\";\n","export * from \"@x402/core\";\nexport * from \"@x402/core/types\";\n\nexport { X402_FACILITATOR_URL, createFacilitatorClient } from \"./client\";\nexport type { WeftFacilitatorConfig } from \"./client\";\n\nexport { getFeeInfo, invalidateFeeCache } from \"./fee\";\nexport type { FeeInfo, FeeCacheConfig } from \"./fee\";\n","import { HTTPFacilitatorClient, FacilitatorConfig } from \"@x402/core/server\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n} from \"@x402/core/types\";\n\nexport const FACILITATOR_UNAVAILABLE_ERROR =\n \"weft:facilitator-settle-unavailable\";\n\nexport const X402_FACILITATOR_URL = \"https://x402.weft.network\";\nexport const X402_FACILITATOR_URL_ENV = \"X402_FACILITATOR_URL\";\n\nexport interface WeftFacilitatorConfig {\n url?: string;\n createAuthHeaders?: FacilitatorConfig[\"createAuthHeaders\"];\n}\n\nclass FacilitatorUnavailableError extends Error {\n readonly statusCode = 503;\n\n constructor() {\n super(FACILITATOR_UNAVAILABLE_ERROR);\n this.name = \"FacilitatorUnavailableError\";\n }\n}\n\nfunction isUnavailableSettleError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const candidate = error as Error & Record<string, unknown>;\n return (\n candidate.name === \"SettleError\" &&\n candidate.statusCode === 503 &&\n \"errorReason\" in candidate &&\n \"errorMessage\" in candidate &&\n \"payer\" in candidate &&\n \"transaction\" in candidate &&\n \"network\" in candidate &&\n !(candidate.errorReason === \"settlement_pending\" && candidate.transaction)\n );\n}\n\nclass WeftHTTPFacilitatorClient extends HTTPFacilitatorClient {\n override async settle(\n paymentPayload: PaymentPayload,\n paymentRequirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n try {\n return await super.settle(paymentPayload, paymentRequirements);\n } catch (error) {\n if (isUnavailableSettleError(error)) {\n throw new FacilitatorUnavailableError();\n }\n throw error;\n }\n }\n}\n\nexport function validateUrl(url: string): void {\n if (!url || url.trim() === \"\") {\n throw new Error(\"Invalid URL: URL cannot be empty\");\n }\n\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n throw new Error(\n `Invalid URL format: URL must start with http:// or https://, got: ${url}`,\n );\n }\n}\n\nexport function resolveUrl(config?: WeftFacilitatorConfig): string {\n if (config?.url) {\n return config.url;\n }\n\n if (\n typeof process !== \"undefined\" &&\n process.env?.[X402_FACILITATOR_URL_ENV]\n ) {\n return process.env[X402_FACILITATOR_URL_ENV]!;\n }\n\n return X402_FACILITATOR_URL;\n}\n\ntype AuthHeadersByPath = Awaited<\n ReturnType<NonNullable<FacilitatorConfig[\"createAuthHeaders\"]>>\n>;\n\n/**\n * Reject a flat headers object the way `@x402/core` itself would.\n *\n * Upstream's `HTTPFacilitatorClient` throws when `createAuthHeaders` returns\n * `{ Authorization: ... }` instead of `{ supported: { Authorization: ... } }`,\n * because silently dropping auth on every request is worse than failing loud.\n * Merging the handshake's own `supported` headers in would mask that check —\n * the merged object always has a path key — so the check runs here first,\n * with the same failure mode a misconfigured seller sees today.\n *\n * @param headers - What the seller's `createAuthHeaders` returned\n */\nfunction assertPathKeyedAuthHeaders(headers: AuthHeadersByPath): void {\n const isHeaderObject = (value: unknown): boolean =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const hasPathKey = [\"verify\", \"settle\", \"supported\", \"bazaar\"].some((key) =>\n isHeaderObject(headers[key as keyof AuthHeadersByPath]),\n );\n const looksFlat =\n !hasPathKey &&\n Object.values(headers).some((value) => !isHeaderObject(value));\n\n if (looksFlat) {\n throw new Error(\n \"createAuthHeaders must return an object keyed by facilitator path, \" +\n 'e.g. { verify: { Authorization: \"...\" }, settle: { ... }, ' +\n \"supported: { ... } }, but received a flat headers object.\",\n );\n }\n}\n\n/**\n * Merge SDK-derived headers under a seller's, case-insensitively, seller wins.\n *\n * Header names are case-insensitive, but object keys are not: a plain spread\n * would keep a derived `Authorization` and a seller `authorization` as two\n * keys, and the HTTP layer folds those into one comma-joined value — a\n * garbled credential. So a seller header replaces any derived header of the\n * same name whatever its case, and the seller's spelling is the one sent.\n *\n * @param derived - Headers the SDK derived from config for one path\n * @param seller - The seller's own headers for that path, if any\n * @returns The merged headers, the seller's winning on conflict\n */\nfunction mergeSellerWins(\n derived: Record<string, string>,\n seller: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = { ...derived };\n for (const [name, value] of Object.entries(seller ?? {})) {\n for (const existing of Object.keys(merged)) {\n if (existing.toLowerCase() === name.toLowerCase()) {\n delete merged[existing];\n }\n }\n merged[name] = value;\n }\n return merged;\n}\n\nexport function createFacilitatorClient(\n config?: WeftFacilitatorConfig,\n weftAuthHeaders?: AuthHeadersByPath,\n): HTTPFacilitatorClient {\n const url = resolveUrl(config);\n validateUrl(url);\n\n const sellerCreateAuthHeaders = config?.createAuthHeaders;\n\n // Only the paths the SDK actually derived headers for — `supported` always,\n // `settle` and `verify` when an apiKey was configured. Empty paths are\n // dropped so a caller with no derived headers is byte-identical to passing\n // none.\n const derivedByPath = Object.entries(weftAuthHeaders ?? {}).filter(\n ([, headers]) => headers !== undefined && Object.keys(headers).length > 0,\n ) as Array<[keyof AuthHeadersByPath, Record<string, string>]>;\n\n const createAuthHeaders =\n derivedByPath.length > 0\n ? async (): Promise<AuthHeadersByPath> => {\n const sellerHeaders = sellerCreateAuthHeaders\n ? await sellerCreateAuthHeaders()\n : undefined;\n if (sellerHeaders) {\n assertPathKeyedAuthHeaders(sellerHeaders);\n }\n // The seller's own headers win on conflict: an explicit\n // createAuthHeaders is a more deliberate act than `apiKey`.\n const merged: AuthHeadersByPath = { ...sellerHeaders };\n for (const [path, derived] of derivedByPath) {\n merged[path] = mergeSellerWins(derived, sellerHeaders?.[path]);\n }\n return merged;\n }\n : sellerCreateAuthHeaders;\n\n return new WeftHTTPFacilitatorClient({\n url,\n createAuthHeaders,\n });\n}\n","import { createFacilitatorClient, WeftFacilitatorConfig } from \"./client\";\n\nexport interface FeeInfo {\n amount: string;\n asset: string;\n network: string;\n}\n\nexport interface FeeCacheConfig {\n ttl?: number;\n}\n\ninterface FeeCache {\n feeInfo: FeeInfo;\n fetchedAt: number;\n ttl: number;\n}\n\nconst DEFAULT_CACHE_TTL = 5 * 60 * 1000;\n\nlet feeCache: FeeCache | null = null;\n\nexport function invalidateFeeCache(): void {\n feeCache = null;\n}\n\nfunction isCacheValid(): boolean {\n if (!feeCache) return false;\n const now = Date.now();\n return now - feeCache.fetchedAt < feeCache.ttl;\n}\n\nexport async function getFeeInfo(\n config?: WeftFacilitatorConfig,\n cacheConfig?: FeeCacheConfig,\n): Promise<FeeInfo> {\n if (isCacheValid() && feeCache) {\n return feeCache.feeInfo;\n }\n\n const client = createFacilitatorClient(config);\n const supported = await client.getSupported();\n\n const fee = (supported as { fee?: FeeInfo }).fee;\n if (!fee) {\n throw new Error(\"Fee information not found in /supported response\");\n }\n\n if (typeof fee.amount !== \"string\") {\n throw new Error(\"Invalid fee structure: amount must be a string\");\n }\n if (typeof fee.asset !== \"string\") {\n throw new Error(\"Invalid fee structure: asset must be a string\");\n }\n if (typeof fee.network !== \"string\") {\n throw new Error(\"Invalid fee structure: network must be a string\");\n }\n\n const feeInfo: FeeInfo = {\n amount: fee.amount,\n asset: fee.asset,\n network: fee.network,\n };\n\n feeCache = {\n feeInfo,\n fetchedAt: Date.now(),\n ttl: cacheConfig?.ttl ?? DEFAULT_CACHE_TTL,\n };\n\n return feeInfo;\n}\n","import type { OutgoingHttpHeaders } from \"node:http\";\nimport {\n HTTPRequestContext,\n PaywallConfig,\n PaywallProvider,\n SETTLEMENT_OVERRIDES_HEADER,\n withPrivateCacheControl,\n x402ResourceServer,\n HTTPAdapter,\n} from \"@x402/core/server\";\nimport { SchemeNetworkServer, Network } from \"@x402/core/types\";\nimport { createFacilitatorClient, WeftFacilitatorConfig } from \"../client\";\nimport { buildFacilitatorAuthHeaders } from \"./handshake\";\nimport {\n applyProductIdentity,\n WeftProductDeclaration,\n WeftRoutesConfig,\n} from \"./product\";\nimport { registerDynamicExtensions } from \"./extensions\";\nimport {\n paymentResumeCandidate,\n resumePaymentResult,\n type ResumeVerifiedPayment,\n} from \"./replay\";\nimport {\n WeftHTTPResourceServer,\n isFacilitatorUnavailable,\n isFacilitatorUnavailableResponse,\n isJsonResponse,\n} from \"./settlement\";\n\ninterface ExpressRequest {\n method: string;\n path: string;\n protocol: string;\n headers: Record<string, string | string[] | undefined>;\n query: Record<string, string | string[] | undefined>;\n body?: unknown;\n header(name: string): string | string[] | undefined;\n}\n\ninterface ExpressResponse {\n status(code: number): ExpressResponse;\n setHeader(\n name: string,\n value: string | number | readonly string[],\n ): ExpressResponse;\n /**\n * Headers the route handler has set. Read at settlement time so a\n * `Settlement-Overrides` header reaches the facilitator.\n */\n getHeaders(): OutgoingHttpHeaders;\n removeHeader(name: string): void;\n send(body: unknown): ExpressResponse;\n json(body: unknown): ExpressResponse;\n statusCode: number;\n writeHead: (...args: unknown[]) => ExpressResponse;\n write: (...args: unknown[]) => boolean;\n end: (...args: unknown[]) => ExpressResponse;\n flushHeaders: () => void;\n}\n\ntype ExpressNextFunction = (err?: unknown) => void;\n\ntype BufferedCall =\n | [\"writeHead\", unknown[]]\n | [\"write\", unknown[]]\n | [\"end\", unknown[]]\n | [\"flushHeaders\", []];\n\nconst UNSAFE_FAILURE_HEADERS = new Set([\n SETTLEMENT_OVERRIDES_HEADER.toLowerCase(),\n \"location\",\n \"set-cookie\",\n]);\n\nfunction isUnsafeFailureHeader(\n name: string,\n value: string | number | readonly string[] | undefined,\n): boolean {\n const normalized = name.toLowerCase();\n return (\n UNSAFE_FAILURE_HEADERS.has(normalized) ||\n (normalized === \"cache-control\" &&\n value !== undefined &&\n /\\bpublic\\b/i.test(\n Array.isArray(value) ? value.join(\",\") : String(value),\n ))\n );\n}\n\n/**\n * Floor between background facilitator re-sync attempts.\n *\n * Without it, a sustained facilitator outage on a busy server couples retry\n * (and warn) volume to request rate: a refused connection settles in\n * milliseconds, so every protected request would launch a fresh `/supported`\n * call for the whole outage. One attempt per floor interval bounds both.\n */\nconst FACILITATOR_SYNC_RETRY_FLOOR_MS = 30_000;\n\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction,\n) => Promise<void> | void;\n\nexport interface SchemeRegistration {\n network: Network;\n server: SchemeNetworkServer;\n}\n\n/**\n * Configuration for the Express payment middleware.\n *\n * Extends {@link WeftProductDeclaration}, so `name`, `type`, `tags`,\n * `iconUrl`, `productId` and `manifestHash` are declared once here and\n * applied to every protected route.\n */\nexport interface WeftExpressMiddlewareConfig extends WeftProductDeclaration {\n /**\n * The seller's Weft API key.\n *\n * Authenticates the facilitator calls that need it: `X-API-Key` on\n * `/settle` — which the facilitator requires, or every settlement 401s —\n * and `Authorization: Bearer <key>` on the construction-time `/supported`\n * handshake, which is how the dashboard learns an SDK is deployed before\n * any payment. Optional, but a seller who omits it must supply their own\n * `facilitator.createAuthHeaders` or settlement fails.\n */\n apiKey?: string;\n facilitator?: WeftFacilitatorConfig;\n schemes?: SchemeRegistration[];\n paywallConfig?: PaywallConfig;\n paywall?: PaywallProvider;\n syncFacilitatorOnStart?: boolean;\n /** Restore durably bound verified inputs for settlement replay. */\n resumeVerifiedPayment?: ResumeVerifiedPayment;\n}\n\nclass ExpressAdapter implements HTTPAdapter {\n constructor(private req: ExpressRequest) {}\n\n getHeader(name: string): string | undefined {\n const value = this.req.header(name);\n return Array.isArray(value) ? value[0] : value;\n }\n\n getMethod(): string {\n return this.req.method;\n }\n\n getPath(): string {\n return this.req.path;\n }\n\n getUrl(): string {\n const host = this.req.headers.host || \"localhost\";\n return `${this.req.protocol}://${host}${this.req.path}`;\n }\n\n getAcceptHeader(): string {\n return this.getHeader(\"Accept\") || \"\";\n }\n\n getUserAgent(): string {\n return this.getHeader(\"User-Agent\") || \"\";\n }\n\n getQueryParams(): Record<string, string | string[]> {\n return this.req.query as Record<string, string | string[]>;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.req.query[name] as string | string[] | undefined;\n }\n\n getBody(): unknown {\n return this.req.body;\n }\n}\n\n/**\n * Flatten Node's outgoing headers into the plain record\n * `HTTPTransportContext` expects. Array values (a repeated header) are joined,\n * numbers stringified; the settlement override lookup in `@x402/core` compares\n * header names case-insensitively.\n *\n * @param headers - Response headers set by the route handler\n * @returns A plain string record\n */\nfunction toHeaderRecord(headers: OutgoingHttpHeaders): Record<string, string> {\n const record: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n record[key] = Array.isArray(value) ? value.join(\",\") : String(value);\n }\n return record;\n}\n\nfunction responseBodyFromBufferedCalls(\n calls: BufferedCall[],\n): Buffer | undefined {\n const chunks: Buffer[] = [];\n for (const [method, args] of calls) {\n if (method !== \"write\" && method !== \"end\") continue;\n const chunk = args[0];\n if (chunk === undefined) continue;\n if (typeof chunk === \"string\") {\n const encoding = typeof args[1] === \"string\" ? args[1] : \"utf8\";\n if (!Buffer.isEncoding(encoding)) return undefined;\n chunks.push(Buffer.from(chunk, encoding));\n } else if (Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else {\n return undefined;\n }\n }\n return Buffer.concat(chunks);\n}\n\nfunction restoreHeaders(\n res: ExpressResponse,\n headers: OutgoingHttpHeaders,\n): void {\n for (const name of Object.keys(res.getHeaders())) res.removeHeader(name);\n for (const [name, value] of Object.entries(headers)) {\n if (value !== undefined) res.setHeader(name, value);\n }\n}\n\nasync function sendCoreResponse(\n res: ExpressResponse,\n response: {\n status: number;\n headers: Record<string, string | string[]>;\n body?: unknown;\n },\n): Promise<void> {\n res.status(response.status);\n Object.entries(response.headers).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n if (isJsonResponse(response)) {\n res.json(response.body ?? {});\n } else if (response.body instanceof Blob) {\n res.send(Buffer.from(await response.body.arrayBuffer()));\n } else if (response.body instanceof ArrayBuffer) {\n res.send(Buffer.from(response.body));\n } else if (ArrayBuffer.isView(response.body)) {\n res.send(\n Buffer.from(\n response.body.buffer,\n response.body.byteOffset,\n response.body.byteLength,\n ),\n );\n } else {\n res.send(\n typeof response.body === \"string\"\n ? response.body\n : String(response.body ?? \"\"),\n );\n }\n}\n\nfunction sendFacilitatorUnavailable(res: ExpressResponse): void {\n res.removeHeader(\"payment-response\");\n res.removeHeader(SETTLEMENT_OVERRIDES_HEADER);\n res.setHeader(\"retry-after\", \"1\");\n res.setHeader(\"cache-control\", withPrivateCacheControl(null));\n res.status(503).json({ error: \"facilitator_unavailable\" });\n}\n\n/**\n * Create an Express middleware that requires x402 payment for the given routes.\n *\n * Product identity declared on `config` (`name`, `type`, `tags`, `iconUrl`) is\n * merged into every route, so it travels on the 402 challenge's `resource` and\n * from there onto the buyer's payment payload and the settlement event.\n *\n * @param routes - Route configuration, either a path map or a single route;\n * each route may declare its own `type` to override the product's\n * @param config - Facilitator, scheme, paywall and product identity settings\n * @returns An Express middleware function\n */\nexport function weftPaymentMiddleware(\n routes: WeftRoutesConfig,\n config?: WeftExpressMiddlewareConfig,\n): ExpressMiddleware {\n const facilitatorClient = createFacilitatorClient(\n config?.facilitator,\n buildFacilitatorAuthHeaders(\"express\", config?.apiKey, config ?? {}),\n );\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerDynamicExtensions(resourceServer, routes);\n\n if (config?.schemes) {\n config.schemes.forEach(({ network, server: schemeServer }) => {\n resourceServer.register(network, schemeServer);\n });\n }\n\n const httpServer = new WeftHTTPResourceServer(\n resourceServer,\n applyProductIdentity(routes, config ?? {}),\n );\n\n if (config?.paywall) {\n httpServer.registerPaywallProvider(config.paywall);\n }\n\n // The construction-time facilitator sync doubles as the identity handshake,\n // so its failure modes are held to handshake rules: it must never crash the\n // process (a rejection with no handler attached would, under Node's default\n // unhandled-rejection policy) and must never brick the middleware. The\n // returned promise therefore cannot reject, and a failed sync is retried in\n // the background off later protected requests until one attempt succeeds.\n const syncOnStart = config?.syncFacilitatorOnStart ?? true;\n let facilitatorSynced = false;\n let syncInFlight: Promise<void> | null = null;\n let lastFailedSyncAt = 0;\n\n const syncFacilitator = (): Promise<void> => {\n syncInFlight ??= httpServer\n .initialize()\n .then(\n () => {\n facilitatorSynced = true;\n },\n (error: unknown) => {\n lastFailedSyncAt = Date.now();\n console.warn(\n \"[weft] facilitator sync failed; payment-protected routes \" +\n \"degrade until a later attempt succeeds: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n },\n )\n .finally(() => {\n syncInFlight = null;\n });\n return syncInFlight;\n };\n\n let bootSync: Promise<void> | null = syncOnStart ? syncFacilitator() : null;\n\n return async (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction,\n ) => {\n const adapter = new ExpressAdapter(req);\n const context: HTTPRequestContext = {\n adapter,\n path: req.path,\n method: req.method,\n paymentHeader:\n adapter.getHeader(\"payment-signature\") ||\n adapter.getHeader(\"x-payment\"),\n };\n\n if (!httpServer.requiresPayment(context)) {\n return next();\n }\n\n if (bootSync) {\n // The pre-existing first-request barrier: with a healthy facilitator\n // this resolves once and never runs again. It cannot throw.\n await bootSync;\n bootSync = null;\n }\n if (\n syncOnStart &&\n !facilitatorSynced &&\n Date.now() - lastFailedSyncAt >= FACILITATOR_SYNC_RETRY_FLOOR_MS\n ) {\n // Heal a failed boot sync without delaying anyone: the retry is kicked\n // fire-and-forget (one in flight at most, one attempt per floor\n // interval) and this request proceeds.\n void syncFacilitator();\n }\n\n let result;\n try {\n const resumeCandidate = paymentResumeCandidate(context);\n const resumedPayment = resumeCandidate\n ? await config?.resumeVerifiedPayment?.(context, resumeCandidate)\n : undefined;\n result = resumedPayment\n ? resumePaymentResult(resourceServer, resumedPayment, context)\n : await httpServer.processHTTPRequest(context, config?.paywallConfig);\n } catch (error) {\n // Express 4 does not catch a rejection from an async middleware; under\n // Node's default policy that takes the whole process down. Routing the\n // failure through next(error) keeps it inside Express's own error\n // handling, whatever left the resource server unable to answer.\n return next(error);\n }\n\n switch (result.type) {\n case \"no-payment-required\":\n return next();\n\n case \"payment-error\": {\n const { response } = result;\n if (isFacilitatorUnavailableResponse(response)) {\n sendFacilitatorUnavailable(res);\n return;\n }\n await sendCoreResponse(res, response);\n return;\n }\n\n case \"payment-verified\": {\n const {\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n cancellationDispatcher,\n beforeHandlerSettlement,\n } = result;\n\n const originalWriteHead = res.writeHead.bind(res);\n const originalWrite = res.write.bind(res);\n const originalEnd = res.end.bind(res);\n const originalFlushHeaders = res.flushHeaders.bind(res);\n const originalSetHeader = res.setHeader.bind(res);\n const originalRemoveHeader = res.removeHeader.bind(res);\n const headersBeforeHandler = { ...res.getHeaders() };\n\n let bufferedCalls: BufferedCall[] = [];\n let settled = false;\n const failureHeaders = new Map<\n string,\n {\n name: string;\n value?: string | number | readonly string[];\n }\n >();\n\n const restoreResponseMethods = () => {\n res.setHeader = originalSetHeader;\n res.removeHeader = originalRemoveHeader;\n res.writeHead = originalWriteHead;\n res.write = originalWrite;\n res.end = originalEnd;\n res.flushHeaders = originalFlushHeaders;\n };\n\n const replayBufferedCall = ([method, args]: BufferedCall) => {\n if (method === \"writeHead\") {\n const [statusCode, statusMessage] = args;\n return typeof statusMessage === \"string\"\n ? originalWriteHead(statusCode, statusMessage)\n : originalWriteHead(statusCode);\n }\n if (method === \"write\") return originalWrite(...args);\n if (method === \"end\") return originalEnd(...args);\n return originalFlushHeaders();\n };\n\n let endCalled: () => void;\n const endPromise = new Promise<void>((resolve) => {\n endCalled = resolve;\n });\n\n res.writeHead = function (...args: unknown[]) {\n if (!settled) {\n const [statusCode, statusMessageOrHeaders, maybeHeaders] = args;\n if (typeof statusCode === \"number\") {\n res.statusCode = statusCode;\n }\n const headers =\n typeof statusMessageOrHeaders === \"string\"\n ? maybeHeaders\n : statusMessageOrHeaders;\n if (Array.isArray(headers)) {\n const grouped = new Map<\n string,\n { name: string; values: string[] }\n >();\n for (let index = 0; index < headers.length; index += 2) {\n const name = String(headers[index]);\n const key = name.toLowerCase();\n const entry = grouped.get(key) ?? { name, values: [] };\n entry.values.push(String(headers[index + 1]));\n grouped.set(key, entry);\n }\n for (const { name, values } of grouped.values()) {\n res.setHeader(name, values.length === 1 ? values[0] : values);\n }\n } else if (headers && typeof headers === \"object\") {\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n res.setHeader(\n key,\n Array.isArray(value) ? value : String(value),\n );\n }\n }\n bufferedCalls.push([\"writeHead\", args]);\n return res;\n }\n return originalWriteHead(...args);\n } as typeof res.writeHead;\n\n res.setHeader = function (name, value) {\n const result = originalSetHeader(name, value);\n if (!settled && res.statusCode >= 400) {\n failureHeaders.set(name.toLowerCase(), {\n name,\n value: Array.isArray(value) ? [...value] : value,\n });\n }\n return result;\n } as typeof res.setHeader;\n\n res.removeHeader = function (name) {\n originalRemoveHeader(name);\n if (!settled && res.statusCode >= 400) {\n failureHeaders.set(name.toLowerCase(), { name });\n }\n };\n\n res.write = function (...args: unknown[]) {\n if (!settled) {\n bufferedCalls.push([\"write\", args]);\n return true;\n }\n return originalWrite(...args);\n } as typeof res.write;\n\n res.end = function (...args: unknown[]) {\n if (!settled) {\n bufferedCalls.push([\"end\", args]);\n endCalled();\n return res;\n }\n return originalEnd(...args);\n } as typeof res.end;\n\n res.flushHeaders = function () {\n if (!settled) {\n bufferedCalls.push([\"flushHeaders\", []]);\n return;\n }\n return originalFlushHeaders();\n };\n\n const finalizeFailure = async (\n cancellation:\n | { reason: \"handler_threw\"; error: unknown }\n | { reason: \"handler_failed\"; responseStatus: number },\n ) => {\n // Express exposes only the final header bag, not whether a pre-status\n // header belongs to a direct error response or a later throw. Preserve\n // by default and remove only headers that can leak payment or success.\n const preservedFailureHeaders = new Map<\n string,\n string | number | readonly string[]\n >();\n for (const [name, value] of Object.entries(res.getHeaders())) {\n if (value === undefined || isUnsafeFailureHeader(name, value))\n continue;\n preservedFailureHeaders.set(\n name,\n Array.isArray(value) ? [...value] : value,\n );\n }\n const cancelSettlement =\n await cancellationDispatcher.cancel(cancellation);\n settled = true;\n restoreHeaders(res, headersBeforeHandler);\n for (const [name, value] of Object.entries(res.getHeaders())) {\n if (isUnsafeFailureHeader(name, value)) res.removeHeader(name);\n }\n for (const [name, value] of preservedFailureHeaders) {\n res.setHeader(name, value);\n }\n for (const { name, value } of failureHeaders.values()) {\n if (value === undefined || isUnsafeFailureHeader(name, value))\n res.removeHeader(name);\n else res.setHeader(name, value);\n }\n const existingCacheControl = Object.entries(res.getHeaders()).find(\n ([key]) => key.toLowerCase() === \"cache-control\",\n )?.[1];\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n Array.isArray(existingCacheControl)\n ? existingCacheControl.join(\",\")\n : existingCacheControl === undefined\n ? undefined\n : String(existingCacheControl),\n );\n Object.entries(headers ?? {}).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n restoreResponseMethods();\n\n for (const call of bufferedCalls) replayBufferedCall(call);\n bufferedCalls = [];\n };\n\n try {\n next();\n } catch (error) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n failureHeaders.clear();\n try {\n next(error);\n } catch (errorMiddlewareError) {\n restoreResponseMethods();\n throw errorMiddlewareError;\n }\n await endPromise;\n await finalizeFailure({ reason: \"handler_threw\", error });\n return;\n }\n\n await endPromise;\n\n if (res.statusCode >= 400) {\n await finalizeFailure({\n reason: \"handler_failed\",\n responseStatus: res.statusCode,\n });\n return;\n }\n\n try {\n const settleResult = await httpServer.processSettlement(\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n // The route handler signals a settlement override (a metered amount\n // below the signed maximum) through a response header.\n // `processSettlement` only reads that off `transportContext`, so\n // omitting this settles the full authorised amount and makes\n // `upto` behave exactly like `exact`.\n {\n request: context,\n responseBody: responseBodyFromBufferedCalls(bufferedCalls),\n responseHeaders: toHeaderRecord(res.getHeaders()),\n },\n undefined,\n beforeHandlerSettlement,\n );\n\n if (!settleResult.success) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n if (isFacilitatorUnavailable(settleResult.errorReason)) {\n sendFacilitatorUnavailable(res);\n return;\n }\n const { response } = settleResult;\n await sendCoreResponse(res, response);\n return;\n }\n\n Object.entries(settleResult.headers).forEach(([key, value]) => {\n const headerValue = Array.isArray(value)\n ? value.join(\",\")\n : String(value);\n res.setHeader(key, headerValue);\n });\n const cacheControl = res.getHeaders()[\"cache-control\"];\n res.setHeader(\n \"cache-control\",\n withPrivateCacheControl(\n Array.isArray(cacheControl)\n ? cacheControl.join(\",\")\n : cacheControl === undefined\n ? null\n : String(cacheControl),\n ),\n );\n res.removeHeader(SETTLEMENT_OVERRIDES_HEADER);\n } catch (error) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n settled = true;\n restoreResponseMethods();\n next(error);\n return;\n } finally {\n settled = true;\n restoreResponseMethods();\n\n for (const call of bufferedCalls) replayBufferedCall(call);\n bufferedCalls = [];\n }\n return;\n }\n }\n };\n}\n","{\n \"name\": \"@weftlabs/sdk\",\n \"version\": \"0.26.7\",\n \"description\": \"Unified Weft SDK for the Weft API and x402 Facilitator\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"./facilitator\": {\n \"import\": {\n \"types\": \"./dist/facilitator/index.d.mts\",\n \"default\": \"./dist/facilitator/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/facilitator/index.d.ts\",\n \"default\": \"./dist/facilitator/index.js\"\n }\n },\n \"./facilitator/middleware\": {\n \"import\": {\n \"types\": \"./dist/facilitator/middleware/index.d.mts\",\n \"default\": \"./dist/facilitator/middleware/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/facilitator/middleware/index.d.ts\",\n \"default\": \"./dist/facilitator/middleware/index.js\"\n }\n },\n \"./server\": {\n \"import\": {\n \"types\": \"./dist/server.d.mts\",\n \"default\": \"./dist/server.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/server.d.ts\",\n \"default\": \"./dist/server.js\"\n }\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest run\",\n \"test:unit\": \"vitest run\",\n \"lint\": \"eslint --fix\",\n \"lint:check\": \"eslint\",\n \"format\": \"prettier --write \\\"src/**/*.ts\\\" \\\"!src/generated/**\\\" \\\"examples/*.mjs\\\" \\\"../scripts/test-typescript-quickstarts.mjs\\\" \\\"../scripts/test-seller-quickstarts.mjs\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.ts\\\" \\\"!src/generated/**\\\" \\\"examples/*.mjs\\\" \\\"../scripts/test-typescript-quickstarts.mjs\\\" \\\"../scripts/test-seller-quickstarts.mjs\\\"\",\n \"hooks:pre-push\": \"pnpm run lint:check && pnpm run format:check && vitest run\",\n \"generate\": \"../scripts/generate-typescript.sh\",\n \"smoke\": \"pnpm run build && node ../scripts/weft-smoke.mjs\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"keywords\": [\n \"weft\",\n \"x402\",\n \"payments\",\n \"micropayments\",\n \"coinbase\",\n \"sdk\"\n ],\n \"author\": \"Weft Labs\",\n \"license\": \"Apache-2.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/weftlabs/weft-sdk\"\n },\n \"peerDependencies\": {\n \"@x402/core\": \"^2.24.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^26.1.2\",\n \"@typescript-eslint/eslint-plugin\": \"^8.29.1\",\n \"@typescript-eslint/parser\": \"^8.29.1\",\n \"@x402/core\": \"2.24.0\",\n \"eslint\": \"^10.4.1\",\n \"express\": \"^5.2.1\",\n \"fast-check\": \"^4.8.0\",\n \"hono\": \"^4.13.5\",\n \"prettier\": \"3.9.6\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.8\"\n },\n \"files\": [\n \"dist\",\n \"docs\",\n \"examples\",\n \"README.md\"\n ],\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"packageManager\": \"pnpm@10.33.4\",\n \"overrides\": {\n \"esbuild\": \"^0.28.1\"\n }\n}\n","import type { RouteConfig, RoutesConfig } from \"@x402/core/server\";\n\n/**\n * What kind of thing the seller is selling.\n *\n * Deliberately small. If you need a kind that is not here, use `tags`.\n */\nexport type WeftProductType = \"api\" | \"agent\" | \"mcp\";\n\n/**\n * The legal {@link WeftProductType} values, as data.\n *\n * `WeftProductType` is erased at compile time and this package ships plain\n * `.mjs` examples, so the type is checked against this list at runtime too.\n */\nconst PRODUCT_TYPES: readonly string[] = [\"api\", \"agent\", \"mcp\"];\n\n/**\n * Reserved tag prefix that carries {@link WeftProductIdentity.type} on the wire.\n *\n * `ResourceInfo` in the x402 protocol has no field for a product kind, and the\n * facilitator only relays `serviceName`, `tags` and `iconUrl` to the settlement\n * event. `tags` is therefore the only channel a product type can travel in, so\n * the SDK encodes it as one reserved tag — `weft:type:api`, `weft:type:agent`,\n * `weft:type:mcp`.\n *\n * The prefix is namespaced so it cannot collide with a seller's own free-text\n * tags, stays readable in a raw settlement row, and is matched downstream with\n * a plain `startsWith`. The SDK guarantees at most one such tag per route: any\n * `weft:type:*` value a caller puts in `tags` is dropped with a warning, in\n * favour of the `type` field on the product or on the route.\n */\nexport const WEFT_TYPE_TAG_PREFIX = \"weft:type:\";\n\n/**\n * Bounds the x402 protocol declares for the `ResourceInfo` identity fields.\n *\n * `ResourceInfoSchema` in `@x402/core/schemas` caps `tags` at five entries of\n * 1-32 printable-ASCII characters, `serviceName` at 1-32 printable-ASCII\n * characters, and `iconUrl` at 2048 characters. No code path inside\n * `@x402/core` applies that schema when a challenge is built, but it is the\n * published contract, and `parsePaymentRequired` — which any buyer may run —\n * rejects the *whole* `PaymentRequired` when a single field is out of bounds.\n *\n * The SDK therefore never emits a value outside these bounds. A declared\n * `type` spends one of the five tag slots, leaving four for the seller.\n *\n * These are the *protocol's* bounds, not the Weft facilitator's, which are\n * looser. That is deliberate: the challenge is read by buyers before it ever\n * reaches a facilitator, so the narrower contract is the one that has to hold.\n * It costs sellers whose names are not expressible in ASCII — a real cost,\n * carried knowingly, and the right place to fix it is the protocol schema.\n */\nconst MAX_TAGS = 5;\nconst MAX_TAG_CHARS = 32;\n/**\n * Bounds on declared analytics dimensions.\n *\n * These are Weft's own, not the x402 protocol's: dimensions never touch the\n * 402 challenge. They travel only on the authenticated boot handshake, where\n * the facilitator caps the whole `X-Weft-Declared` header at 8 KiB.\n *\n * Eight is a deliberate ceiling on ambition rather than on bytes. A dimension\n * is a low-cardinality slice a seller wants revenue broken down by; a seller\n * declaring more than a handful is dumping their parameter list, which is the\n * failure mode the whole rule exists to prevent.\n */\nconst MAX_DIMENSIONS = 8;\nconst MAX_DIMENSION_CHARS = 64;\n/**\n * Shape a declared dimension name must have: a plausible JSON field name.\n *\n * A dimension names a key inside `weft.request`'s `info`, and downstream it\n * becomes an allowlist entry that a SQL aggregate reads. Constraining it to\n * the characters real field names use keeps a hostile or accidental value\n * from ever reaching that position.\n */\nconst DIMENSION_NAME = /^[A-Za-z_][A-Za-z0-9_.-]*$/;\nconst MAX_SERVICE_NAME_CHARS = 32;\nconst MAX_ICON_URL_CHARS = 2048;\nconst PRINTABLE_ASCII = /^[\\x20-\\x7e]+$/;\n\n/**\n * Product-level identity, declared once and applied to every protected route.\n *\n * This is what turns a settlement into a named product in the Weft dashboard.\n * Every field is optional; a middleware configured without any of them behaves\n * exactly as it did before this identity existed.\n *\n * Every field is also validated at construction time, because these values\n * routinely come from JSON or env and TypeScript is not present at runtime.\n * Anything the x402 protocol cannot carry is clamped or dropped, with one\n * `[weft]` line explaining what shipped — never a thrown error in a payment\n * server's boot path, and never a malformed challenge on the wire.\n */\nexport interface WeftProductIdentity {\n /**\n * Display name of the product, e.g. `\"Acme Pricing API\"`.\n *\n * Travels as `ResourceInfo.serviceName` on the 402 challenge. The protocol\n * carries 32 printable-ASCII characters; a longer name is truncated to fit,\n * with a warning naming both values.\n */\n name?: string;\n\n /**\n * What kind of product this is.\n *\n * Travels as a reserved `weft:type:<type>` tag — see {@link WEFT_TYPE_TAG_PREFIX}.\n * A route may declare its own `type`, which wins for that route.\n */\n type?: WeftProductType;\n\n /**\n * Free-text tags describing the product, e.g. `[\"finance\", \"pricing\"]`.\n *\n * Travels as `ResourceInfo.tags`. Tags starting with `weft:type:` are\n * reserved and are dropped in favour of {@link WeftProductIdentity.type}.\n *\n * The x402 protocol allows five tags of at most 32 printable-ASCII\n * characters. A declared `type` uses one slot, so four remain. Anything\n * beyond that is dropped with a warning rather than being put on the wire,\n * because an out-of-bounds array costs the seller every tag they declared.\n */\n tags?: string[];\n\n /**\n * Absolute `http:` or `https:` URL of an icon for the product.\n *\n * Travels as `ResourceInfo.iconUrl`. A dashboard renders this URL, so any\n * other scheme is dropped with a warning.\n */\n iconUrl?: string;\n}\n\n/**\n * Extension key under which the product declaration travels on the wire.\n *\n * Unlike the identity fields, which ride `ResourceInfo`, the product\n * declaration rides x402 v2 `extensions`: declared by the server on the 402\n * challenge, echoed by the buyer's client onto `PaymentPayload`, validated\n * against the advertisement at verify time, and relayed by the facilitator on\n * the settlement event.\n */\nexport const WEFT_PRODUCT_EXTENSION_KEY = \"weft.product\";\n\n/**\n * JSON Schema (Draft 2020-12) for the `weft.product` extension's `info`.\n *\n * Ships verbatim as the extension's `schema` member, per the x402 v2\n * extensions shape `{info, schema}`. Every field is optional because absent\n * declarations are omitted from `info` rather than sent empty.\n *\n * `additionalProperties: false` is a **published contract statement, not an\n * enforcement**. Upstream's echo check is a subset match — advertised `info`\n * fields must be preserved, but a buyer may *add* fields to the echoed\n * `info` and pass, and when a route advertises no extensions the check never\n * runs. So an echoed `weft.product` proves nothing about fields the seller\n * did not advertise: by the time it reaches a consumer it is unauthenticated\n * buyer input. A buyer has no legitimate reason to add fields to a seller\n * claim, and this flag is the declared basis for consumers to strip\n * anything unadvertised — but the stripping, and the deeper rule, are the\n * consumer's job. Attribution must never key on echoed extension contents;\n * it keys on seller-authenticated joins — the API key that settled the\n * payment (weft-app #635 freezes `payments.product_id` from exactly that at\n * settlement time) or the S1 handshake's authenticated declaration.\n */\nexport const WEFT_PRODUCT_INFO_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...PRODUCT_TYPES] },\n product_id: { type: \"string\", minLength: 1 },\n manifest_hash: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n} as const;\n\n/**\n * Product-level declaration: the identity plus the product reference fields.\n *\n * `productId` and `manifestHash` are not cosmetic identity — they are the\n * seller's claim about *which* dashboard product this deployment is and what\n * manifest it was built from. They travel in the `weft.product` extension,\n * never in `ResourceInfo`, so they extend the identity type rather than\n * joining it.\n */\nexport interface WeftProductDeclaration extends WeftProductIdentity {\n /**\n * Identifier of the dashboard product this deployment claims to be.\n *\n * Travels as `extensions[\"weft.product\"].info.product_id` on the 402\n * challenge and, echoed by the buyer, on the payment payload the\n * facilitator settles.\n */\n productId?: string;\n\n /**\n * Hash of the product manifest this deployment was built from.\n *\n * Travels as `extensions[\"weft.product\"].info.manifest_hash`, next to\n * {@link WeftProductDeclaration.productId}. Opaque to the SDK: no format is\n * enforced beyond being a non-empty string.\n */\n manifestHash?: string;\n\n /**\n * Field names inside `weft.request` that revenue may be broken down by,\n * e.g. `[\"model\", \"tier\"]`.\n *\n * Travels only on the authenticated boot handshake — never on the 402\n * challenge, never in `weft.product`. That is the point of it: the values\n * on a payment are buyer-echoed, so an aggregate summing an *undeclared*\n * key would be summing buyer-controlled input. A field declared here is\n * one the seller vouched for under their own API key, which is what makes\n * \"revenue for model=gpt-5.6 this month\" an answer rather than a guess.\n *\n * Declare dimensions, not payloads. Low cardinality, enumerable: `model`,\n * `tier`, `size`, `region`. Never prompt text, a user id or a document\n * body — those blow up the index, leak content, and are useless as a\n * breakdown anyway.\n */\n dimensions?: string[];\n}\n\n/**\n * A route config that may also declare the product kind for that route alone.\n *\n * `RouteConfig` comes from `@x402/core` and has no field for a product kind.\n * A seller whose surface is part API and part MCP needs to say so per route,\n * so the SDK accepts `type` here, consumes it into the reserved tag, and never\n * passes the field itself down to the resource server.\n *\n * The inherited `extensions` map gains one capability here: any value may be a\n * `WeftDynamicExtension` callback instead of a static object, resolved per\n * request at the same point as `price`. The field is already typed\n * `Record<string, unknown>` upstream, so this needs no wider type — only the\n * middleware registering the resolver for those keys.\n */\nexport interface WeftRouteConfig extends RouteConfig {\n /** Product kind for this route; overrides {@link WeftProductIdentity.type}. */\n type?: WeftProductType;\n}\n\n/** {@link RoutesConfig}, with per-route {@link WeftRouteConfig.type} allowed. */\nexport type WeftRoutesConfig =\n Record<string, WeftRouteConfig> | WeftRouteConfig;\n\n/**\n * Build the reserved tag for a product type.\n *\n * @param type - The product type to encode\n * @returns The reserved tag, e.g. `weft:type:api`\n */\nexport function productTypeTag(type: WeftProductType): string {\n return `${WEFT_TYPE_TAG_PREFIX}${type}`;\n}\n\n/**\n * Whether a caller actually declared a value.\n *\n * `null` reads as \"absent\": upstream types every identity field `.nullish()`,\n * and a seller whose JSON config carries an explicit null means they have no\n * name, not that they want `null` on the wire. Treating it as absent also\n * keeps the field off challenges consumed by `@x402/core` 2.14, which typed\n * these `.optional()` and rejects an explicit null — and the peer range\n * (`^2.0.0`) lets a seller pin exactly that.\n *\n * @param value - A declared identity value\n * @returns True when the caller supplied something other than null/undefined\n */\nfunction isDeclared(value: unknown): boolean {\n return value !== undefined && value !== null;\n}\n\n/**\n * Name a value's runtime type for a diagnostic.\n *\n * @param value - The offending value\n * @returns A short phrase, e.g. `a number`, `an array`, `null`\n */\nfunction typeName(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (Array.isArray(value)) {\n return \"an array\";\n }\n return `a ${typeof value}`;\n}\n\n/**\n * Render a value for a diagnostic without ever throwing.\n *\n * @param value - The offending value\n * @returns A quoted, escaped rendering of the value\n */\nfunction show(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return typeName(value);\n }\n}\n\n/**\n * Discriminate the two shapes of `RoutesConfig`.\n *\n * Mirrors the check `@x402/core` uses itself (`\"accepts\" in routes`) so a\n * config the resource server treats as a single route is treated the same way\n * here.\n *\n * @param routes - Route configuration passed by the caller\n * @returns True when `routes` is a single route rather than a path map\n */\nfunction isSingleRoute(routes: WeftRoutesConfig): routes is WeftRouteConfig {\n return \"accepts\" in routes;\n}\n\n/**\n * Reports identity the seller declared but that will not ship as written.\n *\n * `dedupeKey` names the *problem*, and defaults to the message. A caller whose\n * message carries per-occurrence detail — an exception message, a byte count —\n * must pass one, or every occurrence is both a fresh log line and a permanent\n * entry in the sink's memory.\n */\nexport type Warn = (message: string, dedupeKey?: string) => void;\n\n/**\n * Build a warning sink that emits each distinct problem once.\n *\n * Product-level identity is applied to every route, so an over-long tag would\n * otherwise produce one identical line per route at boot. Identity warnings are\n * all emitted when the middleware is built, so they land in boot output rather\n * than in a payment path; the one sink that runs per request — a failing\n * {@link WeftDynamicExtension} — leans on the same de-duplication to stay one\n * line per distinct problem instead of one per request.\n *\n * That per-request use is why the key is separable from the message. A sink\n * that remembered whole messages would, for a callback whose failure carries a\n * request id, log every request and grow a set that is never collected — a\n * memory leak in a payment path, dressed as de-duplication.\n *\n * @returns A warn function that suppresses repeats\n */\nexport function createWarn(): Warn {\n const seen = new Set<string>();\n\n return (message: string, dedupeKey?: string) => {\n const key = dedupeKey ?? message;\n if (seen.has(key)) {\n return;\n }\n seen.add(key);\n console.warn(`[weft] ${message}`);\n };\n}\n\n/**\n * Read a declared value that has to be a string.\n *\n * @param field - Field name, for the diagnostic\n * @param value - The declared value, from a route or from the product identity\n * @param warn - Sink for anything that will not ship\n * @returns The string, or undefined when absent or unusable\n */\nfunction asString(\n field: string,\n value: unknown,\n warn: Warn,\n): string | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (typeof value !== \"string\") {\n warn(\n `ignoring ${field} ${show(value)}: expected a string, got ` +\n `${typeName(value)}`,\n );\n return undefined;\n }\n return value;\n}\n\n/**\n * Whether a tag is using the reserved product-type namespace.\n *\n * Matched leniently — case-folded and trimmed — so `\"WEFT:TYPE:mcp\"` and\n * `\" weft:type:mcp\"` are recognised as the reserved form a reader would have\n * to interpret, rather than surviving as free-text tags that contradict the\n * one-type-per-route guarantee and burn a tag slot doing it.\n *\n * @param tag - A seller-declared tag\n * @returns True when the tag occupies the reserved namespace\n */\nfunction isReservedTypeTag(tag: string): boolean {\n return tag.trim().toLowerCase().startsWith(WEFT_TYPE_TAG_PREFIX);\n}\n\n/**\n * Read a declared product type, rejecting anything not in the legal set.\n *\n * `WeftProductType` is a compile-time type only, and the reserved tag it\n * becomes is subject to the same protocol bounds as every other tag. An\n * unchecked value here is worse than an unchecked free-text tag: the Weft\n * facilitator drops the entire `tags` array when a single entry is malformed,\n * so a junk `type` costs the seller every tag they declared — through the very\n * value the tag bounds exist to protect.\n *\n * @param value - The declared type, from a route or from the product identity\n * @param field - Field name, for the diagnostic\n * @param warn - Sink for anything that will not ship\n * @returns The product type, or undefined when absent or illegal\n */\nfunction resolveType(\n value: unknown,\n field: string,\n warn: Warn,\n): WeftProductType | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (typeof value !== \"string\" || !PRODUCT_TYPES.includes(value)) {\n warn(\n `ignoring ${field} ${show(value)}: expected one of ` +\n `${PRODUCT_TYPES.join(\", \")}`,\n );\n return undefined;\n }\n return value as WeftProductType;\n}\n\n/**\n * Read a declared tag list, dropping entries that are not strings.\n *\n * @param value - The declared tags, from a route or from the product identity\n * @param field - Field name, for the diagnostic\n * @param warn - Sink for anything that will not ship\n * @returns The string tags, or undefined when absent or unusable\n */\nfunction asTagList(\n value: unknown,\n field: string,\n warn: Warn,\n): string[] | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (!Array.isArray(value)) {\n warn(\n `ignoring ${field} ${show(value)}: expected an array of strings, got ` +\n `${typeName(value)}`,\n );\n return undefined;\n }\n\n return value.filter((entry): entry is string => {\n if (typeof entry === \"string\") {\n return true;\n }\n warn(\n `dropping tag ${show(entry)}: expected a string, got ` +\n `${typeName(entry)}`,\n );\n return false;\n });\n}\n\n/**\n * Resolve the tags for one route.\n *\n * Route tags win over product tags wholesale — a seller who lists tags on a\n * route means exactly those. The product type is not a tag default though: it\n * is a separate declaration that happens to travel in the tags channel, so it\n * is always applied on top, and reserved `weft:type:*` values supplied by the\n * caller are dropped so exactly one type ever reaches the settlement event.\n *\n * The type tag is placed first, so if the seller declared more tags than the\n * protocol carries, the product type is the one thing guaranteed to survive.\n * It is then filtered by the same bounds as every other tag rather than being\n * trusted: nothing reaches the wire unchecked, including values the SDK built\n * itself.\n *\n * @param routeTags - Tags declared on the route, if any\n * @param identityTags - Tags declared on the product identity, if any\n * @param type - The already-validated type for this route, if any\n * @param warn - Sink for anything dropped\n * @returns The tags to put on the wire, or undefined to leave `tags` absent\n */\nfunction resolveTags(\n routeTags: unknown,\n identityTags: unknown,\n type: WeftProductType | undefined,\n warn: Warn,\n): string[] | undefined {\n const declared =\n asTagList(routeTags, \"route tags\", warn) ??\n asTagList(identityTags, \"tags\", warn);\n\n if (declared === undefined && type === undefined) {\n return undefined;\n }\n\n const sellerTags = (declared ?? []).filter((tag) => {\n if (!isReservedTypeTag(tag)) {\n return true;\n }\n warn(\n `dropping reserved tag ${show(tag)}: declare the product kind with ` +\n `\\`type\\` (${PRODUCT_TYPES.join(\", \")}) on the middleware config or ` +\n `on the route`,\n );\n return false;\n });\n\n const malformed: string[] = [];\n const carried = [\n ...(type !== undefined ? [productTypeTag(type)] : []),\n ...sellerTags,\n ].filter((tag) => {\n if (tag.length <= MAX_TAG_CHARS && PRINTABLE_ASCII.test(tag)) {\n return true;\n }\n malformed.push(tag);\n return false;\n });\n\n if (malformed.length > 0) {\n warn(\n `dropping ${malformed.length} tag(s) the x402 protocol cannot carry ` +\n `(max ${MAX_TAG_CHARS} printable-ASCII characters each): ` +\n `${malformed.join(\", \")}`,\n );\n }\n\n const deduped = [...new Set(carried)];\n\n if (deduped.length > MAX_TAGS) {\n const dropped = deduped.slice(MAX_TAGS);\n warn(\n `dropping ${dropped.length} tag(s): the x402 protocol carries ` +\n `${MAX_TAGS}` +\n (type !== undefined ? \" and the declared type uses one of them\" : \"\") +\n `. Dropped: ${dropped.join(\", \")}`,\n );\n }\n\n const bounded = deduped.slice(0, MAX_TAGS);\n return bounded.length > 0 ? bounded : undefined;\n}\n\n/**\n * Resolve the service name for one route, keeping it inside the x402 schema.\n *\n * An over-long name is truncated rather than rejected. The alternative — a\n * thrown error at construction — turns a cosmetic field into a boot failure on\n * a payment server, and 32 characters is tight enough that ordinary product\n * names exceed it. Sending it unchanged is not an option either: it is the\n * whole `PaymentRequired` that `parsePaymentRequired` rejects, not the field,\n * so an over-long name costs the seller the entire challenge.\n *\n * Truncating is also what the SDK already does to tags, for the same reason.\n * A name that cannot be represented at all — empty, or not printable ASCII —\n * is dropped instead, because there is nothing left to truncate to.\n *\n * @param routeServiceName - Service name declared on the route, if any\n * @param identityName - Product name declared on the middleware config, if any\n * @param warn - Sink for anything that will not travel as declared\n * @returns The service name to put on the wire, or undefined to leave it absent\n */\nfunction resolveServiceName(\n routeServiceName: unknown,\n identityName: unknown,\n warn: Warn,\n): string | undefined {\n const declared =\n asString(\"route serviceName\", routeServiceName, warn) ??\n asString(\"name\", identityName, warn);\n\n if (declared === undefined) {\n return undefined;\n }\n\n if (!PRINTABLE_ASCII.test(declared)) {\n warn(\n `dropping product name ${show(declared)}: the x402 protocol carries ` +\n `1-${MAX_SERVICE_NAME_CHARS} printable-ASCII characters ` +\n `(U+0020-U+007E)`,\n );\n return undefined;\n }\n\n if (declared.length > MAX_SERVICE_NAME_CHARS) {\n const truncated = declared.slice(0, MAX_SERVICE_NAME_CHARS);\n warn(\n `product name ${show(declared)} is ${declared.length} characters; the ` +\n `x402 protocol carries ${MAX_SERVICE_NAME_CHARS}, so it travels as ` +\n `${show(truncated)}`,\n );\n return truncated;\n }\n\n return declared;\n}\n\n/**\n * Resolve the icon URL for one route.\n *\n * This is the last Weft-authored check before a URL the SDK put on a challenge\n * is rendered in someone's dashboard: the facilitator relays `iconUrl` without\n * inspecting its scheme. So the SDK only emits absolute `http:`/`https:` URLs\n * inside the protocol's length bound, and drops anything else with a warning.\n *\n * @param routeIconUrl - Icon URL declared on the route, if any\n * @param identityIconUrl - Icon URL declared on the middleware config, if any\n * @param warn - Sink for anything that will not ship\n * @returns The icon URL to put on the wire, or undefined to leave it absent\n */\nfunction resolveIconUrl(\n routeIconUrl: unknown,\n identityIconUrl: unknown,\n warn: Warn,\n): string | undefined {\n const declared =\n asString(\"route iconUrl\", routeIconUrl, warn) ??\n asString(\"iconUrl\", identityIconUrl, warn);\n\n if (declared === undefined) {\n return undefined;\n }\n\n if (declared.length > MAX_ICON_URL_CHARS) {\n warn(\n `dropping iconUrl: ${declared.length} characters exceeds the ` +\n `${MAX_ICON_URL_CHARS} the x402 protocol carries`,\n );\n return undefined;\n }\n\n let scheme: string;\n try {\n scheme = new URL(declared).protocol;\n } catch {\n warn(\n `dropping iconUrl ${show(declared)}: expected an absolute http or ` +\n `https URL`,\n );\n return undefined;\n }\n\n if (scheme !== \"http:\" && scheme !== \"https:\") {\n warn(\n `dropping iconUrl ${show(declared)}: only http and https are carried ` +\n `(a dashboard renders this URL)`,\n );\n return undefined;\n }\n\n return declared;\n}\n\n/**\n * Resolve the analytics dimensions a seller declared.\n *\n * Same posture as every other declared value here — clamp, drop, warn once,\n * never throw in a boot path — with bounds that are Weft's rather than the\n * protocol's, because these travel on the handshake alone.\n *\n * @param value - The declared `dimensions` value, from config or env\n * @param warn - Sink for anything that will not ship\n * @returns The dimension names that will travel, or undefined when none do\n */\nexport function resolveDimensions(\n value: unknown,\n warn: Warn,\n): string[] | undefined {\n const declared = asTagList(value, \"dimensions\", warn);\n if (declared === undefined) {\n return undefined;\n }\n\n const malformed: string[] = [];\n const named = declared.filter((name) => {\n if (name.length <= MAX_DIMENSION_CHARS && DIMENSION_NAME.test(name)) {\n return true;\n }\n malformed.push(name);\n return false;\n });\n\n if (malformed.length > 0) {\n warn(\n `dropping ${malformed.length} dimension(s) that do not name a field ` +\n `(max ${MAX_DIMENSION_CHARS} characters, starting with a letter or ` +\n `underscore): ${malformed.join(\", \")}`,\n );\n }\n\n const deduped = [...new Set(named)];\n\n if (deduped.length > MAX_DIMENSIONS) {\n warn(\n `dropping ${deduped.length - MAX_DIMENSIONS} dimension(s): at most ` +\n `${MAX_DIMENSIONS} travel. Dropped: ` +\n `${deduped.slice(MAX_DIMENSIONS).join(\", \")}`,\n );\n }\n\n const bounded = deduped.slice(0, MAX_DIMENSIONS);\n return bounded.length > 0 ? bounded : undefined;\n}\n\n/**\n * Read a declared opaque reference string, refusing blanks.\n *\n * `product_id` and `manifest_hash` have no protocol bound to clamp to, but an\n * empty value is not a declaration — the contract is that absent fields are\n * omitted from `info`, never sent empty. The value ships trimmed: these ids\n * exist to be joined against dashboard records by exact string, and padding\n * from a sloppy env var would silently fail that join.\n *\n * @param field - Field name, for the diagnostic\n * @param value - The declared value\n * @param warn - Sink for anything that will not ship\n * @returns The trimmed string, or undefined when absent, blank or unusable\n */\nfunction resolveOpaqueString(\n field: string,\n value: unknown,\n warn: Warn,\n): string | undefined {\n const declared = asString(field, value, warn);\n if (declared === undefined) {\n return undefined;\n }\n const trimmed = declared.trim();\n if (trimmed === \"\") {\n warn(`ignoring empty ${field}`);\n return undefined;\n }\n return trimmed;\n}\n\n/**\n * Build the `extensions` object for one route, declaring `weft.product`.\n *\n * The declaration is emitted only when it would say something — a resolved\n * kind, product id or manifest hash — and each absent field is omitted from\n * `info`, never sent empty. A route that already declares `weft.product` in\n * its own `extensions` keeps its declaration: per-route always wins over the\n * product level, exactly as it does for `serviceName`.\n *\n * @param routeExtensions - The route's own `extensions`, if any\n * @param type - The already-resolved product kind for this route, if any\n * @param declaration - Product-level declaration from the middleware config\n * @param warn - Sink for anything that will not ship\n * @returns The extensions to put on the route, or undefined to leave them alone\n */\nfunction resolveProductExtensions(\n routeExtensions: RouteConfig[\"extensions\"],\n type: WeftProductType | undefined,\n declaration: WeftProductDeclaration,\n warn: Warn,\n): RouteConfig[\"extensions\"] | undefined {\n const productId = resolveOpaqueString(\n \"productId\",\n declaration.productId,\n warn,\n );\n const manifestHash = resolveOpaqueString(\n \"manifestHash\",\n declaration.manifestHash,\n warn,\n );\n\n const info = {\n ...(type !== undefined && { kind: type }),\n ...(productId !== undefined && { product_id: productId }),\n ...(manifestHash !== undefined && { manifest_hash: manifestHash }),\n };\n\n if (Object.keys(info).length === 0) {\n return undefined;\n }\n\n if (routeExtensions !== undefined) {\n if (\n typeof routeExtensions !== \"object\" ||\n routeExtensions === null ||\n Array.isArray(routeExtensions)\n ) {\n // Pass-through contract: what a seller puts in an upstream RouteConfig\n // field is between them and @x402/core, so the junk value stays on the\n // route untouched — the warning must not claim otherwise.\n warn(\n `route extensions ${show(routeExtensions)} are ${typeName(routeExtensions)}, ` +\n `not an object; leaving them untouched and skipping the ` +\n `${WEFT_PRODUCT_EXTENSION_KEY} declaration for this route`,\n );\n return undefined;\n }\n if (WEFT_PRODUCT_EXTENSION_KEY in routeExtensions) {\n return undefined;\n }\n }\n\n return {\n ...routeExtensions,\n [WEFT_PRODUCT_EXTENSION_KEY]: { info, schema: WEFT_PRODUCT_INFO_SCHEMA },\n };\n}\n\n/**\n * Apply product-level identity to a single route.\n *\n * A per-route value always wins over the product-level default. The route's\n * own `type` is consumed here and never forwarded: `RouteConfig` upstream has\n * no such field, and the value's only destination is the reserved tag and the\n * `weft.product` extension's `kind`.\n *\n * @param route - The seller's route configuration\n * @param identity - Product-level declaration from the middleware config\n * @param warn - Sink for anything that will not ship as declared\n * @returns A new route config; the input is never mutated\n */\nfunction applyToRoute(\n route: WeftRouteConfig,\n identity: WeftProductDeclaration,\n warn: Warn,\n): RouteConfig {\n if (typeof route !== \"object\" || route === null) {\n warn(\n `ignoring route ${show(route)}: expected a route config object, got ` +\n `${typeName(route)}`,\n );\n return route;\n }\n\n // Every identity field is destructured *out* of the route rather than merged\n // over: a value this function drops has to leave the route entirely. Spread\n // the route and add the survivors back, and a dropped value rides through on\n // the original object — defeating the drop precisely when it matters, which\n // is when the seller's own value is the one the protocol cannot carry.\n const {\n type: declaredType,\n serviceName: declaredServiceName,\n tags: declaredTags,\n iconUrl: declaredIconUrl,\n ...rest\n } = route;\n\n const type =\n resolveType(declaredType, \"route type\", warn) ??\n resolveType(identity.type, \"type\", warn);\n const serviceName = resolveServiceName(\n declaredServiceName,\n identity.name,\n warn,\n );\n const iconUrl = resolveIconUrl(declaredIconUrl, identity.iconUrl, warn);\n const tags = resolveTags(declaredTags, identity.tags, type, warn);\n const extensions = resolveProductExtensions(\n rest.extensions,\n type,\n identity,\n warn,\n );\n\n return {\n ...rest,\n ...(serviceName !== undefined && { serviceName }),\n ...(tags !== undefined && { tags }),\n ...(iconUrl !== undefined && { iconUrl }),\n ...(extensions !== undefined && { extensions }),\n };\n}\n\n/**\n * Whether any product-level field was actually declared.\n *\n * @param identity - Product-level declaration from the middleware config\n * @returns True when at least one field is set to something other than null\n */\nfunction hasProductIdentity(identity: WeftProductDeclaration): boolean {\n return (\n isDeclared(identity.name) ||\n isDeclared(identity.type) ||\n isDeclared(identity.tags) ||\n isDeclared(identity.iconUrl) ||\n isDeclared(identity.productId) ||\n isDeclared(identity.manifestHash)\n );\n}\n\n/**\n * Whether any route declares a Weft-specific field of its own.\n *\n * Only `type` counts: `serviceName`, `tags` and `iconUrl` are upstream fields\n * a seller could already set before this identity existed, and a config that\n * uses no Weft identity anywhere must still pass through untouched.\n *\n * @param routes - Route configuration passed by the caller\n * @returns True when at least one route declares `type`\n */\nfunction hasRouteIdentity(routes: WeftRoutesConfig): boolean {\n if (isSingleRoute(routes)) {\n return isDeclared(routes.type);\n }\n return Object.values(routes).some((route) => isDeclared(route?.type));\n}\n\n/**\n * Resolve the product-level identity to exactly what the wire will carry.\n *\n * The construction-time facilitator handshake declares the product too, and a\n * dashboard fed from both sources must never see two different products. So\n * the handshake reuses the resolvers the 402 challenge goes through — same\n * clamping, same drops — with one difference: the product type is returned as\n * its own field rather than folded into `tags`, because the handshake payload\n * has a field for it and the challenge does not.\n *\n * Silent by design: `applyProductIdentity` already warns about these same\n * values at construction time, and one warning per problem is enough.\n *\n * @param identity - Product-level identity from the middleware config\n * @returns The identity as it ships, or an empty object when nothing survives\n */\nexport function sanitizeProductIdentity(\n identity: WeftProductIdentity,\n): WeftProductIdentity {\n const silent: Warn = () => undefined;\n\n const type = resolveType(identity.type, \"type\", silent);\n const name = resolveServiceName(undefined, identity.name, silent);\n const iconUrl = resolveIconUrl(undefined, identity.iconUrl, silent);\n const tags = resolveTags(undefined, identity.tags, type, silent)?.filter(\n (tag) => !isReservedTypeTag(tag),\n );\n\n return {\n ...(name !== undefined && { name }),\n ...(type !== undefined && { type }),\n ...(tags !== undefined && tags.length > 0 && { tags }),\n ...(iconUrl !== undefined && { iconUrl }),\n };\n}\n\n/**\n * Merge product-level identity into every protected route.\n *\n * A per-route value always wins over the product-level default, so a seller\n * who names one route individually keeps that name. Fields nobody declared\n * stay absent from the 402 challenge rather than being sent empty.\n *\n * Every value this produces is inside the bounds `ResourceInfoSchema` declares,\n * so the challenge the middleware emits parses for any buyer that validates.\n * Values that cannot be made to fit are clamped or dropped, each with one\n * `[weft]` line at construction time.\n *\n * A config that declares no Weft identity at all — neither on the middleware\n * nor on a route — is returned by reference, exactly as the caller wrote it.\n * That is the pre-identity behaviour, kept deliberately: with nothing of ours\n * on the routes, what the seller puts in a `RouteConfig` is between them and\n * `@x402/core`.\n *\n * @param routes - Route configuration passed by the caller\n * @param identity - Product-level declaration from the middleware config\n * @returns Route configuration with identity applied; the input is never mutated\n */\nexport function applyProductIdentity(\n routes: WeftRoutesConfig,\n identity: WeftProductDeclaration,\n): RoutesConfig {\n if (typeof routes !== \"object\" || routes === null) {\n return routes;\n }\n\n if (!hasProductIdentity(identity) && !hasRouteIdentity(routes)) {\n return routes;\n }\n\n const warn = createWarn();\n\n if (isSingleRoute(routes)) {\n return applyToRoute(routes, identity, warn);\n }\n\n return Object.fromEntries(\n Object.entries(routes).map(([pattern, route]) => [\n pattern,\n applyToRoute(route, identity, warn),\n ]),\n );\n}\n","import { version as SDK_VERSION } from \"../../../package.json\";\nimport {\n createWarn,\n resolveDimensions,\n sanitizeProductIdentity,\n WeftProductDeclaration,\n} from \"./product\";\n\n/**\n * Header that carries the seller's declared product identity on the\n * construction-time `/supported` call.\n *\n * The value is base64url-encoded JSON of\n * `{name, type, tags, icon_url, dimensions}`. The first four are exactly the\n * identity the 402 challenge will carry, so a dashboard fed from the\n * handshake and one fed from settlements agree.\n *\n * `dimensions` is the exception, and travels here *only*. It never touches\n * the challenge, because its whole job is to be the one statement about a\n * payment's metadata that a buyer never had a chance to author: this call is\n * authenticated by the seller's API key, so a field named here is a field the\n * seller vouched for. That is what lets revenue be summed by it.\n *\n * Fields nobody declared are absent from the JSON, and the header itself is\n * absent when nothing was declared at all.\n */\nexport const WEFT_DECLARED_HEADER = \"X-Weft-Declared\";\n\n/** The middleware adapters a handshake can identify itself as. */\nexport type WeftAdapterName = \"express\" | \"hono\";\n\n/**\n * Encode a string as unpadded base64url without assuming a Node runtime.\n *\n * The Hono middleware runs on edge runtimes where `Buffer` may not exist;\n * `TextEncoder` and `btoa` exist everywhere this package supports.\n *\n * @param value - The string to encode\n * @returns The base64url encoding of the string's UTF-8 bytes\n */\nfunction base64UrlEncode(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * Build the `X-Weft-Declared` value for a product declaration, if any\n * survives.\n *\n * The identity half goes through `sanitizeProductIdentity`, which is silent\n * because `applyProductIdentity` has already warned about the same values.\n * `dimensions` has no such second path — this is the only place it is read —\n * so it is resolved with a warning sink of its own, at boot, once.\n *\n * @param declaration - Product-level declaration from the middleware config\n * @returns The base64url payload, or undefined when nothing was declared\n */\nfunction declaredIdentityValue(\n declaration: WeftProductDeclaration,\n): string | undefined {\n const declared = sanitizeProductIdentity(declaration);\n const dimensions = resolveDimensions(declaration.dimensions, createWarn());\n\n const payload = {\n ...(declared.name !== undefined && { name: declared.name }),\n ...(declared.type !== undefined && { type: declared.type }),\n ...(declared.tags !== undefined && { tags: declared.tags }),\n ...(declared.iconUrl !== undefined && { icon_url: declared.iconUrl }),\n ...(dimensions !== undefined && { dimensions }),\n };\n\n if (Object.keys(payload).length === 0) {\n return undefined;\n }\n return base64UrlEncode(JSON.stringify(payload));\n}\n\n/**\n * Characters that may appear in the `Authorization` value the handshake sends.\n *\n * Printable ASCII excluding space — no real credential contains anything\n * else. The bound exists for log hygiene, not pedantry: a value outside it\n * survives to `fetch`, where undici rejects the header with a `TypeError`\n * that quotes the **entire value**, and upstream `initialize()` prints that\n * error via its own `console.warn` — a live key in the seller's boot output,\n * through a path this SDK cannot intercept. So anything that could trip that\n * error is refused here, before it can become a header.\n */\nconst HEADER_SAFE = /^[\\x21-\\x7e]+$/;\n\n/**\n * Read a declared API key, refusing anything that cannot be a credential.\n *\n * The key's value is never logged — not by the warnings here, which name the\n * field and never quote it, and not by anything downstream, because a value\n * that would make the HTTP layer throw (and echo the key back) never leaves\n * this function.\n *\n * @param apiKey - The declared API key, usually from env at runtime\n * @returns The trimmed key, or undefined when absent or unusable\n */\nfunction resolveApiKey(apiKey: unknown): string | undefined {\n if (apiKey === undefined || apiKey === null) {\n return undefined;\n }\n if (typeof apiKey !== \"string\") {\n console.warn(\n `[weft] ignoring apiKey: expected a string, got ${typeof apiKey}`,\n );\n return undefined;\n }\n const trimmed = apiKey.trim();\n if (trimmed === \"\") {\n console.warn(\"[weft] ignoring empty apiKey\");\n return undefined;\n }\n if (!HEADER_SAFE.test(trimmed)) {\n console.warn(\n \"[weft] ignoring apiKey: it contains whitespace or non-printable \" +\n \"characters that cannot travel in an HTTP header\",\n );\n return undefined;\n }\n return trimmed;\n}\n\n/**\n * Header the Weft facilitator reads the seller's API key from on `/settle`\n * and `/verify`.\n *\n * The facilitator's `/settle` handler validates this header and returns 401\n * without it, so a seller who sets `apiKey` and nothing else must have it\n * here or every settlement — the step that credits their wallet — fails.\n * `/verify` does not require the key, but the facilitator reads it when\n * present and stamps the verification event with the key's digest; the SDK\n * sends it there too so the seller's funnel attributes verification attempts\n * instead of counting settlements against zero. `/supported` carries the same\n * key as a bearer for the handshake, so one key travels under two header names\n * by the facilitator's own design, not the SDK's whim.\n */\nexport const WEFT_API_KEY_HEADER = \"X-API-Key\";\n\n/**\n * Auth headers the SDK derives from `apiKey`, keyed by the facilitator path\n * each belongs to — the shape `@x402/core`'s `createAuthHeaders` expects.\n *\n * `supported` always carries at least a `User-Agent`. `settle` and `verify`\n * are present only when a usable key was configured — they carry the same\n * `X-API-Key`, so the facilitator credits the wallet on `/settle` and\n * attributes the verification funnel on `/verify` from one credential. An\n * empty `X-API-Key` is a failed settlement dressed up as a configured one, so\n * neither is present without a usable key.\n */\nexport interface WeftFacilitatorAuthHeaders {\n supported: Record<string, string>;\n settle?: Record<string, string>;\n verify?: Record<string, string>;\n}\n\n/**\n * Build the auth headers the SDK adds to the facilitator calls it drives.\n *\n * Total by design: this runs in a payment server's boot path, so no input —\n * junk key, junk identity — may ever make it throw. Anything unusable is\n * dropped with a warning and the calls go out without it.\n *\n * The key is validated once here and reused across every path, so a\n * malformed key warns a single time and reaches none of the `/supported`\n * bearer, the `/settle` `X-API-Key`, or the `/verify` `X-API-Key`.\n *\n * @param adapter - Which middleware adapter is calling home\n * @param apiKey - The seller's Weft API key, when configured\n * @param declaration - Product-level declaration from the middleware config\n * @returns Per-path auth headers for the facilitator calls\n */\nexport function buildFacilitatorAuthHeaders(\n adapter: WeftAdapterName,\n apiKey: unknown,\n declaration: WeftProductDeclaration,\n): WeftFacilitatorAuthHeaders {\n const key = resolveApiKey(apiKey);\n\n const supported: Record<string, string> = {\n \"User-Agent\": `weft-sdk-${adapter}/${SDK_VERSION}`,\n };\n if (key !== undefined) {\n supported[\"Authorization\"] = `Bearer ${key}`;\n }\n\n const declared = declaredIdentityValue(declaration);\n if (declared !== undefined) {\n supported[WEFT_DECLARED_HEADER] = declared;\n }\n\n const settle = key !== undefined ? { [WEFT_API_KEY_HEADER]: key } : undefined;\n const verify = key !== undefined ? { [WEFT_API_KEY_HEADER]: key } : undefined;\n\n return {\n supported,\n ...(settle !== undefined && { settle }),\n ...(verify !== undefined && { verify }),\n };\n}\n","import type { HTTPRequestContext, x402ResourceServer } from \"@x402/core/server\";\nimport type {\n PaymentRequiredContext,\n ResourceServerExtension,\n} from \"@x402/core/types\";\nimport { createWarn, type Warn } from \"./product\";\nimport type { WeftRouteConfig, WeftRoutesConfig } from \"./product\";\n\n/**\n * A route extension whose value is computed per request.\n *\n * Declared in place of a static value under a key of a route's `extensions`,\n * and evaluated at the same point as the `price` callback — while the 402\n * challenge is being built, with the same {@link HTTPRequestContext}. The\n * resolved value ships on the challenge, the buyer's client echoes it onto the\n * payment payload, and the facilitator relays it onto the settlement event, so\n * a seller who prices from the request body can also say what that body asked\n * for:\n *\n * ```ts\n * {\n * accepts: [{ scheme, network, payTo, price: quote }],\n * extensions: {\n * [WEFT_REQUEST_EXTENSION_KEY]: async (context) => {\n * const { model, max_tokens } = (await context.adapter.getBody()) as Body;\n * return { model, max_tokens };\n * },\n * },\n * }\n * ```\n *\n * {@link WEFT_REQUEST_EXTENSION_KEY} is the key to reach for. Under it the SDK\n * owns the envelope: the callback returns the `info` payload alone and the\n * published {@link WEFT_REQUEST_INFO_SCHEMA} is stamped beside it, exactly as\n * `weft.product` is assembled from declared fields. Under any other key the\n * resolved value ships verbatim, envelope and all — the escape hatch for a\n * seller who needs their own namespace on the wire.\n *\n * Two rules the callback has to hold to.\n *\n * **It must be deterministic for one request.** The challenge is built twice —\n * once for the unpaid request, once for the buyer's paid retry — and upstream\n * rejects the payment with `extension_echo_mismatch` when what the buyer\n * echoes no longer matches what the retry advertises. Derive the value from\n * the request; never from a clock, a counter or a random source.\n *\n * **It is display-only.** By the time the value reaches a consumer it is\n * unauthenticated buyer input, exactly like every other echoed extension.\n * Attribution stays keyed on the authenticated API key that settled the\n * payment, never on anything in here.\n *\n * The value travels as JSON and is advertised as JSON round-trips it, so a\n * `NaN` arrives as `null` and a function-valued field does not arrive at all.\n * Return plain JSON data and the question never comes up.\n */\nexport type WeftDynamicExtension = (\n context: HTTPRequestContext,\n) => unknown | Promise<unknown>;\n\n/**\n * Extension key for the seller's per-request context.\n *\n * The one *named* key this mechanism ships, and the one to use unless a\n * seller needs their own namespace on the wire. x402 extensions are named\n * capabilities with published contracts — discovery, receipts, gas sponsoring\n * — registered and reviewed rather than invented per seller. A key that any\n * seller may invent is a metadata channel wearing an extension's clothes, so\n * the SDK publishes one key with one contract and leaves the free-form form\n * as the deliberate exception.\n *\n * Sits beside {@link WEFT_PRODUCT_EXTENSION_KEY}, and divides cleanly from it:\n * `weft.product` says what is being sold and is fixed at boot; `weft.request`\n * says what this one call asked for and is resolved per request.\n */\nexport const WEFT_REQUEST_EXTENSION_KEY = \"weft.request\";\n\n/**\n * JSON Schema (Draft 2020-12) for the `weft.request` extension's `info`.\n *\n * Ships verbatim as the extension's `schema` member. Deliberately open where\n * `WEFT_PRODUCT_INFO_SCHEMA` is closed: what a request asked for is the\n * seller's vocabulary — `{model, max_tokens}` for one rail, `{pages}` for\n * another — and no schema Weft could author would fit them all.\n *\n * The contract it publishes is therefore not a field list but a posture: this\n * key holds seller-authored, display-only context for one request, and a\n * consumer must key nothing on it. `additionalProperties: true` states that\n * openness rather than leaving it to be inferred from an absent constraint.\n */\nexport const WEFT_REQUEST_INFO_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"Weft per-request context\",\n description:\n \"Seller-authored context for one paid request, for display only. \" +\n \"Unauthenticated buyer input by the time it is read; key nothing on it.\",\n type: \"object\",\n additionalProperties: true,\n} as const;\n\n/**\n * Largest serialized extensions object, in bytes, the SDK will put on a\n * challenge.\n *\n * Mirrors the facilitator's own `MAX_EXTENSIONS_BYTES` relay cap, and is\n * measured the same way: on the whole object, key names included. The\n * facilitator omits *every* extension when the object is over — `weft.product`\n * with it — so a resolved value that would take the object past the cap is\n * dropped here, on its own key, where the rest of the declaration survives.\n *\n * Keep these blobs small. They describe a request; they are not a place to\n * store one.\n */\nexport const MAX_EXTENSION_BYTES = 16 * 1024;\n\n/**\n * Recover the HTTP request from the enrichment context.\n *\n * `transportContext` is `unknown` upstream because the resource server is not\n * HTTP-only; the HTTP path always passes `{request}`.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @returns The request context, or undefined off the HTTP transport\n */\nfunction requestOf(\n context: PaymentRequiredContext,\n): HTTPRequestContext | undefined {\n const transport = context.transportContext as\n { request?: HTTPRequestContext } | undefined;\n return transport?.request;\n}\n\n/**\n * Drop a key that resolved to nothing shippable.\n *\n * Returning `undefined` from the hook means \"no change\", which would leave the\n * callback *itself* on the challenge — `JSON.stringify` drops a function-valued\n * key, so nothing malformed reaches the wire either way, but the key is removed\n * here so the in-process challenge says the same thing the buyer sees.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @param key - The extension key to remove\n * @returns Always undefined, so the hook makes no assignment of its own\n */\nfunction dropKey(context: PaymentRequiredContext, key: string): undefined {\n delete context.paymentRequiredResponse.extensions?.[key];\n return undefined;\n}\n\n/**\n * Serialize a value to JSON, or undefined when JSON cannot carry it.\n *\n * @param value - The value to serialize\n * @returns The JSON text, or undefined for a circular, BigInt or unserializable value\n */\nfunction toJson(value: unknown): string | undefined {\n try {\n return JSON.stringify(value);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Byte length of a string as UTF-8 — what the facilitator's cap counts.\n *\n * @param text - The serialized JSON\n * @returns The length in bytes\n */\nfunction byteLength(text: string): number {\n return new TextEncoder().encode(text).length;\n}\n\n/**\n * Size of the whole extensions object once this key holds this value.\n *\n * The facilitator's cap is on the *serialized map*, not on one value: a blob\n * that fits on its own can still push the object past the cap once its key\n * name and `weft.product` are counted, and the facilitator then omits every\n * extension rather than the offender. So the projection is what gets measured.\n *\n * Still an approximation in one direction: keys resolved later in the same\n * challenge are unresolved callbacks here, which serialize to nothing. Each\n * one measures against everything already accepted, so the estimate only\n * improves as the map fills.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @param key - The extension key about to be written\n * @param value - The wire value that key would hold\n * @returns The projected size in bytes, or undefined when the map will not serialize\n */\nfunction projectedBytes(\n context: PaymentRequiredContext,\n key: string,\n value: unknown,\n): number | undefined {\n const projected = {\n ...context.paymentRequiredResponse.extensions,\n [key]: value,\n };\n const json = toJson(projected);\n return json === undefined ? undefined : byteLength(json);\n}\n\n/**\n * Build the resource-server extension that resolves one dynamic key.\n *\n * Registered once per key, not per route: the route's own declaration arrives\n * as the hook's `declaration` argument, so two routes may declare the same key\n * with different callbacks. A route that declares the key statically is left\n * alone — only a function is resolved.\n *\n * Nothing here throws. A callback that fails costs the seller the blob, never\n * the payment: the key is dropped and the challenge ships without it.\n *\n * @param key - The extension key this hook resolves\n * @param warn - Sink for anything that will not ship\n * @returns An extension to register on the resource server\n */\nfunction dynamicExtension(key: string, warn: Warn): ResourceServerExtension {\n return {\n key,\n async enrichPaymentRequiredResponse(declaration, context) {\n if (typeof declaration !== \"function\") {\n return undefined;\n }\n\n const request = requestOf(context);\n if (!request) {\n warn(\n `extensions[${key}] is a callback but no HTTP request context ` +\n `reached it; dropping the key from the challenge`,\n `${key}:no-request`,\n );\n return dropKey(context, key);\n }\n\n let resolved: unknown;\n try {\n resolved = await (declaration as WeftDynamicExtension)(request);\n } catch (error) {\n warn(\n `extensions[${key}] callback failed; dropping the key from the ` +\n `challenge: ` +\n (error instanceof Error ? error.message : String(error)),\n `${key}:threw`,\n );\n return dropKey(context, key);\n }\n\n // A callback that returns nothing is opting out for this request — a\n // route that only stamps some requests should not have to warn about\n // the rest.\n if (resolved === undefined || resolved === null) {\n return dropKey(context, key);\n }\n\n const json = toJson(resolved);\n if (json === undefined) {\n warn(\n `extensions[${key}] callback returned a value JSON cannot carry (a ` +\n `function, a circular reference, a BigInt or similar); dropping ` +\n `the key from the challenge`,\n `${key}:unserializable`,\n );\n return dropKey(context, key);\n }\n\n // Advertise the round trip, never the original. `JSON.stringify`\n // normalizes — NaN and Infinity become null, functions and symbols\n // vanish — and the paid retry's echo check compares what this hook\n // advertised against the buyer's JSON-decoded copy. Advertising the\n // un-normalized original makes those two disagree and costs the seller\n // the payment, which is the one thing this path must never do.\n const wire: unknown = JSON.parse(json);\n\n // Checked after the round trip, so a `toJSON` that returns something\n // else is caught alongside a callback that returned it directly.\n if (typeof wire !== \"object\" || wire === null || Array.isArray(wire)) {\n warn(\n `extensions[${key}] callback returned ${Array.isArray(wire) ? \"an array\" : `a ${typeof wire}`}; ` +\n `the x402 extensions channel carries objects, so the key is ` +\n `dropped from the challenge`,\n `${key}:not-an-object`,\n );\n return dropKey(context, key);\n }\n\n // The named key owns its envelope: the callback returns `info` alone\n // and the published schema is stamped beside it, the same assembly\n // `weft.product` goes through. Wrapped before measuring, so the cap\n // counts what actually ships. Any other key ships the resolved value\n // exactly as the seller built it.\n const value =\n key === WEFT_REQUEST_EXTENSION_KEY\n ? { info: wire, schema: WEFT_REQUEST_INFO_SCHEMA }\n : wire;\n\n const bytes = projectedBytes(context, key, value) ?? byteLength(json);\n if (bytes > MAX_EXTENSION_BYTES) {\n warn(\n `extensions[${key}] takes the challenge's extensions to ${bytes} ` +\n `bytes, over the ${MAX_EXTENSION_BYTES}-byte facilitator relay ` +\n `cap; dropping the key so the rest of the declaration still ` +\n `reaches settlement`,\n `${key}:over-cap`,\n );\n return dropKey(context, key);\n }\n\n return value;\n },\n };\n}\n\n/**\n * The route configs in a `RoutesConfig`, in either of its two shapes.\n *\n * @param routes - Route configuration passed by the caller\n * @returns Every route config, ignoring anything that is not one\n */\nfunction routeConfigs(routes: WeftRoutesConfig): WeftRouteConfig[] {\n if (typeof routes !== \"object\" || routes === null) {\n return [];\n }\n const configs = \"accepts\" in routes ? [routes] : Object.values(routes);\n return configs.filter(\n (config): config is WeftRouteConfig =>\n typeof config === \"object\" && config !== null,\n );\n}\n\n/**\n * Every extension key declared as a callback by at least one route.\n *\n * @param routes - Route configuration passed by the caller\n * @returns The distinct keys needing per-request resolution\n */\nfunction dynamicExtensionKeys(routes: WeftRoutesConfig): string[] {\n const keys = new Set<string>();\n for (const config of routeConfigs(routes)) {\n const extensions = config.extensions;\n if (typeof extensions !== \"object\" || extensions === null) {\n continue;\n }\n for (const [key, value] of Object.entries(extensions)) {\n if (typeof value === \"function\") {\n keys.add(key);\n }\n }\n }\n return [...keys];\n}\n\n/**\n * Teach a resource server to resolve the routes' {@link WeftDynamicExtension}\n * callbacks.\n *\n * Upstream reads `routeConfig.extensions` straight off the shared, long-lived\n * route config, so a per-request value cannot be written there without racing\n * every concurrent request. `registerExtension` is the path that *is* request\n * scoped: the enrichment hook runs while the challenge for one request is\n * being built, and its return value replaces that request's copy of the key —\n * which is the same object the verify and settle steps go on to see.\n *\n * A config with no callbacks registers nothing at all.\n *\n * @param server - The resource server the middleware is building on\n * @param routes - Route configuration passed by the caller\n */\nexport function registerDynamicExtensions(\n server: x402ResourceServer,\n routes: WeftRoutesConfig,\n): void {\n const keys = dynamicExtensionKeys(routes);\n if (keys.length === 0) {\n return;\n }\n\n const warn = createWarn();\n\n // The peer range is `^2.0.0` and per-key enrichment arrived mid-2.x. On an\n // older build the callback stays a function, which JSON drops: the seller\n // loses the blob, not the payment — but silently, so say it once at boot.\n if (typeof server.registerExtension !== \"function\") {\n warn(\n `this @x402/core build has no registerExtension, so per-request route ` +\n `extensions (${keys.join(\", \")}) cannot be resolved and will not ship`,\n );\n return;\n }\n\n for (const key of keys) {\n server.registerExtension(dynamicExtension(key, warn));\n }\n}\n","import type {\n CompletedSettlement,\n HTTPRequestContext,\n PaymentCancellationDispatcher,\n x402ResourceServer,\n} from \"@x402/core/server\";\nimport { decodePaymentSignatureHeader } from \"@x402/core/http\";\nimport { validatePaymentPayload } from \"@x402/core/schemas\";\nimport type { PaymentPayload, PaymentRequirements } from \"@x402/core/types\";\n\n/** A structurally valid, but not cryptographically verified, v2 payment. */\nexport interface PaymentResumeCandidate {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n}\n\n/** Verified payment inputs restored from durable application storage. */\nexport interface VerifiedPaymentResume {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n declaredExtensions?: Record<string, unknown>;\n /** Restore this receipt when Core settled before the original handler. */\n beforeHandlerSettlement?: CompletedSettlement;\n /** Restore Core's cancellation state for a before-handler settlement. */\n cancellationDispatcher?: PaymentCancellationDispatcher;\n}\n\n/**\n * Restore a previously verified payment for settlement replay.\n *\n * This callback is a trust boundary. The caller must durably bind its result to\n * the exact signed payment payload and request fingerprint. The SDK does not\n * authenticate or validate callback output before settlement.\n */\nexport type ResumeVerifiedPayment = (\n context: HTTPRequestContext,\n candidate: PaymentResumeCandidate,\n) =>\n | VerifiedPaymentResume\n | undefined\n | Promise<VerifiedPaymentResume | undefined>;\n\n/**\n * Decode the generic v2 envelope before it crosses the application replay\n * trust boundary. Scheme validation and signature verification stay with Core\n * and the registered scheme implementation.\n */\nexport function paymentResumeCandidate(\n context: HTTPRequestContext,\n): PaymentResumeCandidate | undefined {\n if (!context.paymentHeader) return undefined;\n\n try {\n const paymentPayload = decodePaymentSignatureHeader(context.paymentHeader);\n validatePaymentPayload(paymentPayload);\n if (paymentPayload.x402Version !== 2) return undefined;\n\n return {\n paymentPayload,\n paymentRequirements: paymentPayload.accepted,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function resumePaymentResult(\n resourceServer: x402ResourceServer,\n resumed: VerifiedPaymentResume,\n context: HTTPRequestContext,\n) {\n return {\n type: \"payment-verified\" as const,\n paymentPayload: resumed.paymentPayload,\n paymentRequirements: resumed.paymentRequirements,\n declaredExtensions: resumed.declaredExtensions,\n beforeHandlerSettlement: resumed.beforeHandlerSettlement,\n cancellationDispatcher:\n resumed.cancellationDispatcher ??\n resourceServer.createPaymentCancellationDispatcher(\n resumed.paymentPayload,\n resumed.paymentRequirements,\n resumed.declaredExtensions,\n { request: context },\n resumed.beforeHandlerSettlement ? [\"before-handler\"] : [],\n ),\n };\n}\n","import { x402HTTPResourceServer } from \"@x402/core/server\";\nimport { decodePaymentResponseHeader } from \"@x402/core/http\";\nimport { FACILITATOR_UNAVAILABLE_ERROR } from \"../client\";\n\nconst CORE_FACILITATOR_UNAVAILABLE =\n /^Facilitator settle failed \\(503\\):(?: |$)/;\n\n/**\n * The Weft client marks structured 503s before Core drops their status. Match\n * Core's exact prefix only as a fallback for unstructured 503 responses.\n */\nexport function isFacilitatorUnavailable(errorReason?: string): boolean {\n return (\n errorReason === FACILITATOR_UNAVAILABLE_ERROR ||\n CORE_FACILITATOR_UNAVAILABLE.test(errorReason ?? \"\")\n );\n}\n\ninterface CoreResponseInstructions {\n body?: unknown;\n headers: Record<string, string | string[]>;\n}\n\nfunction responseHeader(\n headers: CoreResponseInstructions[\"headers\"],\n name: string,\n): string | undefined {\n const value = Object.entries(headers).find(\n ([key]) => key.toLowerCase() === name,\n )?.[1];\n return Array.isArray(value) ? value[0] : value;\n}\n\nexport function isFacilitatorUnavailableResponse(\n response: CoreResponseInstructions,\n): boolean {\n if (typeof response.body === \"object\" && response.body !== null) {\n for (const field of [\"errorReason\", \"error\"]) {\n if (\n field in response.body &&\n typeof response.body[field as keyof typeof response.body] ===\n \"string\" &&\n isFacilitatorUnavailable(\n response.body[field as keyof typeof response.body] as string,\n )\n ) {\n return true;\n }\n }\n }\n\n const paymentResponse = responseHeader(response.headers, \"payment-response\");\n if (!paymentResponse) return false;\n try {\n return isFacilitatorUnavailable(\n decodePaymentResponseHeader(paymentResponse).errorReason,\n );\n } catch {\n return false;\n }\n}\n\nexport function isJsonResponse(response: CoreResponseInstructions): boolean {\n const contentType = responseHeader(response.headers, \"content-type\");\n return /^(application\\/json|[^;]+\\+json)(?:;|$)/i.test(contentType ?? \"\");\n}\n\nexport function serializeResponseBody(\n response: CoreResponseInstructions,\n): BodyInit {\n if (isJsonResponse(response)) return JSON.stringify(response.body ?? {});\n if (\n response.body instanceof Blob ||\n response.body instanceof ArrayBuffer ||\n ArrayBuffer.isView(response.body)\n ) {\n return response.body as BodyInit;\n }\n return typeof response.body === \"string\"\n ? response.body\n : String(response.body ?? \"\");\n}\n\n/** Observe the seller method at both before-handler and after-handler settlement. */\nexport class WeftHTTPResourceServer extends x402HTTPResourceServer {\n override processSettlement(\n ...args: Parameters<x402HTTPResourceServer[\"processSettlement\"]>\n ) {\n const request = args[3]?.request;\n const method = request?.method ?? request?.adapter.getMethod();\n if (method) {\n const payload = { ...args[0], httpMethod: method.toUpperCase() };\n args[0] = payload;\n }\n return super.processSettlement(...args);\n }\n}\n","import {\n HTTPRequestContext,\n PaywallConfig,\n PaywallProvider,\n SETTLEMENT_OVERRIDES_HEADER,\n withPrivateCacheControl,\n x402ResourceServer,\n HTTPAdapter,\n} from \"@x402/core/server\";\nimport { SchemeNetworkServer, Network } from \"@x402/core/types\";\nimport { createFacilitatorClient, WeftFacilitatorConfig } from \"../client\";\nimport { buildFacilitatorAuthHeaders } from \"./handshake\";\nimport {\n applyProductIdentity,\n WeftProductDeclaration,\n WeftRoutesConfig,\n} from \"./product\";\nimport { registerDynamicExtensions } from \"./extensions\";\nimport {\n paymentResumeCandidate,\n resumePaymentResult,\n type ResumeVerifiedPayment,\n} from \"./replay\";\nimport {\n WeftHTTPResourceServer,\n isFacilitatorUnavailable,\n isFacilitatorUnavailableResponse,\n isJsonResponse,\n serializeResponseBody,\n} from \"./settlement\";\n\ninterface HonoRequest {\n method: string;\n path: string;\n url: string;\n header(name: string): string | undefined;\n query(): Record<string, string>;\n query(name: string): string | undefined;\n json(): Promise<unknown>;\n}\n\ninterface HonoContext {\n req: HonoRequest;\n res: Response | undefined;\n error?: Error;\n header(\n name: string,\n value: string | undefined,\n options?: { append?: boolean },\n ): void;\n html(body: string, status?: number): Response;\n json(body: unknown, status?: number): Response;\n}\n\nexport type HonoMiddleware = (\n c: HonoContext,\n next: () => Promise<void>,\n) => Promise<Response | void>;\n\n/**\n * Floor between background facilitator re-sync attempts.\n *\n * Without it, a sustained facilitator outage on a busy server couples retry\n * (and warn) volume to request rate: a refused connection settles in\n * milliseconds, so every protected request would launch a fresh `/supported`\n * call for the whole outage. One attempt per floor interval bounds both.\n */\nconst FACILITATOR_SYNC_RETRY_FLOOR_MS = 30_000;\n\nexport interface SchemeRegistration {\n network: Network;\n server: SchemeNetworkServer;\n}\n\n/**\n * Configuration for the Hono payment middleware.\n *\n * Extends {@link WeftProductDeclaration}, so `name`, `type`, `tags`,\n * `iconUrl`, `productId` and `manifestHash` are declared once here and\n * applied to every protected route.\n */\nexport interface WeftHonoMiddlewareConfig extends WeftProductDeclaration {\n /**\n * The seller's Weft API key.\n *\n * Authenticates the facilitator calls that need it: `X-API-Key` on\n * `/settle` — which the facilitator requires, or every settlement 401s —\n * and `Authorization: Bearer <key>` on the construction-time `/supported`\n * handshake, which is how the dashboard learns an SDK is deployed before\n * any payment. Optional, but a seller who omits it must supply their own\n * `facilitator.createAuthHeaders` or settlement fails.\n */\n apiKey?: string;\n facilitator?: WeftFacilitatorConfig;\n schemes?: SchemeRegistration[];\n paywallConfig?: PaywallConfig;\n paywall?: PaywallProvider;\n syncFacilitatorOnStart?: boolean;\n /** Restore durably bound verified inputs for settlement replay. */\n resumeVerifiedPayment?: ResumeVerifiedPayment;\n}\n\nclass HonoAdapter implements HTTPAdapter {\n constructor(private c: HonoContext) {}\n\n getHeader(name: string): string | undefined {\n return this.c.req.header(name);\n }\n\n getMethod(): string {\n return this.c.req.method;\n }\n\n getPath(): string {\n return this.c.req.path;\n }\n\n getUrl(): string {\n return this.c.req.url;\n }\n\n getAcceptHeader(): string {\n return this.c.req.header(\"Accept\") || \"\";\n }\n\n getUserAgent(): string {\n return this.c.req.header(\"User-Agent\") || \"\";\n }\n\n getQueryParams(): Record<string, string | string[]> {\n const query = this.c.req.query();\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(query)) {\n result[key] = value;\n }\n return result;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.c.req.query(name);\n }\n\n async getBody(): Promise<unknown> {\n try {\n return await this.c.req.json();\n } catch {\n return undefined;\n }\n }\n}\n\n/**\n * Flatten a `Headers` instance into the plain record `HTTPTransportContext`\n * expects. Header names are already lowercased by `Headers`; the settlement\n * override lookup in `@x402/core` compares case-insensitively either way.\n *\n * @param headers - Response headers set by the route handler, if any\n * @returns A plain record, or undefined when there is no response yet\n */\nfunction toHeaderRecord(\n headers: Headers | undefined,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n}\n\n/**\n * Rebuild a Fetch response with additional headers. Responses returned by\n * `fetch()` and `Response.redirect()` have immutable header guards.\n *\n * @param response - The route handler response\n * @param additions - Headers to add to the outgoing response\n * @returns The original response when there are no additions, otherwise a rebuilt response\n */\nfunction withResponseHeaders(\n response: Response,\n additions: Record<string, string> | undefined,\n): Response {\n if (\n (!additions || Object.keys(additions).length === 0) &&\n !response.headers.has(SETTLEMENT_OVERRIDES_HEADER)\n )\n return response;\n const headers = new Headers(response.headers);\n Object.entries(additions ?? {}).forEach(([key, value]) => {\n headers.set(key, value);\n });\n headers.delete(SETTLEMENT_OVERRIDES_HEADER);\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction withSuccessfulSettlementHeaders(\n response: Response,\n additions: Record<string, string>,\n): Response {\n const headers = new Headers(response.headers);\n Object.entries(additions).forEach(([key, value]) => {\n headers.set(key, value);\n });\n headers.delete(SETTLEMENT_OVERRIDES_HEADER);\n headers.set(\n \"cache-control\",\n withPrivateCacheControl(headers.get(\"cache-control\")),\n );\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction failureResponse(\n body: unknown,\n status: number,\n headers: Record<string, string | string[]>,\n): Response {\n const responseHeaders = new Headers();\n for (const [name, value] of Object.entries(headers)) {\n const values = Array.isArray(value) ? value : [value];\n for (const item of values) responseHeaders.append(name, item);\n }\n return new Response(serializeResponseBody({ body, headers }), {\n status,\n headers: responseHeaders,\n });\n}\n\nfunction facilitatorUnavailableResponse(): Response {\n return failureResponse({ error: \"facilitator_unavailable\" }, 503, {\n \"retry-after\": \"1\",\n \"cache-control\": withPrivateCacheControl(null),\n \"content-type\": \"application/json; charset=UTF-8\",\n });\n}\n\nfunction replaceContextResponse(c: HonoContext, response: Response): void {\n for (const name of [...(c.res?.headers.keys() ?? [])]) {\n c.header(name, undefined);\n }\n c.res = response;\n}\n\n/**\n * Create a Hono middleware that requires x402 payment for the given routes.\n *\n * Product identity declared on `config` (`name`, `type`, `tags`, `iconUrl`) is\n * merged into every route, so it travels on the 402 challenge's `resource` and\n * from there onto the buyer's payment payload and the settlement event.\n *\n * @param routes - Route configuration, either a path map or a single route;\n * each route may declare its own `type` to override the product's\n * @param config - Facilitator, scheme, paywall and product identity settings\n * @returns A Hono middleware function\n */\nexport function weftPaymentMiddlewareHono(\n routes: WeftRoutesConfig,\n config?: WeftHonoMiddlewareConfig,\n): HonoMiddleware {\n const facilitatorClient = createFacilitatorClient(\n config?.facilitator,\n buildFacilitatorAuthHeaders(\"hono\", config?.apiKey, config ?? {}),\n );\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerDynamicExtensions(resourceServer, routes);\n\n if (config?.schemes) {\n config.schemes.forEach(({ network, server: schemeServer }) => {\n resourceServer.register(network, schemeServer);\n });\n }\n\n const httpServer = new WeftHTTPResourceServer(\n resourceServer,\n applyProductIdentity(routes, config ?? {}),\n );\n\n if (config?.paywall) {\n httpServer.registerPaywallProvider(config.paywall);\n }\n\n // The construction-time facilitator sync doubles as the identity handshake,\n // so its failure modes are held to handshake rules: it must never crash the\n // process (a rejection with no handler attached would, under Node's default\n // unhandled-rejection policy) and must never brick the middleware. The\n // returned promise therefore cannot reject, and a failed sync is retried in\n // the background off later protected requests until one attempt succeeds.\n // A request the sync still cannot serve rejects into Hono's own onError.\n const syncOnStart = config?.syncFacilitatorOnStart ?? true;\n let facilitatorSynced = false;\n let syncInFlight: Promise<void> | null = null;\n let lastFailedSyncAt = 0;\n\n const syncFacilitator = (): Promise<void> => {\n syncInFlight ??= httpServer\n .initialize()\n .then(\n () => {\n facilitatorSynced = true;\n },\n (error: unknown) => {\n lastFailedSyncAt = Date.now();\n console.warn(\n \"[weft] facilitator sync failed; payment-protected routes \" +\n \"degrade until a later attempt succeeds: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n },\n )\n .finally(() => {\n syncInFlight = null;\n });\n return syncInFlight;\n };\n\n let bootSync: Promise<void> | null = syncOnStart ? syncFacilitator() : null;\n\n return async (c: HonoContext, next: () => Promise<void>) => {\n const adapter = new HonoAdapter(c);\n const context: HTTPRequestContext = {\n adapter,\n path: c.req.path,\n method: c.req.method,\n paymentHeader:\n adapter.getHeader(\"payment-signature\") ||\n adapter.getHeader(\"x-payment\"),\n };\n\n if (!httpServer.requiresPayment(context)) {\n return next();\n }\n\n if (bootSync) {\n // The pre-existing first-request barrier: with a healthy facilitator\n // this resolves once and never runs again. It cannot throw.\n await bootSync;\n bootSync = null;\n }\n if (\n syncOnStart &&\n !facilitatorSynced &&\n Date.now() - lastFailedSyncAt >= FACILITATOR_SYNC_RETRY_FLOOR_MS\n ) {\n // Heal a failed boot sync without delaying anyone: the retry is kicked\n // fire-and-forget (one in flight at most, one attempt per floor\n // interval) and this request proceeds.\n void syncFacilitator();\n }\n\n const resumeCandidate = paymentResumeCandidate(context);\n const resumedPayment = resumeCandidate\n ? await config?.resumeVerifiedPayment?.(context, resumeCandidate)\n : undefined;\n const result = resumedPayment\n ? resumePaymentResult(resourceServer, resumedPayment, context)\n : await httpServer.processHTTPRequest(context, config?.paywallConfig);\n\n switch (result.type) {\n case \"no-payment-required\":\n return next();\n\n case \"payment-error\": {\n const { response } = result;\n if (isFacilitatorUnavailableResponse(response)) {\n return facilitatorUnavailableResponse();\n }\n if (!response.isHtml && !isJsonResponse(response)) {\n return failureResponse(\n response.body,\n response.status,\n response.headers,\n );\n }\n Object.entries(response.headers).forEach(([key, value]) => {\n c.header(key, value as string);\n });\n if (response.isHtml) {\n return c.html(response.body as string, response.status as 402);\n }\n return c.json(response.body || {}, response.status as 402);\n }\n\n case \"payment-verified\": {\n const {\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n cancellationDispatcher,\n beforeHandlerSettlement,\n } = result;\n\n const propagateHandlerError = async (\n error: unknown,\n ): Promise<never> => {\n replaceContextResponse(c, new Response());\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_threw\",\n error,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n );\n Object.entries(headers ?? {}).forEach(([key, value]) => {\n c.header(key, value);\n });\n throw error;\n };\n\n const originalHeader = c.header;\n const handlerHeaders = new Set<string>();\n const errorHeaders = new Set<string>();\n c.header = (name, value, options) => {\n (c.error ? errorHeaders : handlerHeaders).add(name.toLowerCase());\n originalHeader.call(c, name, value, options);\n };\n try {\n await next();\n } catch (error) {\n c.header = originalHeader;\n await propagateHandlerError(error);\n }\n c.header = originalHeader;\n if (c.error) {\n const res = c.res ?? new Response();\n const responseHeaders = new Headers(res.headers);\n for (const name of handlerHeaders) {\n if (!errorHeaders.has(name)) responseHeaders.delete(name);\n }\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_threw\",\n error: c.error,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n responseHeaders.get(\"cache-control\"),\n );\n const sanitizedResponse = new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers: responseHeaders,\n });\n replaceContextResponse(\n c,\n withResponseHeaders(sanitizedResponse, headers),\n );\n return;\n }\n\n let res = c.res;\n\n if (res && res.status >= 400) {\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_failed\",\n responseStatus: res.status,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n res.headers.get(\"cache-control\"),\n );\n replaceContextResponse(c, withResponseHeaders(res, headers));\n return;\n }\n\n let settleResult;\n try {\n settleResult = await httpServer.processSettlement(\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n // The route handler signals a settlement override (a metered amount\n // below the signed maximum) through a response header.\n // `processSettlement` only reads that off `transportContext`, so\n // omitting this settles the full authorised amount and makes\n // `upto` behave exactly like `exact`.\n {\n request: context,\n responseBody: res\n ? Buffer.from(await res.clone().arrayBuffer())\n : undefined,\n responseHeaders: toHeaderRecord(res?.headers),\n },\n undefined,\n beforeHandlerSettlement,\n );\n } catch (error) {\n replaceContextResponse(c, new Response());\n throw error;\n }\n\n if (!settleResult.success) {\n if (isFacilitatorUnavailable(settleResult.errorReason)) {\n replaceContextResponse(c, facilitatorUnavailableResponse());\n return;\n }\n const { response } = settleResult;\n replaceContextResponse(\n c,\n failureResponse(response.body, response.status, response.headers),\n );\n return;\n } else if (res) {\n res = withSuccessfulSettlementHeaders(res, settleResult.headers);\n }\n\n if (res) replaceContextResponse(c, res);\n return;\n }\n }\n };\n}\n"],"mappings":"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","names":["result","SETTLEMENT_OVERRIDES_HEADER","withPrivateCacheControl","x402ResourceServer","FACILITATOR_SYNC_RETRY_FLOOR_MS","toHeaderRecord","SETTLEMENT_OVERRIDES_HEADER","withPrivateCacheControl","x402ResourceServer","res"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/facilitator/index.ts","../src/facilitator/client.ts","../src/facilitator/fee.ts","../src/facilitator/middleware/express.ts","../package.json","../src/facilitator/middleware/product.ts","../src/facilitator/middleware/handshake.ts","../src/facilitator/middleware/extensions.ts","../src/facilitator/middleware/replay.ts","../src/facilitator/middleware/settlement.ts","../src/facilitator/middleware/hono.ts"],"sourcesContent":["export * from \"@x402/core/server\";\n\nexport { createFacilitatorClient, X402_FACILITATOR_URL } from \"./facilitator\";\nexport type { WeftFacilitatorConfig } from \"./facilitator\";\nexport { getFeeInfo, invalidateFeeCache } from \"./facilitator/fee\";\nexport type { FeeInfo, FeeCacheConfig } from \"./facilitator/fee\";\nexport * from \"./facilitator/middleware\";\n","export * from \"@x402/core\";\nexport * from \"@x402/core/types\";\n\nexport { X402_FACILITATOR_URL, createFacilitatorClient } from \"./client\";\nexport type { WeftFacilitatorConfig } from \"./client\";\n\nexport { getFeeInfo, invalidateFeeCache } from \"./fee\";\nexport type { FeeInfo, FeeCacheConfig } from \"./fee\";\n","import { HTTPFacilitatorClient, FacilitatorConfig } from \"@x402/core/server\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n} from \"@x402/core/types\";\n\nexport const FACILITATOR_UNAVAILABLE_ERROR =\n \"weft:facilitator-settle-unavailable\";\n\nexport const X402_FACILITATOR_URL = \"https://x402.weft.network\";\nexport const X402_FACILITATOR_URL_ENV = \"X402_FACILITATOR_URL\";\n\nexport interface WeftFacilitatorConfig {\n url?: string;\n createAuthHeaders?: FacilitatorConfig[\"createAuthHeaders\"];\n}\n\nclass FacilitatorUnavailableError extends Error {\n readonly statusCode = 503;\n\n constructor() {\n super(FACILITATOR_UNAVAILABLE_ERROR);\n this.name = \"FacilitatorUnavailableError\";\n }\n}\n\nfunction isUnavailableSettleError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const candidate = error as Error & Record<string, unknown>;\n return (\n candidate.name === \"SettleError\" &&\n candidate.statusCode === 503 &&\n \"errorReason\" in candidate &&\n \"errorMessage\" in candidate &&\n \"payer\" in candidate &&\n \"transaction\" in candidate &&\n \"network\" in candidate &&\n !(candidate.errorReason === \"settlement_pending\" && candidate.transaction)\n );\n}\n\nclass WeftHTTPFacilitatorClient extends HTTPFacilitatorClient {\n override async settle(\n paymentPayload: PaymentPayload,\n paymentRequirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n try {\n return await super.settle(paymentPayload, paymentRequirements);\n } catch (error) {\n if (isUnavailableSettleError(error)) {\n throw new FacilitatorUnavailableError();\n }\n throw error;\n }\n }\n}\n\nexport function validateUrl(url: string): void {\n if (!url || url.trim() === \"\") {\n throw new Error(\"Invalid URL: URL cannot be empty\");\n }\n\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n throw new Error(\n `Invalid URL format: URL must start with http:// or https://, got: ${url}`,\n );\n }\n}\n\nexport function resolveUrl(config?: WeftFacilitatorConfig): string {\n if (config?.url) {\n return config.url;\n }\n\n if (\n typeof process !== \"undefined\" &&\n process.env?.[X402_FACILITATOR_URL_ENV]\n ) {\n return process.env[X402_FACILITATOR_URL_ENV]!;\n }\n\n return X402_FACILITATOR_URL;\n}\n\ntype AuthHeadersByPath = Awaited<\n ReturnType<NonNullable<FacilitatorConfig[\"createAuthHeaders\"]>>\n>;\n\n/**\n * Reject a flat headers object the way `@x402/core` itself would.\n *\n * Upstream's `HTTPFacilitatorClient` throws when `createAuthHeaders` returns\n * `{ Authorization: ... }` instead of `{ supported: { Authorization: ... } }`,\n * because silently dropping auth on every request is worse than failing loud.\n * Merging the handshake's own `supported` headers in would mask that check —\n * the merged object always has a path key — so the check runs here first,\n * with the same failure mode a misconfigured seller sees today.\n *\n * @param headers - What the seller's `createAuthHeaders` returned\n */\nfunction assertPathKeyedAuthHeaders(headers: AuthHeadersByPath): void {\n const isHeaderObject = (value: unknown): boolean =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const hasPathKey = [\"verify\", \"settle\", \"supported\", \"bazaar\"].some((key) =>\n isHeaderObject(headers[key as keyof AuthHeadersByPath]),\n );\n const looksFlat =\n !hasPathKey &&\n Object.values(headers).some((value) => !isHeaderObject(value));\n\n if (looksFlat) {\n throw new Error(\n \"createAuthHeaders must return an object keyed by facilitator path, \" +\n 'e.g. { verify: { Authorization: \"...\" }, settle: { ... }, ' +\n \"supported: { ... } }, but received a flat headers object.\",\n );\n }\n}\n\n/**\n * Merge SDK-derived headers under a seller's, case-insensitively, seller wins.\n *\n * Header names are case-insensitive, but object keys are not: a plain spread\n * would keep a derived `Authorization` and a seller `authorization` as two\n * keys, and the HTTP layer folds those into one comma-joined value — a\n * garbled credential. So a seller header replaces any derived header of the\n * same name whatever its case, and the seller's spelling is the one sent.\n *\n * @param derived - Headers the SDK derived from config for one path\n * @param seller - The seller's own headers for that path, if any\n * @returns The merged headers, the seller's winning on conflict\n */\nfunction mergeSellerWins(\n derived: Record<string, string>,\n seller: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = { ...derived };\n for (const [name, value] of Object.entries(seller ?? {})) {\n for (const existing of Object.keys(merged)) {\n if (existing.toLowerCase() === name.toLowerCase()) {\n delete merged[existing];\n }\n }\n merged[name] = value;\n }\n return merged;\n}\n\nexport function createFacilitatorClient(\n config?: WeftFacilitatorConfig,\n weftAuthHeaders?: AuthHeadersByPath,\n): HTTPFacilitatorClient {\n const url = resolveUrl(config);\n validateUrl(url);\n\n const sellerCreateAuthHeaders = config?.createAuthHeaders;\n\n // Only the paths the SDK actually derived headers for — `supported` always,\n // `settle` and `verify` when an apiKey was configured. Empty paths are\n // dropped so a caller with no derived headers is byte-identical to passing\n // none.\n const derivedByPath = Object.entries(weftAuthHeaders ?? {}).filter(\n ([, headers]) => headers !== undefined && Object.keys(headers).length > 0,\n ) as Array<[keyof AuthHeadersByPath, Record<string, string>]>;\n\n const createAuthHeaders =\n derivedByPath.length > 0\n ? async (): Promise<AuthHeadersByPath> => {\n const sellerHeaders = sellerCreateAuthHeaders\n ? await sellerCreateAuthHeaders()\n : undefined;\n if (sellerHeaders) {\n assertPathKeyedAuthHeaders(sellerHeaders);\n }\n // The seller's own headers win on conflict: an explicit\n // createAuthHeaders is a more deliberate act than `apiKey`.\n const merged: AuthHeadersByPath = { ...sellerHeaders };\n for (const [path, derived] of derivedByPath) {\n merged[path] = mergeSellerWins(derived, sellerHeaders?.[path]);\n }\n return merged;\n }\n : sellerCreateAuthHeaders;\n\n return new WeftHTTPFacilitatorClient({\n url,\n createAuthHeaders,\n });\n}\n","import { createFacilitatorClient, WeftFacilitatorConfig } from \"./client\";\n\nexport interface FeeInfo {\n amount: string;\n asset: string;\n network: string;\n}\n\nexport interface FeeCacheConfig {\n ttl?: number;\n}\n\ninterface FeeCache {\n feeInfo: FeeInfo;\n fetchedAt: number;\n ttl: number;\n}\n\nconst DEFAULT_CACHE_TTL = 5 * 60 * 1000;\n\nlet feeCache: FeeCache | null = null;\n\nexport function invalidateFeeCache(): void {\n feeCache = null;\n}\n\nfunction isCacheValid(): boolean {\n if (!feeCache) return false;\n const now = Date.now();\n return now - feeCache.fetchedAt < feeCache.ttl;\n}\n\nexport async function getFeeInfo(\n config?: WeftFacilitatorConfig,\n cacheConfig?: FeeCacheConfig,\n): Promise<FeeInfo> {\n if (isCacheValid() && feeCache) {\n return feeCache.feeInfo;\n }\n\n const client = createFacilitatorClient(config);\n const supported = await client.getSupported();\n\n const fee = (supported as { fee?: FeeInfo }).fee;\n if (!fee) {\n throw new Error(\"Fee information not found in /supported response\");\n }\n\n if (typeof fee.amount !== \"string\") {\n throw new Error(\"Invalid fee structure: amount must be a string\");\n }\n if (typeof fee.asset !== \"string\") {\n throw new Error(\"Invalid fee structure: asset must be a string\");\n }\n if (typeof fee.network !== \"string\") {\n throw new Error(\"Invalid fee structure: network must be a string\");\n }\n\n const feeInfo: FeeInfo = {\n amount: fee.amount,\n asset: fee.asset,\n network: fee.network,\n };\n\n feeCache = {\n feeInfo,\n fetchedAt: Date.now(),\n ttl: cacheConfig?.ttl ?? DEFAULT_CACHE_TTL,\n };\n\n return feeInfo;\n}\n","import type { OutgoingHttpHeaders } from \"node:http\";\nimport {\n HTTPRequestContext,\n PaywallConfig,\n PaywallProvider,\n SETTLEMENT_OVERRIDES_HEADER,\n withPrivateCacheControl,\n x402ResourceServer,\n HTTPAdapter,\n} from \"@x402/core/server\";\nimport { SchemeNetworkServer, Network } from \"@x402/core/types\";\nimport { createFacilitatorClient, WeftFacilitatorConfig } from \"../client\";\nimport { buildFacilitatorAuthHeaders } from \"./handshake\";\nimport {\n applyProductIdentity,\n WeftProductDeclaration,\n WeftRoutesConfig,\n} from \"./product\";\nimport { registerDynamicExtensions } from \"./extensions\";\nimport {\n paymentResumeCandidate,\n resumePaymentResult,\n type ResumeVerifiedPayment,\n} from \"./replay\";\nimport {\n WeftHTTPResourceServer,\n isFacilitatorUnavailable,\n isFacilitatorUnavailableResponse,\n isJsonResponse,\n} from \"./settlement\";\n\ninterface ExpressRequest {\n method: string;\n path: string;\n protocol: string;\n headers: Record<string, string | string[] | undefined>;\n query: Record<string, string | string[] | undefined>;\n body?: unknown;\n header(name: string): string | string[] | undefined;\n}\n\ninterface ExpressResponse {\n status(code: number): ExpressResponse;\n setHeader(\n name: string,\n value: string | number | readonly string[],\n ): ExpressResponse;\n /**\n * Headers the route handler has set. Read at settlement time so a\n * `Settlement-Overrides` header reaches the facilitator.\n */\n getHeaders(): OutgoingHttpHeaders;\n removeHeader(name: string): void;\n send(body: unknown): ExpressResponse;\n json(body: unknown): ExpressResponse;\n statusCode: number;\n writeHead: (...args: unknown[]) => ExpressResponse;\n write: (...args: unknown[]) => boolean;\n end: (...args: unknown[]) => ExpressResponse;\n flushHeaders: () => void;\n}\n\ntype ExpressNextFunction = (err?: unknown) => void;\n\ntype BufferedCall =\n | [\"writeHead\", unknown[]]\n | [\"write\", unknown[]]\n | [\"end\", unknown[]]\n | [\"flushHeaders\", []];\n\nconst UNSAFE_FAILURE_HEADERS = new Set([\n SETTLEMENT_OVERRIDES_HEADER.toLowerCase(),\n \"location\",\n \"set-cookie\",\n]);\n\nfunction isUnsafeFailureHeader(\n name: string,\n value: string | number | readonly string[] | undefined,\n): boolean {\n const normalized = name.toLowerCase();\n return (\n UNSAFE_FAILURE_HEADERS.has(normalized) ||\n (normalized === \"cache-control\" &&\n value !== undefined &&\n /\\bpublic\\b/i.test(\n Array.isArray(value) ? value.join(\",\") : String(value),\n ))\n );\n}\n\n/**\n * Floor between background facilitator re-sync attempts.\n *\n * Without it, a sustained facilitator outage on a busy server couples retry\n * (and warn) volume to request rate: a refused connection settles in\n * milliseconds, so every protected request would launch a fresh `/supported`\n * call for the whole outage. One attempt per floor interval bounds both.\n */\nconst FACILITATOR_SYNC_RETRY_FLOOR_MS = 30_000;\n\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction,\n) => Promise<void> | void;\n\nexport interface SchemeRegistration {\n network: Network;\n server: SchemeNetworkServer;\n}\n\n/**\n * Configuration for the Express payment middleware.\n *\n * Extends {@link WeftProductDeclaration}, so `name`, `type`, `tags`,\n * `iconUrl`, `productId` and `manifestHash` are declared once here and\n * applied to every protected route.\n */\nexport interface WeftExpressMiddlewareConfig extends WeftProductDeclaration {\n /**\n * The seller's Weft API key.\n *\n * Authenticates the facilitator calls that need it: `X-API-Key` on\n * `/settle` — which the facilitator requires, or every settlement 401s —\n * and `Authorization: Bearer <key>` on the construction-time `/supported`\n * handshake, which is how the dashboard learns an SDK is deployed before\n * any payment. Optional, but a seller who omits it must supply their own\n * `facilitator.createAuthHeaders` or settlement fails.\n */\n apiKey?: string;\n facilitator?: WeftFacilitatorConfig;\n schemes?: SchemeRegistration[];\n paywallConfig?: PaywallConfig;\n paywall?: PaywallProvider;\n syncFacilitatorOnStart?: boolean;\n /** Restore durably bound verified inputs for settlement replay. */\n resumeVerifiedPayment?: ResumeVerifiedPayment;\n}\n\nclass ExpressAdapter implements HTTPAdapter {\n constructor(private req: ExpressRequest) {}\n\n getHeader(name: string): string | undefined {\n const value = this.req.header(name);\n return Array.isArray(value) ? value[0] : value;\n }\n\n getMethod(): string {\n return this.req.method;\n }\n\n getPath(): string {\n return this.req.path;\n }\n\n getUrl(): string {\n const host = this.req.headers.host || \"localhost\";\n return `${this.req.protocol}://${host}${this.req.path}`;\n }\n\n getAcceptHeader(): string {\n return this.getHeader(\"Accept\") || \"\";\n }\n\n getUserAgent(): string {\n return this.getHeader(\"User-Agent\") || \"\";\n }\n\n getQueryParams(): Record<string, string | string[]> {\n return this.req.query as Record<string, string | string[]>;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.req.query[name] as string | string[] | undefined;\n }\n\n getBody(): unknown {\n return this.req.body;\n }\n}\n\n/**\n * Flatten Node's outgoing headers into the plain record\n * `HTTPTransportContext` expects. Array values (a repeated header) are joined,\n * numbers stringified; the settlement override lookup in `@x402/core` compares\n * header names case-insensitively.\n *\n * @param headers - Response headers set by the route handler\n * @returns A plain string record\n */\nfunction toHeaderRecord(headers: OutgoingHttpHeaders): Record<string, string> {\n const record: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n record[key] = Array.isArray(value) ? value.join(\",\") : String(value);\n }\n return record;\n}\n\nfunction responseBodyFromBufferedCalls(\n calls: BufferedCall[],\n): Buffer | undefined {\n const chunks: Buffer[] = [];\n for (const [method, args] of calls) {\n if (method !== \"write\" && method !== \"end\") continue;\n const chunk = args[0];\n if (chunk === undefined) continue;\n if (typeof chunk === \"string\") {\n const encoding = typeof args[1] === \"string\" ? args[1] : \"utf8\";\n if (!Buffer.isEncoding(encoding)) return undefined;\n chunks.push(Buffer.from(chunk, encoding));\n } else if (Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {\n chunks.push(Buffer.from(chunk));\n } else {\n return undefined;\n }\n }\n return Buffer.concat(chunks);\n}\n\nfunction restoreHeaders(\n res: ExpressResponse,\n headers: OutgoingHttpHeaders,\n): void {\n for (const name of Object.keys(res.getHeaders())) res.removeHeader(name);\n for (const [name, value] of Object.entries(headers)) {\n if (value !== undefined) res.setHeader(name, value);\n }\n}\n\nasync function sendCoreResponse(\n res: ExpressResponse,\n response: {\n status: number;\n headers: Record<string, string | string[]>;\n body?: unknown;\n },\n): Promise<void> {\n res.status(response.status);\n Object.entries(response.headers).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n if (isJsonResponse(response)) {\n res.json(response.body ?? {});\n } else if (response.body instanceof Blob) {\n res.send(Buffer.from(await response.body.arrayBuffer()));\n } else if (response.body instanceof ArrayBuffer) {\n res.send(Buffer.from(response.body));\n } else if (ArrayBuffer.isView(response.body)) {\n res.send(\n Buffer.from(\n response.body.buffer,\n response.body.byteOffset,\n response.body.byteLength,\n ),\n );\n } else {\n res.send(\n typeof response.body === \"string\"\n ? response.body\n : String(response.body ?? \"\"),\n );\n }\n}\n\nfunction sendFacilitatorUnavailable(res: ExpressResponse): void {\n res.removeHeader(\"payment-response\");\n res.removeHeader(SETTLEMENT_OVERRIDES_HEADER);\n res.setHeader(\"retry-after\", \"1\");\n res.setHeader(\"cache-control\", withPrivateCacheControl(null));\n res.status(503).json({ error: \"facilitator_unavailable\" });\n}\n\n/**\n * Create an Express middleware that requires x402 payment for the given routes.\n *\n * Product identity declared on `config` (`name`, `type`, `tags`, `iconUrl`) is\n * merged into every route, so it travels on the 402 challenge's `resource` and\n * from there onto the buyer's payment payload and the settlement event.\n *\n * @param routes - Route configuration, either a path map or a single route;\n * each route may declare its own `type` to override the product's\n * @param config - Facilitator, scheme, paywall and product identity settings\n * @returns An Express middleware function\n */\nexport function weftPaymentMiddleware(\n routes: WeftRoutesConfig,\n config?: WeftExpressMiddlewareConfig,\n): ExpressMiddleware {\n const facilitatorClient = createFacilitatorClient(\n config?.facilitator,\n buildFacilitatorAuthHeaders(\"express\", config?.apiKey, config ?? {}),\n );\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerDynamicExtensions(resourceServer, routes);\n\n if (config?.schemes) {\n config.schemes.forEach(({ network, server: schemeServer }) => {\n resourceServer.register(network, schemeServer);\n });\n }\n\n const httpServer = new WeftHTTPResourceServer(\n resourceServer,\n applyProductIdentity(routes, config ?? {}),\n );\n\n if (config?.paywall) {\n httpServer.registerPaywallProvider(config.paywall);\n }\n\n // The construction-time facilitator sync doubles as the identity handshake,\n // so its failure modes are held to handshake rules: it must never crash the\n // process (a rejection with no handler attached would, under Node's default\n // unhandled-rejection policy) and must never brick the middleware. The\n // returned promise therefore cannot reject, and a failed sync is retried in\n // the background off later protected requests until one attempt succeeds.\n const syncOnStart = config?.syncFacilitatorOnStart ?? true;\n let facilitatorSynced = false;\n let syncInFlight: Promise<void> | null = null;\n let lastFailedSyncAt = 0;\n\n const syncFacilitator = (): Promise<void> => {\n syncInFlight ??= httpServer\n .initialize()\n .then(\n () => {\n facilitatorSynced = true;\n },\n (error: unknown) => {\n lastFailedSyncAt = Date.now();\n console.warn(\n \"[weft] facilitator sync failed; payment-protected routes \" +\n \"degrade until a later attempt succeeds: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n },\n )\n .finally(() => {\n syncInFlight = null;\n });\n return syncInFlight;\n };\n\n let bootSync: Promise<void> | null = syncOnStart ? syncFacilitator() : null;\n\n return async (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction,\n ) => {\n const adapter = new ExpressAdapter(req);\n const context: HTTPRequestContext = {\n adapter,\n path: req.path,\n method: req.method,\n paymentHeader:\n adapter.getHeader(\"payment-signature\") ||\n adapter.getHeader(\"x-payment\"),\n };\n\n if (!httpServer.requiresPayment(context)) {\n return next();\n }\n\n if (bootSync) {\n // The pre-existing first-request barrier: with a healthy facilitator\n // this resolves once and never runs again. It cannot throw.\n await bootSync;\n bootSync = null;\n }\n if (\n syncOnStart &&\n !facilitatorSynced &&\n Date.now() - lastFailedSyncAt >= FACILITATOR_SYNC_RETRY_FLOOR_MS\n ) {\n // Heal a failed boot sync without delaying anyone: the retry is kicked\n // fire-and-forget (one in flight at most, one attempt per floor\n // interval) and this request proceeds.\n void syncFacilitator();\n }\n\n let result;\n try {\n const resumeCandidate = paymentResumeCandidate(context);\n const resumedPayment = resumeCandidate\n ? await config?.resumeVerifiedPayment?.(context, resumeCandidate)\n : undefined;\n result = resumedPayment\n ? resumePaymentResult(resourceServer, resumedPayment, context)\n : await httpServer.processHTTPRequest(context, config?.paywallConfig);\n } catch (error) {\n // Express 4 does not catch a rejection from an async middleware; under\n // Node's default policy that takes the whole process down. Routing the\n // failure through next(error) keeps it inside Express's own error\n // handling, whatever left the resource server unable to answer.\n return next(error);\n }\n\n switch (result.type) {\n case \"no-payment-required\":\n return next();\n\n case \"payment-error\": {\n const { response } = result;\n if (isFacilitatorUnavailableResponse(response)) {\n sendFacilitatorUnavailable(res);\n return;\n }\n await sendCoreResponse(res, response);\n return;\n }\n\n case \"payment-verified\": {\n const {\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n cancellationDispatcher,\n beforeHandlerSettlement,\n } = result;\n\n const originalWriteHead = res.writeHead.bind(res);\n const originalWrite = res.write.bind(res);\n const originalEnd = res.end.bind(res);\n const originalFlushHeaders = res.flushHeaders.bind(res);\n const originalSetHeader = res.setHeader.bind(res);\n const originalRemoveHeader = res.removeHeader.bind(res);\n const headersBeforeHandler = { ...res.getHeaders() };\n\n let bufferedCalls: BufferedCall[] = [];\n let settled = false;\n const failureHeaders = new Map<\n string,\n {\n name: string;\n value?: string | number | readonly string[];\n }\n >();\n\n const restoreResponseMethods = () => {\n res.setHeader = originalSetHeader;\n res.removeHeader = originalRemoveHeader;\n res.writeHead = originalWriteHead;\n res.write = originalWrite;\n res.end = originalEnd;\n res.flushHeaders = originalFlushHeaders;\n };\n\n const replayBufferedCall = ([method, args]: BufferedCall) => {\n if (method === \"writeHead\") {\n const [statusCode, statusMessage] = args;\n return typeof statusMessage === \"string\"\n ? originalWriteHead(statusCode, statusMessage)\n : originalWriteHead(statusCode);\n }\n if (method === \"write\") return originalWrite(...args);\n if (method === \"end\") return originalEnd(...args);\n return originalFlushHeaders();\n };\n\n let endCalled: () => void;\n const endPromise = new Promise<void>((resolve) => {\n endCalled = resolve;\n });\n\n res.writeHead = function (...args: unknown[]) {\n if (!settled) {\n const [statusCode, statusMessageOrHeaders, maybeHeaders] = args;\n if (typeof statusCode === \"number\") {\n res.statusCode = statusCode;\n }\n const headers =\n typeof statusMessageOrHeaders === \"string\"\n ? maybeHeaders\n : statusMessageOrHeaders;\n if (Array.isArray(headers)) {\n const grouped = new Map<\n string,\n { name: string; values: string[] }\n >();\n for (let index = 0; index < headers.length; index += 2) {\n const name = String(headers[index]);\n const key = name.toLowerCase();\n const entry = grouped.get(key) ?? { name, values: [] };\n entry.values.push(String(headers[index + 1]));\n grouped.set(key, entry);\n }\n for (const { name, values } of grouped.values()) {\n res.setHeader(name, values.length === 1 ? values[0] : values);\n }\n } else if (headers && typeof headers === \"object\") {\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n res.setHeader(\n key,\n Array.isArray(value) ? value : String(value),\n );\n }\n }\n bufferedCalls.push([\"writeHead\", args]);\n return res;\n }\n return originalWriteHead(...args);\n } as typeof res.writeHead;\n\n res.setHeader = function (name, value) {\n const result = originalSetHeader(name, value);\n if (!settled && res.statusCode >= 400) {\n failureHeaders.set(name.toLowerCase(), {\n name,\n value: Array.isArray(value) ? [...value] : value,\n });\n }\n return result;\n } as typeof res.setHeader;\n\n res.removeHeader = function (name) {\n originalRemoveHeader(name);\n if (!settled && res.statusCode >= 400) {\n failureHeaders.set(name.toLowerCase(), { name });\n }\n };\n\n res.write = function (...args: unknown[]) {\n if (!settled) {\n bufferedCalls.push([\"write\", args]);\n return true;\n }\n return originalWrite(...args);\n } as typeof res.write;\n\n res.end = function (...args: unknown[]) {\n if (!settled) {\n bufferedCalls.push([\"end\", args]);\n endCalled();\n return res;\n }\n return originalEnd(...args);\n } as typeof res.end;\n\n res.flushHeaders = function () {\n if (!settled) {\n bufferedCalls.push([\"flushHeaders\", []]);\n return;\n }\n return originalFlushHeaders();\n };\n\n const finalizeFailure = async (\n cancellation:\n | { reason: \"handler_threw\"; error: unknown }\n | { reason: \"handler_failed\"; responseStatus: number },\n ) => {\n // Express exposes only the final header bag, not whether a pre-status\n // header belongs to a direct error response or a later throw. Preserve\n // by default and remove only headers that can leak payment or success.\n const preservedFailureHeaders = new Map<\n string,\n string | number | readonly string[]\n >();\n for (const [name, value] of Object.entries(res.getHeaders())) {\n if (value === undefined || isUnsafeFailureHeader(name, value))\n continue;\n preservedFailureHeaders.set(\n name,\n Array.isArray(value) ? [...value] : value,\n );\n }\n const cancelSettlement =\n await cancellationDispatcher.cancel(cancellation);\n settled = true;\n restoreHeaders(res, headersBeforeHandler);\n for (const [name, value] of Object.entries(res.getHeaders())) {\n if (isUnsafeFailureHeader(name, value)) res.removeHeader(name);\n }\n for (const [name, value] of preservedFailureHeaders) {\n res.setHeader(name, value);\n }\n for (const { name, value } of failureHeaders.values()) {\n if (value === undefined || isUnsafeFailureHeader(name, value))\n res.removeHeader(name);\n else res.setHeader(name, value);\n }\n const existingCacheControl = Object.entries(res.getHeaders()).find(\n ([key]) => key.toLowerCase() === \"cache-control\",\n )?.[1];\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n Array.isArray(existingCacheControl)\n ? existingCacheControl.join(\",\")\n : existingCacheControl === undefined\n ? undefined\n : String(existingCacheControl),\n );\n Object.entries(headers ?? {}).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n restoreResponseMethods();\n\n for (const call of bufferedCalls) replayBufferedCall(call);\n bufferedCalls = [];\n };\n\n try {\n next();\n } catch (error) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n failureHeaders.clear();\n try {\n next(error);\n } catch (errorMiddlewareError) {\n restoreResponseMethods();\n throw errorMiddlewareError;\n }\n await endPromise;\n await finalizeFailure({ reason: \"handler_threw\", error });\n return;\n }\n\n await endPromise;\n\n if (res.statusCode >= 400) {\n await finalizeFailure({\n reason: \"handler_failed\",\n responseStatus: res.statusCode,\n });\n return;\n }\n\n try {\n const settleResult = await httpServer.processSettlement(\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n // The route handler signals a settlement override (a metered amount\n // below the signed maximum) through a response header.\n // `processSettlement` only reads that off `transportContext`, so\n // omitting this settles the full authorised amount and makes\n // `upto` behave exactly like `exact`.\n {\n request: context,\n responseBody: responseBodyFromBufferedCalls(bufferedCalls),\n responseHeaders: toHeaderRecord(res.getHeaders()),\n },\n undefined,\n beforeHandlerSettlement,\n );\n\n if (!settleResult.success) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n if (isFacilitatorUnavailable(settleResult.errorReason)) {\n sendFacilitatorUnavailable(res);\n return;\n }\n const { response } = settleResult;\n await sendCoreResponse(res, response);\n return;\n }\n\n Object.entries(settleResult.headers).forEach(([key, value]) => {\n const headerValue = Array.isArray(value)\n ? value.join(\",\")\n : String(value);\n res.setHeader(key, headerValue);\n });\n const cacheControl = res.getHeaders()[\"cache-control\"];\n res.setHeader(\n \"cache-control\",\n withPrivateCacheControl(\n Array.isArray(cacheControl)\n ? cacheControl.join(\",\")\n : cacheControl === undefined\n ? null\n : String(cacheControl),\n ),\n );\n res.removeHeader(SETTLEMENT_OVERRIDES_HEADER);\n } catch (error) {\n bufferedCalls = [];\n restoreHeaders(res, headersBeforeHandler);\n settled = true;\n restoreResponseMethods();\n next(error);\n return;\n } finally {\n settled = true;\n restoreResponseMethods();\n\n for (const call of bufferedCalls) replayBufferedCall(call);\n bufferedCalls = [];\n }\n return;\n }\n }\n };\n}\n","{\n \"name\": \"@weftlabs/sdk\",\n \"version\": \"0.26.9\",\n \"description\": \"Unified Weft SDK for the Weft API and x402 Facilitator\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"./facilitator\": {\n \"import\": {\n \"types\": \"./dist/facilitator/index.d.mts\",\n \"default\": \"./dist/facilitator/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/facilitator/index.d.ts\",\n \"default\": \"./dist/facilitator/index.js\"\n }\n },\n \"./facilitator/middleware\": {\n \"import\": {\n \"types\": \"./dist/facilitator/middleware/index.d.mts\",\n \"default\": \"./dist/facilitator/middleware/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/facilitator/middleware/index.d.ts\",\n \"default\": \"./dist/facilitator/middleware/index.js\"\n }\n },\n \"./server\": {\n \"import\": {\n \"types\": \"./dist/server.d.mts\",\n \"default\": \"./dist/server.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/server.d.ts\",\n \"default\": \"./dist/server.js\"\n }\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest run\",\n \"test:unit\": \"vitest run\",\n \"lint\": \"eslint --fix\",\n \"lint:check\": \"eslint\",\n \"format\": \"prettier --write \\\"src/**/*.ts\\\" \\\"!src/generated/**\\\" \\\"examples/*.mjs\\\" \\\"../scripts/test-typescript-quickstarts.mjs\\\" \\\"../scripts/test-seller-quickstarts.mjs\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.ts\\\" \\\"!src/generated/**\\\" \\\"examples/*.mjs\\\" \\\"../scripts/test-typescript-quickstarts.mjs\\\" \\\"../scripts/test-seller-quickstarts.mjs\\\"\",\n \"hooks:pre-push\": \"pnpm run lint:check && pnpm run format:check && vitest run\",\n \"generate\": \"../scripts/generate-typescript.sh\",\n \"smoke\": \"pnpm run build && node ../scripts/weft-smoke.mjs\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"keywords\": [\n \"weft\",\n \"x402\",\n \"payments\",\n \"micropayments\",\n \"coinbase\",\n \"sdk\"\n ],\n \"author\": \"Weft Labs\",\n \"license\": \"Apache-2.0\",\n \"homepage\": \"https://weftlabs.com\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/weftlabs/weft-sdk\"\n },\n \"peerDependencies\": {\n \"@x402/core\": \"^2.24.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^26.1.2\",\n \"@typescript-eslint/eslint-plugin\": \"^8.29.1\",\n \"@typescript-eslint/parser\": \"^8.29.1\",\n \"@x402/core\": \"2.24.0\",\n \"eslint\": \"^10.4.1\",\n \"express\": \"^5.2.1\",\n \"fast-check\": \"^4.8.0\",\n \"hono\": \"^4.13.5\",\n \"prettier\": \"3.9.6\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.11\"\n },\n \"files\": [\n \"dist\",\n \"docs\",\n \"examples\",\n \"README.md\"\n ],\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"packageManager\": \"pnpm@10.33.4\",\n \"overrides\": {\n \"esbuild\": \"^0.28.1\"\n }\n}\n","import type { RouteConfig, RoutesConfig } from \"@x402/core/server\";\n\n/**\n * What kind of thing the seller is selling.\n *\n * Deliberately small. If you need a kind that is not here, use `tags`.\n */\nexport type WeftProductType = \"api\" | \"agent\" | \"mcp\";\n\n/**\n * The legal {@link WeftProductType} values, as data.\n *\n * `WeftProductType` is erased at compile time and this package ships plain\n * `.mjs` examples, so the type is checked against this list at runtime too.\n */\nconst PRODUCT_TYPES: readonly string[] = [\"api\", \"agent\", \"mcp\"];\n\n/**\n * Reserved tag prefix that carries {@link WeftProductIdentity.type} on the wire.\n *\n * `ResourceInfo` in the x402 protocol has no field for a product kind, and the\n * facilitator only relays `serviceName`, `tags` and `iconUrl` to the settlement\n * event. `tags` is therefore the only channel a product type can travel in, so\n * the SDK encodes it as one reserved tag — `weft:type:api`, `weft:type:agent`,\n * `weft:type:mcp`.\n *\n * The prefix is namespaced so it cannot collide with a seller's own free-text\n * tags, stays readable in a raw settlement row, and is matched downstream with\n * a plain `startsWith`. The SDK guarantees at most one such tag per route: any\n * `weft:type:*` value a caller puts in `tags` is dropped with a warning, in\n * favour of the `type` field on the product or on the route.\n */\nexport const WEFT_TYPE_TAG_PREFIX = \"weft:type:\";\n\n/**\n * Bounds the x402 protocol declares for the `ResourceInfo` identity fields.\n *\n * `ResourceInfoSchema` in `@x402/core/schemas` caps `tags` at five entries of\n * 1-32 printable-ASCII characters, `serviceName` at 1-32 printable-ASCII\n * characters, and `iconUrl` at 2048 characters. No code path inside\n * `@x402/core` applies that schema when a challenge is built, but it is the\n * published contract, and `parsePaymentRequired` — which any buyer may run —\n * rejects the *whole* `PaymentRequired` when a single field is out of bounds.\n *\n * The SDK therefore never emits a value outside these bounds. A declared\n * `type` spends one of the five tag slots, leaving four for the seller.\n *\n * These are the *protocol's* bounds, not the Weft facilitator's, which are\n * looser. That is deliberate: the challenge is read by buyers before it ever\n * reaches a facilitator, so the narrower contract is the one that has to hold.\n * It costs sellers whose names are not expressible in ASCII — a real cost,\n * carried knowingly, and the right place to fix it is the protocol schema.\n */\nconst MAX_TAGS = 5;\nconst MAX_TAG_CHARS = 32;\n/**\n * Bounds on declared analytics dimensions.\n *\n * These are Weft's own, not the x402 protocol's: dimensions never touch the\n * 402 challenge. They travel only on the authenticated boot handshake, where\n * the facilitator caps the whole `X-Weft-Declared` header at 8 KiB.\n *\n * Eight is a deliberate ceiling on ambition rather than on bytes. A dimension\n * is a low-cardinality slice a seller wants revenue broken down by; a seller\n * declaring more than a handful is dumping their parameter list, which is the\n * failure mode the whole rule exists to prevent.\n */\nconst MAX_DIMENSIONS = 8;\nconst MAX_DIMENSION_CHARS = 64;\n/**\n * Shape a declared dimension name must have: a plausible JSON field name.\n *\n * A dimension names a key inside `weft.request`'s `info`, and downstream it\n * becomes an allowlist entry that a SQL aggregate reads. Constraining it to\n * the characters real field names use keeps a hostile or accidental value\n * from ever reaching that position.\n */\nconst DIMENSION_NAME = /^[A-Za-z_][A-Za-z0-9_.-]*$/;\nconst MAX_SERVICE_NAME_CHARS = 32;\nconst MAX_ICON_URL_CHARS = 2048;\nconst PRINTABLE_ASCII = /^[\\x20-\\x7e]+$/;\n\n/**\n * Product-level identity, declared once and applied to every protected route.\n *\n * This is what turns a settlement into a named product in the Weft dashboard.\n * Every field is optional; a middleware configured without any of them behaves\n * exactly as it did before this identity existed.\n *\n * Every field is also validated at construction time, because these values\n * routinely come from JSON or env and TypeScript is not present at runtime.\n * Anything the x402 protocol cannot carry is clamped or dropped, with one\n * `[weft]` line explaining what shipped — never a thrown error in a payment\n * server's boot path, and never a malformed challenge on the wire.\n */\nexport interface WeftProductIdentity {\n /**\n * Display name of the product, e.g. `\"Acme Pricing API\"`.\n *\n * Travels as `ResourceInfo.serviceName` on the 402 challenge. The protocol\n * carries 32 printable-ASCII characters; a longer name is truncated to fit,\n * with a warning naming both values.\n */\n name?: string;\n\n /**\n * What kind of product this is.\n *\n * Travels as a reserved `weft:type:<type>` tag — see {@link WEFT_TYPE_TAG_PREFIX}.\n * A route may declare its own `type`, which wins for that route.\n */\n type?: WeftProductType;\n\n /**\n * Free-text tags describing the product, e.g. `[\"finance\", \"pricing\"]`.\n *\n * Travels as `ResourceInfo.tags`. Tags starting with `weft:type:` are\n * reserved and are dropped in favour of {@link WeftProductIdentity.type}.\n *\n * The x402 protocol allows five tags of at most 32 printable-ASCII\n * characters. A declared `type` uses one slot, so four remain. Anything\n * beyond that is dropped with a warning rather than being put on the wire,\n * because an out-of-bounds array costs the seller every tag they declared.\n */\n tags?: string[];\n\n /**\n * Absolute `http:` or `https:` URL of an icon for the product.\n *\n * Travels as `ResourceInfo.iconUrl`. A dashboard renders this URL, so any\n * other scheme is dropped with a warning.\n */\n iconUrl?: string;\n}\n\n/**\n * Extension key under which the product declaration travels on the wire.\n *\n * Unlike the identity fields, which ride `ResourceInfo`, the product\n * declaration rides x402 v2 `extensions`: declared by the server on the 402\n * challenge, echoed by the buyer's client onto `PaymentPayload`, validated\n * against the advertisement at verify time, and relayed by the facilitator on\n * the settlement event.\n */\nexport const WEFT_PRODUCT_EXTENSION_KEY = \"weft.product\";\n\n/**\n * JSON Schema (Draft 2020-12) for the `weft.product` extension's `info`.\n *\n * Ships verbatim as the extension's `schema` member, per the x402 v2\n * extensions shape `{info, schema}`. Every field is optional because absent\n * declarations are omitted from `info` rather than sent empty.\n *\n * `additionalProperties: false` is a **published contract statement, not an\n * enforcement**. Upstream's echo check is a subset match — advertised `info`\n * fields must be preserved, but a buyer may *add* fields to the echoed\n * `info` and pass, and when a route advertises no extensions the check never\n * runs. So an echoed `weft.product` proves nothing about fields the seller\n * did not advertise: by the time it reaches a consumer it is unauthenticated\n * buyer input. A buyer has no legitimate reason to add fields to a seller\n * claim, and this flag is the declared basis for consumers to strip\n * anything unadvertised — but the stripping, and the deeper rule, are the\n * consumer's job. Attribution must never key on echoed extension contents;\n * it keys on seller-authenticated joins — the API key that settled the\n * payment (weft-app #635 freezes `payments.product_id` from exactly that at\n * settlement time) or the S1 handshake's authenticated declaration.\n */\nexport const WEFT_PRODUCT_INFO_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...PRODUCT_TYPES] },\n product_id: { type: \"string\", minLength: 1 },\n manifest_hash: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n} as const;\n\n/**\n * Product-level declaration: the identity plus the product reference fields.\n *\n * `productId` and `manifestHash` are not cosmetic identity — they are the\n * seller's claim about *which* dashboard product this deployment is and what\n * manifest it was built from. They travel in the `weft.product` extension,\n * never in `ResourceInfo`, so they extend the identity type rather than\n * joining it.\n */\nexport interface WeftProductDeclaration extends WeftProductIdentity {\n /**\n * Identifier of the dashboard product this deployment claims to be.\n *\n * Travels as `extensions[\"weft.product\"].info.product_id` on the 402\n * challenge and, echoed by the buyer, on the payment payload the\n * facilitator settles.\n */\n productId?: string;\n\n /**\n * Hash of the product manifest this deployment was built from.\n *\n * Travels as `extensions[\"weft.product\"].info.manifest_hash`, next to\n * {@link WeftProductDeclaration.productId}. Opaque to the SDK: no format is\n * enforced beyond being a non-empty string.\n */\n manifestHash?: string;\n\n /**\n * Field names inside `weft.request` that revenue may be broken down by,\n * e.g. `[\"model\", \"tier\"]`.\n *\n * Travels only on the authenticated boot handshake — never on the 402\n * challenge, never in `weft.product`. That is the point of it: the values\n * on a payment are buyer-echoed, so an aggregate summing an *undeclared*\n * key would be summing buyer-controlled input. A field declared here is\n * one the seller vouched for under their own API key, which is what makes\n * \"revenue for model=gpt-5.6 this month\" an answer rather than a guess.\n *\n * Declare dimensions, not payloads. Low cardinality, enumerable: `model`,\n * `tier`, `size`, `region`. Never prompt text, a user id or a document\n * body — those blow up the index, leak content, and are useless as a\n * breakdown anyway.\n */\n dimensions?: string[];\n}\n\n/**\n * A route config that may also declare the product kind for that route alone.\n *\n * `RouteConfig` comes from `@x402/core` and has no field for a product kind.\n * A seller whose surface is part API and part MCP needs to say so per route,\n * so the SDK accepts `type` here, consumes it into the reserved tag, and never\n * passes the field itself down to the resource server.\n *\n * The inherited `extensions` map gains one capability here: any value may be a\n * `WeftDynamicExtension` callback instead of a static object, resolved per\n * request at the same point as `price`. The field is already typed\n * `Record<string, unknown>` upstream, so this needs no wider type — only the\n * middleware registering the resolver for those keys.\n */\nexport interface WeftRouteConfig extends RouteConfig {\n /** Product kind for this route; overrides {@link WeftProductIdentity.type}. */\n type?: WeftProductType;\n}\n\n/** {@link RoutesConfig}, with per-route {@link WeftRouteConfig.type} allowed. */\nexport type WeftRoutesConfig =\n Record<string, WeftRouteConfig> | WeftRouteConfig;\n\n/**\n * Build the reserved tag for a product type.\n *\n * @param type - The product type to encode\n * @returns The reserved tag, e.g. `weft:type:api`\n */\nexport function productTypeTag(type: WeftProductType): string {\n return `${WEFT_TYPE_TAG_PREFIX}${type}`;\n}\n\n/**\n * Whether a caller actually declared a value.\n *\n * `null` reads as \"absent\": upstream types every identity field `.nullish()`,\n * and a seller whose JSON config carries an explicit null means they have no\n * name, not that they want `null` on the wire. Treating it as absent also\n * keeps the field off challenges consumed by `@x402/core` 2.14, which typed\n * these `.optional()` and rejects an explicit null — and the peer range\n * (`^2.0.0`) lets a seller pin exactly that.\n *\n * @param value - A declared identity value\n * @returns True when the caller supplied something other than null/undefined\n */\nfunction isDeclared(value: unknown): boolean {\n return value !== undefined && value !== null;\n}\n\n/**\n * Name a value's runtime type for a diagnostic.\n *\n * @param value - The offending value\n * @returns A short phrase, e.g. `a number`, `an array`, `null`\n */\nfunction typeName(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (Array.isArray(value)) {\n return \"an array\";\n }\n return `a ${typeof value}`;\n}\n\n/**\n * Render a value for a diagnostic without ever throwing.\n *\n * @param value - The offending value\n * @returns A quoted, escaped rendering of the value\n */\nfunction show(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return typeName(value);\n }\n}\n\n/**\n * Discriminate the two shapes of `RoutesConfig`.\n *\n * Mirrors the check `@x402/core` uses itself (`\"accepts\" in routes`) so a\n * config the resource server treats as a single route is treated the same way\n * here.\n *\n * @param routes - Route configuration passed by the caller\n * @returns True when `routes` is a single route rather than a path map\n */\nfunction isSingleRoute(routes: WeftRoutesConfig): routes is WeftRouteConfig {\n return \"accepts\" in routes;\n}\n\n/**\n * Reports identity the seller declared but that will not ship as written.\n *\n * `dedupeKey` names the *problem*, and defaults to the message. A caller whose\n * message carries per-occurrence detail — an exception message, a byte count —\n * must pass one, or every occurrence is both a fresh log line and a permanent\n * entry in the sink's memory.\n */\nexport type Warn = (message: string, dedupeKey?: string) => void;\n\n/**\n * Build a warning sink that emits each distinct problem once.\n *\n * Product-level identity is applied to every route, so an over-long tag would\n * otherwise produce one identical line per route at boot. Identity warnings are\n * all emitted when the middleware is built, so they land in boot output rather\n * than in a payment path; the one sink that runs per request — a failing\n * {@link WeftDynamicExtension} — leans on the same de-duplication to stay one\n * line per distinct problem instead of one per request.\n *\n * That per-request use is why the key is separable from the message. A sink\n * that remembered whole messages would, for a callback whose failure carries a\n * request id, log every request and grow a set that is never collected — a\n * memory leak in a payment path, dressed as de-duplication.\n *\n * @returns A warn function that suppresses repeats\n */\nexport function createWarn(): Warn {\n const seen = new Set<string>();\n\n return (message: string, dedupeKey?: string) => {\n const key = dedupeKey ?? message;\n if (seen.has(key)) {\n return;\n }\n seen.add(key);\n console.warn(`[weft] ${message}`);\n };\n}\n\n/**\n * Read a declared value that has to be a string.\n *\n * @param field - Field name, for the diagnostic\n * @param value - The declared value, from a route or from the product identity\n * @param warn - Sink for anything that will not ship\n * @returns The string, or undefined when absent or unusable\n */\nfunction asString(\n field: string,\n value: unknown,\n warn: Warn,\n): string | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (typeof value !== \"string\") {\n warn(\n `ignoring ${field} ${show(value)}: expected a string, got ` +\n `${typeName(value)}`,\n );\n return undefined;\n }\n return value;\n}\n\n/**\n * Whether a tag is using the reserved product-type namespace.\n *\n * Matched leniently — case-folded and trimmed — so `\"WEFT:TYPE:mcp\"` and\n * `\" weft:type:mcp\"` are recognised as the reserved form a reader would have\n * to interpret, rather than surviving as free-text tags that contradict the\n * one-type-per-route guarantee and burn a tag slot doing it.\n *\n * @param tag - A seller-declared tag\n * @returns True when the tag occupies the reserved namespace\n */\nfunction isReservedTypeTag(tag: string): boolean {\n return tag.trim().toLowerCase().startsWith(WEFT_TYPE_TAG_PREFIX);\n}\n\n/**\n * Read a declared product type, rejecting anything not in the legal set.\n *\n * `WeftProductType` is a compile-time type only, and the reserved tag it\n * becomes is subject to the same protocol bounds as every other tag. An\n * unchecked value here is worse than an unchecked free-text tag: the Weft\n * facilitator drops the entire `tags` array when a single entry is malformed,\n * so a junk `type` costs the seller every tag they declared — through the very\n * value the tag bounds exist to protect.\n *\n * @param value - The declared type, from a route or from the product identity\n * @param field - Field name, for the diagnostic\n * @param warn - Sink for anything that will not ship\n * @returns The product type, or undefined when absent or illegal\n */\nfunction resolveType(\n value: unknown,\n field: string,\n warn: Warn,\n): WeftProductType | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (typeof value !== \"string\" || !PRODUCT_TYPES.includes(value)) {\n warn(\n `ignoring ${field} ${show(value)}: expected one of ` +\n `${PRODUCT_TYPES.join(\", \")}`,\n );\n return undefined;\n }\n return value as WeftProductType;\n}\n\n/**\n * Read a declared tag list, dropping entries that are not strings.\n *\n * @param value - The declared tags, from a route or from the product identity\n * @param field - Field name, for the diagnostic\n * @param warn - Sink for anything that will not ship\n * @returns The string tags, or undefined when absent or unusable\n */\nfunction asTagList(\n value: unknown,\n field: string,\n warn: Warn,\n): string[] | undefined {\n if (!isDeclared(value)) {\n return undefined;\n }\n if (!Array.isArray(value)) {\n warn(\n `ignoring ${field} ${show(value)}: expected an array of strings, got ` +\n `${typeName(value)}`,\n );\n return undefined;\n }\n\n return value.filter((entry): entry is string => {\n if (typeof entry === \"string\") {\n return true;\n }\n warn(\n `dropping tag ${show(entry)}: expected a string, got ` +\n `${typeName(entry)}`,\n );\n return false;\n });\n}\n\n/**\n * Resolve the tags for one route.\n *\n * Route tags win over product tags wholesale — a seller who lists tags on a\n * route means exactly those. The product type is not a tag default though: it\n * is a separate declaration that happens to travel in the tags channel, so it\n * is always applied on top, and reserved `weft:type:*` values supplied by the\n * caller are dropped so exactly one type ever reaches the settlement event.\n *\n * The type tag is placed first, so if the seller declared more tags than the\n * protocol carries, the product type is the one thing guaranteed to survive.\n * It is then filtered by the same bounds as every other tag rather than being\n * trusted: nothing reaches the wire unchecked, including values the SDK built\n * itself.\n *\n * @param routeTags - Tags declared on the route, if any\n * @param identityTags - Tags declared on the product identity, if any\n * @param type - The already-validated type for this route, if any\n * @param warn - Sink for anything dropped\n * @returns The tags to put on the wire, or undefined to leave `tags` absent\n */\nfunction resolveTags(\n routeTags: unknown,\n identityTags: unknown,\n type: WeftProductType | undefined,\n warn: Warn,\n): string[] | undefined {\n const declared =\n asTagList(routeTags, \"route tags\", warn) ??\n asTagList(identityTags, \"tags\", warn);\n\n if (declared === undefined && type === undefined) {\n return undefined;\n }\n\n const sellerTags = (declared ?? []).filter((tag) => {\n if (!isReservedTypeTag(tag)) {\n return true;\n }\n warn(\n `dropping reserved tag ${show(tag)}: declare the product kind with ` +\n `\\`type\\` (${PRODUCT_TYPES.join(\", \")}) on the middleware config or ` +\n `on the route`,\n );\n return false;\n });\n\n const malformed: string[] = [];\n const carried = [\n ...(type !== undefined ? [productTypeTag(type)] : []),\n ...sellerTags,\n ].filter((tag) => {\n if (tag.length <= MAX_TAG_CHARS && PRINTABLE_ASCII.test(tag)) {\n return true;\n }\n malformed.push(tag);\n return false;\n });\n\n if (malformed.length > 0) {\n warn(\n `dropping ${malformed.length} tag(s) the x402 protocol cannot carry ` +\n `(max ${MAX_TAG_CHARS} printable-ASCII characters each): ` +\n `${malformed.join(\", \")}`,\n );\n }\n\n const deduped = [...new Set(carried)];\n\n if (deduped.length > MAX_TAGS) {\n const dropped = deduped.slice(MAX_TAGS);\n warn(\n `dropping ${dropped.length} tag(s): the x402 protocol carries ` +\n `${MAX_TAGS}` +\n (type !== undefined ? \" and the declared type uses one of them\" : \"\") +\n `. Dropped: ${dropped.join(\", \")}`,\n );\n }\n\n const bounded = deduped.slice(0, MAX_TAGS);\n return bounded.length > 0 ? bounded : undefined;\n}\n\n/**\n * Resolve the service name for one route, keeping it inside the x402 schema.\n *\n * An over-long name is truncated rather than rejected. The alternative — a\n * thrown error at construction — turns a cosmetic field into a boot failure on\n * a payment server, and 32 characters is tight enough that ordinary product\n * names exceed it. Sending it unchanged is not an option either: it is the\n * whole `PaymentRequired` that `parsePaymentRequired` rejects, not the field,\n * so an over-long name costs the seller the entire challenge.\n *\n * Truncating is also what the SDK already does to tags, for the same reason.\n * A name that cannot be represented at all — empty, or not printable ASCII —\n * is dropped instead, because there is nothing left to truncate to.\n *\n * @param routeServiceName - Service name declared on the route, if any\n * @param identityName - Product name declared on the middleware config, if any\n * @param warn - Sink for anything that will not travel as declared\n * @returns The service name to put on the wire, or undefined to leave it absent\n */\nfunction resolveServiceName(\n routeServiceName: unknown,\n identityName: unknown,\n warn: Warn,\n): string | undefined {\n const declared =\n asString(\"route serviceName\", routeServiceName, warn) ??\n asString(\"name\", identityName, warn);\n\n if (declared === undefined) {\n return undefined;\n }\n\n if (!PRINTABLE_ASCII.test(declared)) {\n warn(\n `dropping product name ${show(declared)}: the x402 protocol carries ` +\n `1-${MAX_SERVICE_NAME_CHARS} printable-ASCII characters ` +\n `(U+0020-U+007E)`,\n );\n return undefined;\n }\n\n if (declared.length > MAX_SERVICE_NAME_CHARS) {\n const truncated = declared.slice(0, MAX_SERVICE_NAME_CHARS);\n warn(\n `product name ${show(declared)} is ${declared.length} characters; the ` +\n `x402 protocol carries ${MAX_SERVICE_NAME_CHARS}, so it travels as ` +\n `${show(truncated)}`,\n );\n return truncated;\n }\n\n return declared;\n}\n\n/**\n * Resolve the icon URL for one route.\n *\n * This is the last Weft-authored check before a URL the SDK put on a challenge\n * is rendered in someone's dashboard: the facilitator relays `iconUrl` without\n * inspecting its scheme. So the SDK only emits absolute `http:`/`https:` URLs\n * inside the protocol's length bound, and drops anything else with a warning.\n *\n * @param routeIconUrl - Icon URL declared on the route, if any\n * @param identityIconUrl - Icon URL declared on the middleware config, if any\n * @param warn - Sink for anything that will not ship\n * @returns The icon URL to put on the wire, or undefined to leave it absent\n */\nfunction resolveIconUrl(\n routeIconUrl: unknown,\n identityIconUrl: unknown,\n warn: Warn,\n): string | undefined {\n const declared =\n asString(\"route iconUrl\", routeIconUrl, warn) ??\n asString(\"iconUrl\", identityIconUrl, warn);\n\n if (declared === undefined) {\n return undefined;\n }\n\n if (declared.length > MAX_ICON_URL_CHARS) {\n warn(\n `dropping iconUrl: ${declared.length} characters exceeds the ` +\n `${MAX_ICON_URL_CHARS} the x402 protocol carries`,\n );\n return undefined;\n }\n\n let scheme: string;\n try {\n scheme = new URL(declared).protocol;\n } catch {\n warn(\n `dropping iconUrl ${show(declared)}: expected an absolute http or ` +\n `https URL`,\n );\n return undefined;\n }\n\n if (scheme !== \"http:\" && scheme !== \"https:\") {\n warn(\n `dropping iconUrl ${show(declared)}: only http and https are carried ` +\n `(a dashboard renders this URL)`,\n );\n return undefined;\n }\n\n return declared;\n}\n\n/**\n * Resolve the analytics dimensions a seller declared.\n *\n * Same posture as every other declared value here — clamp, drop, warn once,\n * never throw in a boot path — with bounds that are Weft's rather than the\n * protocol's, because these travel on the handshake alone.\n *\n * @param value - The declared `dimensions` value, from config or env\n * @param warn - Sink for anything that will not ship\n * @returns The dimension names that will travel, or undefined when none do\n */\nexport function resolveDimensions(\n value: unknown,\n warn: Warn,\n): string[] | undefined {\n const declared = asTagList(value, \"dimensions\", warn);\n if (declared === undefined) {\n return undefined;\n }\n\n const malformed: string[] = [];\n const named = declared.filter((name) => {\n if (name.length <= MAX_DIMENSION_CHARS && DIMENSION_NAME.test(name)) {\n return true;\n }\n malformed.push(name);\n return false;\n });\n\n if (malformed.length > 0) {\n warn(\n `dropping ${malformed.length} dimension(s) that do not name a field ` +\n `(max ${MAX_DIMENSION_CHARS} characters, starting with a letter or ` +\n `underscore): ${malformed.join(\", \")}`,\n );\n }\n\n const deduped = [...new Set(named)];\n\n if (deduped.length > MAX_DIMENSIONS) {\n warn(\n `dropping ${deduped.length - MAX_DIMENSIONS} dimension(s): at most ` +\n `${MAX_DIMENSIONS} travel. Dropped: ` +\n `${deduped.slice(MAX_DIMENSIONS).join(\", \")}`,\n );\n }\n\n const bounded = deduped.slice(0, MAX_DIMENSIONS);\n return bounded.length > 0 ? bounded : undefined;\n}\n\n/**\n * Read a declared opaque reference string, refusing blanks.\n *\n * `product_id` and `manifest_hash` have no protocol bound to clamp to, but an\n * empty value is not a declaration — the contract is that absent fields are\n * omitted from `info`, never sent empty. The value ships trimmed: these ids\n * exist to be joined against dashboard records by exact string, and padding\n * from a sloppy env var would silently fail that join.\n *\n * @param field - Field name, for the diagnostic\n * @param value - The declared value\n * @param warn - Sink for anything that will not ship\n * @returns The trimmed string, or undefined when absent, blank or unusable\n */\nfunction resolveOpaqueString(\n field: string,\n value: unknown,\n warn: Warn,\n): string | undefined {\n const declared = asString(field, value, warn);\n if (declared === undefined) {\n return undefined;\n }\n const trimmed = declared.trim();\n if (trimmed === \"\") {\n warn(`ignoring empty ${field}`);\n return undefined;\n }\n return trimmed;\n}\n\n/**\n * Build the `extensions` object for one route, declaring `weft.product`.\n *\n * The declaration is emitted only when it would say something — a resolved\n * kind, product id or manifest hash — and each absent field is omitted from\n * `info`, never sent empty. A route that already declares `weft.product` in\n * its own `extensions` keeps its declaration: per-route always wins over the\n * product level, exactly as it does for `serviceName`.\n *\n * @param routeExtensions - The route's own `extensions`, if any\n * @param type - The already-resolved product kind for this route, if any\n * @param declaration - Product-level declaration from the middleware config\n * @param warn - Sink for anything that will not ship\n * @returns The extensions to put on the route, or undefined to leave them alone\n */\nfunction resolveProductExtensions(\n routeExtensions: RouteConfig[\"extensions\"],\n type: WeftProductType | undefined,\n declaration: WeftProductDeclaration,\n warn: Warn,\n): RouteConfig[\"extensions\"] | undefined {\n const productId = resolveOpaqueString(\n \"productId\",\n declaration.productId,\n warn,\n );\n const manifestHash = resolveOpaqueString(\n \"manifestHash\",\n declaration.manifestHash,\n warn,\n );\n\n const info = {\n ...(type !== undefined && { kind: type }),\n ...(productId !== undefined && { product_id: productId }),\n ...(manifestHash !== undefined && { manifest_hash: manifestHash }),\n };\n\n if (Object.keys(info).length === 0) {\n return undefined;\n }\n\n if (routeExtensions !== undefined) {\n if (\n typeof routeExtensions !== \"object\" ||\n routeExtensions === null ||\n Array.isArray(routeExtensions)\n ) {\n // Pass-through contract: what a seller puts in an upstream RouteConfig\n // field is between them and @x402/core, so the junk value stays on the\n // route untouched — the warning must not claim otherwise.\n warn(\n `route extensions ${show(routeExtensions)} are ${typeName(routeExtensions)}, ` +\n `not an object; leaving them untouched and skipping the ` +\n `${WEFT_PRODUCT_EXTENSION_KEY} declaration for this route`,\n );\n return undefined;\n }\n if (WEFT_PRODUCT_EXTENSION_KEY in routeExtensions) {\n return undefined;\n }\n }\n\n return {\n ...routeExtensions,\n [WEFT_PRODUCT_EXTENSION_KEY]: { info, schema: WEFT_PRODUCT_INFO_SCHEMA },\n };\n}\n\n/**\n * Apply product-level identity to a single route.\n *\n * A per-route value always wins over the product-level default. The route's\n * own `type` is consumed here and never forwarded: `RouteConfig` upstream has\n * no such field, and the value's only destination is the reserved tag and the\n * `weft.product` extension's `kind`.\n *\n * @param route - The seller's route configuration\n * @param identity - Product-level declaration from the middleware config\n * @param warn - Sink for anything that will not ship as declared\n * @returns A new route config; the input is never mutated\n */\nfunction applyToRoute(\n route: WeftRouteConfig,\n identity: WeftProductDeclaration,\n warn: Warn,\n): RouteConfig {\n if (typeof route !== \"object\" || route === null) {\n warn(\n `ignoring route ${show(route)}: expected a route config object, got ` +\n `${typeName(route)}`,\n );\n return route;\n }\n\n // Every identity field is destructured *out* of the route rather than merged\n // over: a value this function drops has to leave the route entirely. Spread\n // the route and add the survivors back, and a dropped value rides through on\n // the original object — defeating the drop precisely when it matters, which\n // is when the seller's own value is the one the protocol cannot carry.\n const {\n type: declaredType,\n serviceName: declaredServiceName,\n tags: declaredTags,\n iconUrl: declaredIconUrl,\n ...rest\n } = route;\n\n const type =\n resolveType(declaredType, \"route type\", warn) ??\n resolveType(identity.type, \"type\", warn);\n const serviceName = resolveServiceName(\n declaredServiceName,\n identity.name,\n warn,\n );\n const iconUrl = resolveIconUrl(declaredIconUrl, identity.iconUrl, warn);\n const tags = resolveTags(declaredTags, identity.tags, type, warn);\n const extensions = resolveProductExtensions(\n rest.extensions,\n type,\n identity,\n warn,\n );\n\n return {\n ...rest,\n ...(serviceName !== undefined && { serviceName }),\n ...(tags !== undefined && { tags }),\n ...(iconUrl !== undefined && { iconUrl }),\n ...(extensions !== undefined && { extensions }),\n };\n}\n\n/**\n * Whether any product-level field was actually declared.\n *\n * @param identity - Product-level declaration from the middleware config\n * @returns True when at least one field is set to something other than null\n */\nfunction hasProductIdentity(identity: WeftProductDeclaration): boolean {\n return (\n isDeclared(identity.name) ||\n isDeclared(identity.type) ||\n isDeclared(identity.tags) ||\n isDeclared(identity.iconUrl) ||\n isDeclared(identity.productId) ||\n isDeclared(identity.manifestHash)\n );\n}\n\n/**\n * Whether any route declares a Weft-specific field of its own.\n *\n * Only `type` counts: `serviceName`, `tags` and `iconUrl` are upstream fields\n * a seller could already set before this identity existed, and a config that\n * uses no Weft identity anywhere must still pass through untouched.\n *\n * @param routes - Route configuration passed by the caller\n * @returns True when at least one route declares `type`\n */\nfunction hasRouteIdentity(routes: WeftRoutesConfig): boolean {\n if (isSingleRoute(routes)) {\n return isDeclared(routes.type);\n }\n return Object.values(routes).some((route) => isDeclared(route?.type));\n}\n\n/**\n * Resolve the product-level identity to exactly what the wire will carry.\n *\n * The construction-time facilitator handshake declares the product too, and a\n * dashboard fed from both sources must never see two different products. So\n * the handshake reuses the resolvers the 402 challenge goes through — same\n * clamping, same drops — with one difference: the product type is returned as\n * its own field rather than folded into `tags`, because the handshake payload\n * has a field for it and the challenge does not.\n *\n * Silent by design: `applyProductIdentity` already warns about these same\n * values at construction time, and one warning per problem is enough.\n *\n * @param identity - Product-level identity from the middleware config\n * @returns The identity as it ships, or an empty object when nothing survives\n */\nexport function sanitizeProductIdentity(\n identity: WeftProductIdentity,\n): WeftProductIdentity {\n const silent: Warn = () => undefined;\n\n const type = resolveType(identity.type, \"type\", silent);\n const name = resolveServiceName(undefined, identity.name, silent);\n const iconUrl = resolveIconUrl(undefined, identity.iconUrl, silent);\n const tags = resolveTags(undefined, identity.tags, type, silent)?.filter(\n (tag) => !isReservedTypeTag(tag),\n );\n\n return {\n ...(name !== undefined && { name }),\n ...(type !== undefined && { type }),\n ...(tags !== undefined && tags.length > 0 && { tags }),\n ...(iconUrl !== undefined && { iconUrl }),\n };\n}\n\n/**\n * Merge product-level identity into every protected route.\n *\n * A per-route value always wins over the product-level default, so a seller\n * who names one route individually keeps that name. Fields nobody declared\n * stay absent from the 402 challenge rather than being sent empty.\n *\n * Every value this produces is inside the bounds `ResourceInfoSchema` declares,\n * so the challenge the middleware emits parses for any buyer that validates.\n * Values that cannot be made to fit are clamped or dropped, each with one\n * `[weft]` line at construction time.\n *\n * A config that declares no Weft identity at all — neither on the middleware\n * nor on a route — is returned by reference, exactly as the caller wrote it.\n * That is the pre-identity behaviour, kept deliberately: with nothing of ours\n * on the routes, what the seller puts in a `RouteConfig` is between them and\n * `@x402/core`.\n *\n * @param routes - Route configuration passed by the caller\n * @param identity - Product-level declaration from the middleware config\n * @returns Route configuration with identity applied; the input is never mutated\n */\nexport function applyProductIdentity(\n routes: WeftRoutesConfig,\n identity: WeftProductDeclaration,\n): RoutesConfig {\n if (typeof routes !== \"object\" || routes === null) {\n return routes;\n }\n\n if (!hasProductIdentity(identity) && !hasRouteIdentity(routes)) {\n return routes;\n }\n\n const warn = createWarn();\n\n if (isSingleRoute(routes)) {\n return applyToRoute(routes, identity, warn);\n }\n\n return Object.fromEntries(\n Object.entries(routes).map(([pattern, route]) => [\n pattern,\n applyToRoute(route, identity, warn),\n ]),\n );\n}\n","import { version as SDK_VERSION } from \"../../../package.json\";\nimport {\n createWarn,\n resolveDimensions,\n sanitizeProductIdentity,\n WeftProductDeclaration,\n} from \"./product\";\n\n/**\n * Header that carries the seller's declared product identity on the\n * construction-time `/supported` call.\n *\n * The value is base64url-encoded JSON of\n * `{name, type, tags, icon_url, dimensions}`. The first four are exactly the\n * identity the 402 challenge will carry, so a dashboard fed from the\n * handshake and one fed from settlements agree.\n *\n * `dimensions` is the exception, and travels here *only*. It never touches\n * the challenge, because its whole job is to be the one statement about a\n * payment's metadata that a buyer never had a chance to author: this call is\n * authenticated by the seller's API key, so a field named here is a field the\n * seller vouched for. That is what lets revenue be summed by it.\n *\n * Fields nobody declared are absent from the JSON, and the header itself is\n * absent when nothing was declared at all.\n */\nexport const WEFT_DECLARED_HEADER = \"X-Weft-Declared\";\n\n/** The middleware adapters a handshake can identify itself as. */\nexport type WeftAdapterName = \"express\" | \"hono\";\n\n/**\n * Encode a string as unpadded base64url without assuming a Node runtime.\n *\n * The Hono middleware runs on edge runtimes where `Buffer` may not exist;\n * `TextEncoder` and `btoa` exist everywhere this package supports.\n *\n * @param value - The string to encode\n * @returns The base64url encoding of the string's UTF-8 bytes\n */\nfunction base64UrlEncode(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/**\n * Build the `X-Weft-Declared` value for a product declaration, if any\n * survives.\n *\n * The identity half goes through `sanitizeProductIdentity`, which is silent\n * because `applyProductIdentity` has already warned about the same values.\n * `dimensions` has no such second path — this is the only place it is read —\n * so it is resolved with a warning sink of its own, at boot, once.\n *\n * @param declaration - Product-level declaration from the middleware config\n * @returns The base64url payload, or undefined when nothing was declared\n */\nfunction declaredIdentityValue(\n declaration: WeftProductDeclaration,\n): string | undefined {\n const declared = sanitizeProductIdentity(declaration);\n const dimensions = resolveDimensions(declaration.dimensions, createWarn());\n\n const payload = {\n ...(declared.name !== undefined && { name: declared.name }),\n ...(declared.type !== undefined && { type: declared.type }),\n ...(declared.tags !== undefined && { tags: declared.tags }),\n ...(declared.iconUrl !== undefined && { icon_url: declared.iconUrl }),\n ...(dimensions !== undefined && { dimensions }),\n };\n\n if (Object.keys(payload).length === 0) {\n return undefined;\n }\n return base64UrlEncode(JSON.stringify(payload));\n}\n\n/**\n * Characters that may appear in the `Authorization` value the handshake sends.\n *\n * Printable ASCII excluding space — no real credential contains anything\n * else. The bound exists for log hygiene, not pedantry: a value outside it\n * survives to `fetch`, where undici rejects the header with a `TypeError`\n * that quotes the **entire value**, and upstream `initialize()` prints that\n * error via its own `console.warn` — a live key in the seller's boot output,\n * through a path this SDK cannot intercept. So anything that could trip that\n * error is refused here, before it can become a header.\n */\nconst HEADER_SAFE = /^[\\x21-\\x7e]+$/;\n\n/**\n * Read a declared API key, refusing anything that cannot be a credential.\n *\n * The key's value is never logged — not by the warnings here, which name the\n * field and never quote it, and not by anything downstream, because a value\n * that would make the HTTP layer throw (and echo the key back) never leaves\n * this function.\n *\n * @param apiKey - The declared API key, usually from env at runtime\n * @returns The trimmed key, or undefined when absent or unusable\n */\nfunction resolveApiKey(apiKey: unknown): string | undefined {\n if (apiKey === undefined || apiKey === null) {\n return undefined;\n }\n if (typeof apiKey !== \"string\") {\n console.warn(\n `[weft] ignoring apiKey: expected a string, got ${typeof apiKey}`,\n );\n return undefined;\n }\n const trimmed = apiKey.trim();\n if (trimmed === \"\") {\n console.warn(\"[weft] ignoring empty apiKey\");\n return undefined;\n }\n if (!HEADER_SAFE.test(trimmed)) {\n console.warn(\n \"[weft] ignoring apiKey: it contains whitespace or non-printable \" +\n \"characters that cannot travel in an HTTP header\",\n );\n return undefined;\n }\n return trimmed;\n}\n\n/**\n * Header the Weft facilitator reads the seller's API key from on `/settle`\n * and `/verify`.\n *\n * The facilitator's `/settle` handler validates this header and returns 401\n * without it, so a seller who sets `apiKey` and nothing else must have it\n * here or every settlement — the step that credits their wallet — fails.\n * `/verify` does not require the key, but the facilitator reads it when\n * present and stamps the verification event with the key's digest; the SDK\n * sends it there too so the seller's funnel attributes verification attempts\n * instead of counting settlements against zero. `/supported` carries the same\n * key as a bearer for the handshake, so one key travels under two header names\n * by the facilitator's own design, not the SDK's whim.\n */\nexport const WEFT_API_KEY_HEADER = \"X-API-Key\";\n\n/**\n * Auth headers the SDK derives from `apiKey`, keyed by the facilitator path\n * each belongs to — the shape `@x402/core`'s `createAuthHeaders` expects.\n *\n * `supported` always carries at least a `User-Agent`. `settle` and `verify`\n * are present only when a usable key was configured — they carry the same\n * `X-API-Key`, so the facilitator credits the wallet on `/settle` and\n * attributes the verification funnel on `/verify` from one credential. An\n * empty `X-API-Key` is a failed settlement dressed up as a configured one, so\n * neither is present without a usable key.\n */\nexport interface WeftFacilitatorAuthHeaders {\n supported: Record<string, string>;\n settle?: Record<string, string>;\n verify?: Record<string, string>;\n}\n\n/**\n * Build the auth headers the SDK adds to the facilitator calls it drives.\n *\n * Total by design: this runs in a payment server's boot path, so no input —\n * junk key, junk identity — may ever make it throw. Anything unusable is\n * dropped with a warning and the calls go out without it.\n *\n * The key is validated once here and reused across every path, so a\n * malformed key warns a single time and reaches none of the `/supported`\n * bearer, the `/settle` `X-API-Key`, or the `/verify` `X-API-Key`.\n *\n * @param adapter - Which middleware adapter is calling home\n * @param apiKey - The seller's Weft API key, when configured\n * @param declaration - Product-level declaration from the middleware config\n * @returns Per-path auth headers for the facilitator calls\n */\nexport function buildFacilitatorAuthHeaders(\n adapter: WeftAdapterName,\n apiKey: unknown,\n declaration: WeftProductDeclaration,\n): WeftFacilitatorAuthHeaders {\n const key = resolveApiKey(apiKey);\n\n const supported: Record<string, string> = {\n \"User-Agent\": `weft-sdk-${adapter}/${SDK_VERSION}`,\n };\n if (key !== undefined) {\n supported[\"Authorization\"] = `Bearer ${key}`;\n }\n\n const declared = declaredIdentityValue(declaration);\n if (declared !== undefined) {\n supported[WEFT_DECLARED_HEADER] = declared;\n }\n\n const settle = key !== undefined ? { [WEFT_API_KEY_HEADER]: key } : undefined;\n const verify = key !== undefined ? { [WEFT_API_KEY_HEADER]: key } : undefined;\n\n return {\n supported,\n ...(settle !== undefined && { settle }),\n ...(verify !== undefined && { verify }),\n };\n}\n","import type { HTTPRequestContext, x402ResourceServer } from \"@x402/core/server\";\nimport type {\n PaymentRequiredContext,\n ResourceServerExtension,\n} from \"@x402/core/types\";\nimport { createWarn, type Warn } from \"./product\";\nimport type { WeftRouteConfig, WeftRoutesConfig } from \"./product\";\n\n/**\n * A route extension whose value is computed per request.\n *\n * Declared in place of a static value under a key of a route's `extensions`,\n * and evaluated at the same point as the `price` callback — while the 402\n * challenge is being built, with the same {@link HTTPRequestContext}. The\n * resolved value ships on the challenge, the buyer's client echoes it onto the\n * payment payload, and the facilitator relays it onto the settlement event, so\n * a seller who prices from the request body can also say what that body asked\n * for:\n *\n * ```ts\n * {\n * accepts: [{ scheme, network, payTo, price: quote }],\n * extensions: {\n * [WEFT_REQUEST_EXTENSION_KEY]: async (context) => {\n * const { model, max_tokens } = (await context.adapter.getBody()) as Body;\n * return { model, max_tokens };\n * },\n * },\n * }\n * ```\n *\n * {@link WEFT_REQUEST_EXTENSION_KEY} is the key to reach for. Under it the SDK\n * owns the envelope: the callback returns the `info` payload alone and the\n * published {@link WEFT_REQUEST_INFO_SCHEMA} is stamped beside it, exactly as\n * `weft.product` is assembled from declared fields. Under any other key the\n * resolved value ships verbatim, envelope and all — the escape hatch for a\n * seller who needs their own namespace on the wire.\n *\n * Two rules the callback has to hold to.\n *\n * **It must be deterministic for one request.** The challenge is built twice —\n * once for the unpaid request, once for the buyer's paid retry — and upstream\n * rejects the payment with `extension_echo_mismatch` when what the buyer\n * echoes no longer matches what the retry advertises. Derive the value from\n * the request; never from a clock, a counter or a random source.\n *\n * **It is display-only.** By the time the value reaches a consumer it is\n * unauthenticated buyer input, exactly like every other echoed extension.\n * Attribution stays keyed on the authenticated API key that settled the\n * payment, never on anything in here.\n *\n * The value travels as JSON and is advertised as JSON round-trips it, so a\n * `NaN` arrives as `null` and a function-valued field does not arrive at all.\n * Return plain JSON data and the question never comes up.\n */\nexport type WeftDynamicExtension = (\n context: HTTPRequestContext,\n) => unknown | Promise<unknown>;\n\n/**\n * Extension key for the seller's per-request context.\n *\n * The one *named* key this mechanism ships, and the one to use unless a\n * seller needs their own namespace on the wire. x402 extensions are named\n * capabilities with published contracts — discovery, receipts, gas sponsoring\n * — registered and reviewed rather than invented per seller. A key that any\n * seller may invent is a metadata channel wearing an extension's clothes, so\n * the SDK publishes one key with one contract and leaves the free-form form\n * as the deliberate exception.\n *\n * Sits beside {@link WEFT_PRODUCT_EXTENSION_KEY}, and divides cleanly from it:\n * `weft.product` says what is being sold and is fixed at boot; `weft.request`\n * says what this one call asked for and is resolved per request.\n */\nexport const WEFT_REQUEST_EXTENSION_KEY = \"weft.request\";\n\n/**\n * JSON Schema (Draft 2020-12) for the `weft.request` extension's `info`.\n *\n * Ships verbatim as the extension's `schema` member. Deliberately open where\n * `WEFT_PRODUCT_INFO_SCHEMA` is closed: what a request asked for is the\n * seller's vocabulary — `{model, max_tokens}` for one rail, `{pages}` for\n * another — and no schema Weft could author would fit them all.\n *\n * The contract it publishes is therefore not a field list but a posture: this\n * key holds seller-authored, display-only context for one request, and a\n * consumer must key nothing on it. `additionalProperties: true` states that\n * openness rather than leaving it to be inferred from an absent constraint.\n */\nexport const WEFT_REQUEST_INFO_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"Weft per-request context\",\n description:\n \"Seller-authored context for one paid request, for display only. \" +\n \"Unauthenticated buyer input by the time it is read; key nothing on it.\",\n type: \"object\",\n additionalProperties: true,\n} as const;\n\n/**\n * Largest serialized extensions object, in bytes, the SDK will put on a\n * challenge.\n *\n * Mirrors the facilitator's own `MAX_EXTENSIONS_BYTES` relay cap, and is\n * measured the same way: on the whole object, key names included. The\n * facilitator omits *every* extension when the object is over — `weft.product`\n * with it — so a resolved value that would take the object past the cap is\n * dropped here, on its own key, where the rest of the declaration survives.\n *\n * Keep these blobs small. They describe a request; they are not a place to\n * store one.\n */\nexport const MAX_EXTENSION_BYTES = 16 * 1024;\n\n/**\n * Recover the HTTP request from the enrichment context.\n *\n * `transportContext` is `unknown` upstream because the resource server is not\n * HTTP-only; the HTTP path always passes `{request}`.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @returns The request context, or undefined off the HTTP transport\n */\nfunction requestOf(\n context: PaymentRequiredContext,\n): HTTPRequestContext | undefined {\n const transport = context.transportContext as\n { request?: HTTPRequestContext } | undefined;\n return transport?.request;\n}\n\n/**\n * Drop a key that resolved to nothing shippable.\n *\n * Returning `undefined` from the hook means \"no change\", which would leave the\n * callback *itself* on the challenge — `JSON.stringify` drops a function-valued\n * key, so nothing malformed reaches the wire either way, but the key is removed\n * here so the in-process challenge says the same thing the buyer sees.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @param key - The extension key to remove\n * @returns Always undefined, so the hook makes no assignment of its own\n */\nfunction dropKey(context: PaymentRequiredContext, key: string): undefined {\n delete context.paymentRequiredResponse.extensions?.[key];\n return undefined;\n}\n\n/**\n * Serialize a value to JSON, or undefined when JSON cannot carry it.\n *\n * @param value - The value to serialize\n * @returns The JSON text, or undefined for a circular, BigInt or unserializable value\n */\nfunction toJson(value: unknown): string | undefined {\n try {\n return JSON.stringify(value);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Byte length of a string as UTF-8 — what the facilitator's cap counts.\n *\n * @param text - The serialized JSON\n * @returns The length in bytes\n */\nfunction byteLength(text: string): number {\n return new TextEncoder().encode(text).length;\n}\n\n/**\n * Size of the whole extensions object once this key holds this value.\n *\n * The facilitator's cap is on the *serialized map*, not on one value: a blob\n * that fits on its own can still push the object past the cap once its key\n * name and `weft.product` are counted, and the facilitator then omits every\n * extension rather than the offender. So the projection is what gets measured.\n *\n * Still an approximation in one direction: keys resolved later in the same\n * challenge are unresolved callbacks here, which serialize to nothing. Each\n * one measures against everything already accepted, so the estimate only\n * improves as the map fills.\n *\n * @param context - Payment-required enrichment context from `@x402/core`\n * @param key - The extension key about to be written\n * @param value - The wire value that key would hold\n * @returns The projected size in bytes, or undefined when the map will not serialize\n */\nfunction projectedBytes(\n context: PaymentRequiredContext,\n key: string,\n value: unknown,\n): number | undefined {\n const projected = {\n ...context.paymentRequiredResponse.extensions,\n [key]: value,\n };\n const json = toJson(projected);\n return json === undefined ? undefined : byteLength(json);\n}\n\n/**\n * Build the resource-server extension that resolves one dynamic key.\n *\n * Registered once per key, not per route: the route's own declaration arrives\n * as the hook's `declaration` argument, so two routes may declare the same key\n * with different callbacks. A route that declares the key statically is left\n * alone — only a function is resolved.\n *\n * Nothing here throws. A callback that fails costs the seller the blob, never\n * the payment: the key is dropped and the challenge ships without it.\n *\n * @param key - The extension key this hook resolves\n * @param warn - Sink for anything that will not ship\n * @returns An extension to register on the resource server\n */\nfunction dynamicExtension(key: string, warn: Warn): ResourceServerExtension {\n return {\n key,\n async enrichPaymentRequiredResponse(declaration, context) {\n if (typeof declaration !== \"function\") {\n return undefined;\n }\n\n const request = requestOf(context);\n if (!request) {\n warn(\n `extensions[${key}] is a callback but no HTTP request context ` +\n `reached it; dropping the key from the challenge`,\n `${key}:no-request`,\n );\n return dropKey(context, key);\n }\n\n let resolved: unknown;\n try {\n resolved = await (declaration as WeftDynamicExtension)(request);\n } catch (error) {\n warn(\n `extensions[${key}] callback failed; dropping the key from the ` +\n `challenge: ` +\n (error instanceof Error ? error.message : String(error)),\n `${key}:threw`,\n );\n return dropKey(context, key);\n }\n\n // A callback that returns nothing is opting out for this request — a\n // route that only stamps some requests should not have to warn about\n // the rest.\n if (resolved === undefined || resolved === null) {\n return dropKey(context, key);\n }\n\n const json = toJson(resolved);\n if (json === undefined) {\n warn(\n `extensions[${key}] callback returned a value JSON cannot carry (a ` +\n `function, a circular reference, a BigInt or similar); dropping ` +\n `the key from the challenge`,\n `${key}:unserializable`,\n );\n return dropKey(context, key);\n }\n\n // Advertise the round trip, never the original. `JSON.stringify`\n // normalizes — NaN and Infinity become null, functions and symbols\n // vanish — and the paid retry's echo check compares what this hook\n // advertised against the buyer's JSON-decoded copy. Advertising the\n // un-normalized original makes those two disagree and costs the seller\n // the payment, which is the one thing this path must never do.\n const wire: unknown = JSON.parse(json);\n\n // Checked after the round trip, so a `toJSON` that returns something\n // else is caught alongside a callback that returned it directly.\n if (typeof wire !== \"object\" || wire === null || Array.isArray(wire)) {\n warn(\n `extensions[${key}] callback returned ${Array.isArray(wire) ? \"an array\" : `a ${typeof wire}`}; ` +\n `the x402 extensions channel carries objects, so the key is ` +\n `dropped from the challenge`,\n `${key}:not-an-object`,\n );\n return dropKey(context, key);\n }\n\n // The named key owns its envelope: the callback returns `info` alone\n // and the published schema is stamped beside it, the same assembly\n // `weft.product` goes through. Wrapped before measuring, so the cap\n // counts what actually ships. Any other key ships the resolved value\n // exactly as the seller built it.\n const value =\n key === WEFT_REQUEST_EXTENSION_KEY\n ? { info: wire, schema: WEFT_REQUEST_INFO_SCHEMA }\n : wire;\n\n const bytes = projectedBytes(context, key, value) ?? byteLength(json);\n if (bytes > MAX_EXTENSION_BYTES) {\n warn(\n `extensions[${key}] takes the challenge's extensions to ${bytes} ` +\n `bytes, over the ${MAX_EXTENSION_BYTES}-byte facilitator relay ` +\n `cap; dropping the key so the rest of the declaration still ` +\n `reaches settlement`,\n `${key}:over-cap`,\n );\n return dropKey(context, key);\n }\n\n return value;\n },\n };\n}\n\n/**\n * The route configs in a `RoutesConfig`, in either of its two shapes.\n *\n * @param routes - Route configuration passed by the caller\n * @returns Every route config, ignoring anything that is not one\n */\nfunction routeConfigs(routes: WeftRoutesConfig): WeftRouteConfig[] {\n if (typeof routes !== \"object\" || routes === null) {\n return [];\n }\n const configs = \"accepts\" in routes ? [routes] : Object.values(routes);\n return configs.filter(\n (config): config is WeftRouteConfig =>\n typeof config === \"object\" && config !== null,\n );\n}\n\n/**\n * Every extension key declared as a callback by at least one route.\n *\n * @param routes - Route configuration passed by the caller\n * @returns The distinct keys needing per-request resolution\n */\nfunction dynamicExtensionKeys(routes: WeftRoutesConfig): string[] {\n const keys = new Set<string>();\n for (const config of routeConfigs(routes)) {\n const extensions = config.extensions;\n if (typeof extensions !== \"object\" || extensions === null) {\n continue;\n }\n for (const [key, value] of Object.entries(extensions)) {\n if (typeof value === \"function\") {\n keys.add(key);\n }\n }\n }\n return [...keys];\n}\n\n/**\n * Teach a resource server to resolve the routes' {@link WeftDynamicExtension}\n * callbacks.\n *\n * Upstream reads `routeConfig.extensions` straight off the shared, long-lived\n * route config, so a per-request value cannot be written there without racing\n * every concurrent request. `registerExtension` is the path that *is* request\n * scoped: the enrichment hook runs while the challenge for one request is\n * being built, and its return value replaces that request's copy of the key —\n * which is the same object the verify and settle steps go on to see.\n *\n * A config with no callbacks registers nothing at all.\n *\n * @param server - The resource server the middleware is building on\n * @param routes - Route configuration passed by the caller\n */\nexport function registerDynamicExtensions(\n server: x402ResourceServer,\n routes: WeftRoutesConfig,\n): void {\n const keys = dynamicExtensionKeys(routes);\n if (keys.length === 0) {\n return;\n }\n\n const warn = createWarn();\n\n // The peer range is `^2.0.0` and per-key enrichment arrived mid-2.x. On an\n // older build the callback stays a function, which JSON drops: the seller\n // loses the blob, not the payment — but silently, so say it once at boot.\n if (typeof server.registerExtension !== \"function\") {\n warn(\n `this @x402/core build has no registerExtension, so per-request route ` +\n `extensions (${keys.join(\", \")}) cannot be resolved and will not ship`,\n );\n return;\n }\n\n for (const key of keys) {\n server.registerExtension(dynamicExtension(key, warn));\n }\n}\n","import type {\n CompletedSettlement,\n HTTPRequestContext,\n PaymentCancellationDispatcher,\n x402ResourceServer,\n} from \"@x402/core/server\";\nimport { decodePaymentSignatureHeader } from \"@x402/core/http\";\nimport { validatePaymentPayload } from \"@x402/core/schemas\";\nimport type { PaymentPayload, PaymentRequirements } from \"@x402/core/types\";\n\n/** A structurally valid, but not cryptographically verified, v2 payment. */\nexport interface PaymentResumeCandidate {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n}\n\n/** Verified payment inputs restored from durable application storage. */\nexport interface VerifiedPaymentResume {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n declaredExtensions?: Record<string, unknown>;\n /** Restore this receipt when Core settled before the original handler. */\n beforeHandlerSettlement?: CompletedSettlement;\n /** Restore Core's cancellation state for a before-handler settlement. */\n cancellationDispatcher?: PaymentCancellationDispatcher;\n}\n\n/**\n * Restore a previously verified payment for settlement replay.\n *\n * This callback is a trust boundary. The caller must durably bind its result to\n * the exact signed payment payload and request fingerprint. The SDK does not\n * authenticate or validate callback output before settlement.\n */\nexport type ResumeVerifiedPayment = (\n context: HTTPRequestContext,\n candidate: PaymentResumeCandidate,\n) =>\n | VerifiedPaymentResume\n | undefined\n | Promise<VerifiedPaymentResume | undefined>;\n\n/**\n * Decode the generic v2 envelope before it crosses the application replay\n * trust boundary. Scheme validation and signature verification stay with Core\n * and the registered scheme implementation.\n */\nexport function paymentResumeCandidate(\n context: HTTPRequestContext,\n): PaymentResumeCandidate | undefined {\n if (!context.paymentHeader) return undefined;\n\n try {\n const paymentPayload = decodePaymentSignatureHeader(context.paymentHeader);\n validatePaymentPayload(paymentPayload);\n if (paymentPayload.x402Version !== 2) return undefined;\n\n return {\n paymentPayload,\n paymentRequirements: paymentPayload.accepted,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function resumePaymentResult(\n resourceServer: x402ResourceServer,\n resumed: VerifiedPaymentResume,\n context: HTTPRequestContext,\n) {\n return {\n type: \"payment-verified\" as const,\n paymentPayload: resumed.paymentPayload,\n paymentRequirements: resumed.paymentRequirements,\n declaredExtensions: resumed.declaredExtensions,\n beforeHandlerSettlement: resumed.beforeHandlerSettlement,\n cancellationDispatcher:\n resumed.cancellationDispatcher ??\n resourceServer.createPaymentCancellationDispatcher(\n resumed.paymentPayload,\n resumed.paymentRequirements,\n resumed.declaredExtensions,\n { request: context },\n resumed.beforeHandlerSettlement ? [\"before-handler\"] : [],\n ),\n };\n}\n","import { x402HTTPResourceServer } from \"@x402/core/server\";\nimport { decodePaymentResponseHeader } from \"@x402/core/http\";\nimport { FACILITATOR_UNAVAILABLE_ERROR } from \"../client\";\n\nconst CORE_FACILITATOR_UNAVAILABLE =\n /^Facilitator settle failed \\(503\\):(?: |$)/;\n\n/**\n * The Weft client marks structured 503s before Core drops their status. Match\n * Core's exact prefix only as a fallback for unstructured 503 responses.\n */\nexport function isFacilitatorUnavailable(errorReason?: string): boolean {\n return (\n errorReason === FACILITATOR_UNAVAILABLE_ERROR ||\n CORE_FACILITATOR_UNAVAILABLE.test(errorReason ?? \"\")\n );\n}\n\ninterface CoreResponseInstructions {\n body?: unknown;\n headers: Record<string, string | string[]>;\n}\n\nfunction responseHeader(\n headers: CoreResponseInstructions[\"headers\"],\n name: string,\n): string | undefined {\n const value = Object.entries(headers).find(\n ([key]) => key.toLowerCase() === name,\n )?.[1];\n return Array.isArray(value) ? value[0] : value;\n}\n\nexport function isFacilitatorUnavailableResponse(\n response: CoreResponseInstructions,\n): boolean {\n if (typeof response.body === \"object\" && response.body !== null) {\n for (const field of [\"errorReason\", \"error\"]) {\n if (\n field in response.body &&\n typeof response.body[field as keyof typeof response.body] ===\n \"string\" &&\n isFacilitatorUnavailable(\n response.body[field as keyof typeof response.body] as string,\n )\n ) {\n return true;\n }\n }\n }\n\n const paymentResponse = responseHeader(response.headers, \"payment-response\");\n if (!paymentResponse) return false;\n try {\n return isFacilitatorUnavailable(\n decodePaymentResponseHeader(paymentResponse).errorReason,\n );\n } catch {\n return false;\n }\n}\n\nexport function isJsonResponse(response: CoreResponseInstructions): boolean {\n const contentType = responseHeader(response.headers, \"content-type\");\n return /^(application\\/json|[^;]+\\+json)(?:;|$)/i.test(contentType ?? \"\");\n}\n\nexport function serializeResponseBody(\n response: CoreResponseInstructions,\n): BodyInit {\n if (isJsonResponse(response)) return JSON.stringify(response.body ?? {});\n if (\n response.body instanceof Blob ||\n response.body instanceof ArrayBuffer ||\n ArrayBuffer.isView(response.body)\n ) {\n return response.body as BodyInit;\n }\n return typeof response.body === \"string\"\n ? response.body\n : String(response.body ?? \"\");\n}\n\n/** Observe the seller method at both before-handler and after-handler settlement. */\nexport class WeftHTTPResourceServer extends x402HTTPResourceServer {\n override processSettlement(\n ...args: Parameters<x402HTTPResourceServer[\"processSettlement\"]>\n ) {\n const request = args[3]?.request;\n const method = request?.method ?? request?.adapter.getMethod();\n if (method) {\n const payload = { ...args[0], httpMethod: method.toUpperCase() };\n args[0] = payload;\n }\n return super.processSettlement(...args);\n }\n}\n","import {\n HTTPRequestContext,\n PaywallConfig,\n PaywallProvider,\n SETTLEMENT_OVERRIDES_HEADER,\n withPrivateCacheControl,\n x402ResourceServer,\n HTTPAdapter,\n} from \"@x402/core/server\";\nimport { SchemeNetworkServer, Network } from \"@x402/core/types\";\nimport { createFacilitatorClient, WeftFacilitatorConfig } from \"../client\";\nimport { buildFacilitatorAuthHeaders } from \"./handshake\";\nimport {\n applyProductIdentity,\n WeftProductDeclaration,\n WeftRoutesConfig,\n} from \"./product\";\nimport { registerDynamicExtensions } from \"./extensions\";\nimport {\n paymentResumeCandidate,\n resumePaymentResult,\n type ResumeVerifiedPayment,\n} from \"./replay\";\nimport {\n WeftHTTPResourceServer,\n isFacilitatorUnavailable,\n isFacilitatorUnavailableResponse,\n isJsonResponse,\n serializeResponseBody,\n} from \"./settlement\";\n\ninterface HonoRequest {\n method: string;\n path: string;\n url: string;\n header(name: string): string | undefined;\n query(): Record<string, string>;\n query(name: string): string | undefined;\n json(): Promise<unknown>;\n}\n\ninterface HonoContext {\n req: HonoRequest;\n res: Response | undefined;\n error?: Error;\n header(\n name: string,\n value: string | undefined,\n options?: { append?: boolean },\n ): void;\n html(body: string, status?: number): Response;\n json(body: unknown, status?: number): Response;\n}\n\nexport type HonoMiddleware = (\n c: HonoContext,\n next: () => Promise<void>,\n) => Promise<Response | void>;\n\n/**\n * Floor between background facilitator re-sync attempts.\n *\n * Without it, a sustained facilitator outage on a busy server couples retry\n * (and warn) volume to request rate: a refused connection settles in\n * milliseconds, so every protected request would launch a fresh `/supported`\n * call for the whole outage. One attempt per floor interval bounds both.\n */\nconst FACILITATOR_SYNC_RETRY_FLOOR_MS = 30_000;\n\nexport interface SchemeRegistration {\n network: Network;\n server: SchemeNetworkServer;\n}\n\n/**\n * Configuration for the Hono payment middleware.\n *\n * Extends {@link WeftProductDeclaration}, so `name`, `type`, `tags`,\n * `iconUrl`, `productId` and `manifestHash` are declared once here and\n * applied to every protected route.\n */\nexport interface WeftHonoMiddlewareConfig extends WeftProductDeclaration {\n /**\n * The seller's Weft API key.\n *\n * Authenticates the facilitator calls that need it: `X-API-Key` on\n * `/settle` — which the facilitator requires, or every settlement 401s —\n * and `Authorization: Bearer <key>` on the construction-time `/supported`\n * handshake, which is how the dashboard learns an SDK is deployed before\n * any payment. Optional, but a seller who omits it must supply their own\n * `facilitator.createAuthHeaders` or settlement fails.\n */\n apiKey?: string;\n facilitator?: WeftFacilitatorConfig;\n schemes?: SchemeRegistration[];\n paywallConfig?: PaywallConfig;\n paywall?: PaywallProvider;\n syncFacilitatorOnStart?: boolean;\n /** Restore durably bound verified inputs for settlement replay. */\n resumeVerifiedPayment?: ResumeVerifiedPayment;\n}\n\nclass HonoAdapter implements HTTPAdapter {\n constructor(private c: HonoContext) {}\n\n getHeader(name: string): string | undefined {\n return this.c.req.header(name);\n }\n\n getMethod(): string {\n return this.c.req.method;\n }\n\n getPath(): string {\n return this.c.req.path;\n }\n\n getUrl(): string {\n return this.c.req.url;\n }\n\n getAcceptHeader(): string {\n return this.c.req.header(\"Accept\") || \"\";\n }\n\n getUserAgent(): string {\n return this.c.req.header(\"User-Agent\") || \"\";\n }\n\n getQueryParams(): Record<string, string | string[]> {\n const query = this.c.req.query();\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(query)) {\n result[key] = value;\n }\n return result;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.c.req.query(name);\n }\n\n async getBody(): Promise<unknown> {\n try {\n return await this.c.req.json();\n } catch {\n return undefined;\n }\n }\n}\n\n/**\n * Flatten a `Headers` instance into the plain record `HTTPTransportContext`\n * expects. Header names are already lowercased by `Headers`; the settlement\n * override lookup in `@x402/core` compares case-insensitively either way.\n *\n * @param headers - Response headers set by the route handler, if any\n * @returns A plain record, or undefined when there is no response yet\n */\nfunction toHeaderRecord(\n headers: Headers | undefined,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n}\n\n/**\n * Rebuild a Fetch response with additional headers. Responses returned by\n * `fetch()` and `Response.redirect()` have immutable header guards.\n *\n * @param response - The route handler response\n * @param additions - Headers to add to the outgoing response\n * @returns The original response when there are no additions, otherwise a rebuilt response\n */\nfunction withResponseHeaders(\n response: Response,\n additions: Record<string, string> | undefined,\n): Response {\n if (\n (!additions || Object.keys(additions).length === 0) &&\n !response.headers.has(SETTLEMENT_OVERRIDES_HEADER)\n )\n return response;\n const headers = new Headers(response.headers);\n Object.entries(additions ?? {}).forEach(([key, value]) => {\n headers.set(key, value);\n });\n headers.delete(SETTLEMENT_OVERRIDES_HEADER);\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction withSuccessfulSettlementHeaders(\n response: Response,\n additions: Record<string, string>,\n): Response {\n const headers = new Headers(response.headers);\n Object.entries(additions).forEach(([key, value]) => {\n headers.set(key, value);\n });\n headers.delete(SETTLEMENT_OVERRIDES_HEADER);\n headers.set(\n \"cache-control\",\n withPrivateCacheControl(headers.get(\"cache-control\")),\n );\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction failureResponse(\n body: unknown,\n status: number,\n headers: Record<string, string | string[]>,\n): Response {\n const responseHeaders = new Headers();\n for (const [name, value] of Object.entries(headers)) {\n const values = Array.isArray(value) ? value : [value];\n for (const item of values) responseHeaders.append(name, item);\n }\n return new Response(serializeResponseBody({ body, headers }), {\n status,\n headers: responseHeaders,\n });\n}\n\nfunction facilitatorUnavailableResponse(): Response {\n return failureResponse({ error: \"facilitator_unavailable\" }, 503, {\n \"retry-after\": \"1\",\n \"cache-control\": withPrivateCacheControl(null),\n \"content-type\": \"application/json; charset=UTF-8\",\n });\n}\n\nfunction replaceContextResponse(c: HonoContext, response: Response): void {\n for (const name of [...(c.res?.headers.keys() ?? [])]) {\n c.header(name, undefined);\n }\n c.res = response;\n}\n\n/**\n * Create a Hono middleware that requires x402 payment for the given routes.\n *\n * Product identity declared on `config` (`name`, `type`, `tags`, `iconUrl`) is\n * merged into every route, so it travels on the 402 challenge's `resource` and\n * from there onto the buyer's payment payload and the settlement event.\n *\n * @param routes - Route configuration, either a path map or a single route;\n * each route may declare its own `type` to override the product's\n * @param config - Facilitator, scheme, paywall and product identity settings\n * @returns A Hono middleware function\n */\nexport function weftPaymentMiddlewareHono(\n routes: WeftRoutesConfig,\n config?: WeftHonoMiddlewareConfig,\n): HonoMiddleware {\n const facilitatorClient = createFacilitatorClient(\n config?.facilitator,\n buildFacilitatorAuthHeaders(\"hono\", config?.apiKey, config ?? {}),\n );\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerDynamicExtensions(resourceServer, routes);\n\n if (config?.schemes) {\n config.schemes.forEach(({ network, server: schemeServer }) => {\n resourceServer.register(network, schemeServer);\n });\n }\n\n const httpServer = new WeftHTTPResourceServer(\n resourceServer,\n applyProductIdentity(routes, config ?? {}),\n );\n\n if (config?.paywall) {\n httpServer.registerPaywallProvider(config.paywall);\n }\n\n // The construction-time facilitator sync doubles as the identity handshake,\n // so its failure modes are held to handshake rules: it must never crash the\n // process (a rejection with no handler attached would, under Node's default\n // unhandled-rejection policy) and must never brick the middleware. The\n // returned promise therefore cannot reject, and a failed sync is retried in\n // the background off later protected requests until one attempt succeeds.\n // A request the sync still cannot serve rejects into Hono's own onError.\n const syncOnStart = config?.syncFacilitatorOnStart ?? true;\n let facilitatorSynced = false;\n let syncInFlight: Promise<void> | null = null;\n let lastFailedSyncAt = 0;\n\n const syncFacilitator = (): Promise<void> => {\n syncInFlight ??= httpServer\n .initialize()\n .then(\n () => {\n facilitatorSynced = true;\n },\n (error: unknown) => {\n lastFailedSyncAt = Date.now();\n console.warn(\n \"[weft] facilitator sync failed; payment-protected routes \" +\n \"degrade until a later attempt succeeds: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n },\n )\n .finally(() => {\n syncInFlight = null;\n });\n return syncInFlight;\n };\n\n let bootSync: Promise<void> | null = syncOnStart ? syncFacilitator() : null;\n\n return async (c: HonoContext, next: () => Promise<void>) => {\n const adapter = new HonoAdapter(c);\n const context: HTTPRequestContext = {\n adapter,\n path: c.req.path,\n method: c.req.method,\n paymentHeader:\n adapter.getHeader(\"payment-signature\") ||\n adapter.getHeader(\"x-payment\"),\n };\n\n if (!httpServer.requiresPayment(context)) {\n return next();\n }\n\n if (bootSync) {\n // The pre-existing first-request barrier: with a healthy facilitator\n // this resolves once and never runs again. It cannot throw.\n await bootSync;\n bootSync = null;\n }\n if (\n syncOnStart &&\n !facilitatorSynced &&\n Date.now() - lastFailedSyncAt >= FACILITATOR_SYNC_RETRY_FLOOR_MS\n ) {\n // Heal a failed boot sync without delaying anyone: the retry is kicked\n // fire-and-forget (one in flight at most, one attempt per floor\n // interval) and this request proceeds.\n void syncFacilitator();\n }\n\n const resumeCandidate = paymentResumeCandidate(context);\n const resumedPayment = resumeCandidate\n ? await config?.resumeVerifiedPayment?.(context, resumeCandidate)\n : undefined;\n const result = resumedPayment\n ? resumePaymentResult(resourceServer, resumedPayment, context)\n : await httpServer.processHTTPRequest(context, config?.paywallConfig);\n\n switch (result.type) {\n case \"no-payment-required\":\n return next();\n\n case \"payment-error\": {\n const { response } = result;\n if (isFacilitatorUnavailableResponse(response)) {\n return facilitatorUnavailableResponse();\n }\n if (!response.isHtml && !isJsonResponse(response)) {\n return failureResponse(\n response.body,\n response.status,\n response.headers,\n );\n }\n Object.entries(response.headers).forEach(([key, value]) => {\n c.header(key, value as string);\n });\n if (response.isHtml) {\n return c.html(response.body as string, response.status as 402);\n }\n return c.json(response.body || {}, response.status as 402);\n }\n\n case \"payment-verified\": {\n const {\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n cancellationDispatcher,\n beforeHandlerSettlement,\n } = result;\n\n const propagateHandlerError = async (\n error: unknown,\n ): Promise<never> => {\n replaceContextResponse(c, new Response());\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_threw\",\n error,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n );\n Object.entries(headers ?? {}).forEach(([key, value]) => {\n c.header(key, value);\n });\n throw error;\n };\n\n const originalHeader = c.header;\n const handlerHeaders = new Set<string>();\n const errorHeaders = new Set<string>();\n c.header = (name, value, options) => {\n (c.error ? errorHeaders : handlerHeaders).add(name.toLowerCase());\n originalHeader.call(c, name, value, options);\n };\n try {\n await next();\n } catch (error) {\n c.header = originalHeader;\n await propagateHandlerError(error);\n }\n c.header = originalHeader;\n if (c.error) {\n const res = c.res ?? new Response();\n const responseHeaders = new Headers(res.headers);\n for (const name of handlerHeaders) {\n if (!errorHeaders.has(name)) responseHeaders.delete(name);\n }\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_threw\",\n error: c.error,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n responseHeaders.get(\"cache-control\"),\n );\n const sanitizedResponse = new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers: responseHeaders,\n });\n replaceContextResponse(\n c,\n withResponseHeaders(sanitizedResponse, headers),\n );\n return;\n }\n\n let res = c.res;\n\n if (res && res.status >= 400) {\n const cancelSettlement = await cancellationDispatcher.cancel({\n reason: \"handler_failed\",\n responseStatus: res.status,\n });\n const headers = httpServer.createFailurePathSettlementHeaders(\n cancelSettlement,\n beforeHandlerSettlement,\n paymentPayload,\n res.headers.get(\"cache-control\"),\n );\n replaceContextResponse(c, withResponseHeaders(res, headers));\n return;\n }\n\n let settleResult;\n try {\n settleResult = await httpServer.processSettlement(\n paymentPayload,\n paymentRequirements,\n declaredExtensions,\n // The route handler signals a settlement override (a metered amount\n // below the signed maximum) through a response header.\n // `processSettlement` only reads that off `transportContext`, so\n // omitting this settles the full authorised amount and makes\n // `upto` behave exactly like `exact`.\n {\n request: context,\n responseBody: res\n ? Buffer.from(await res.clone().arrayBuffer())\n : undefined,\n responseHeaders: toHeaderRecord(res?.headers),\n },\n undefined,\n beforeHandlerSettlement,\n );\n } catch (error) {\n replaceContextResponse(c, new Response());\n throw error;\n }\n\n if (!settleResult.success) {\n if (isFacilitatorUnavailable(settleResult.errorReason)) {\n replaceContextResponse(c, facilitatorUnavailableResponse());\n return;\n }\n const { response } = settleResult;\n replaceContextResponse(\n c,\n failureResponse(response.body, response.status, response.headers),\n );\n return;\n } else if (res) {\n res = withSuccessfulSettlementHeaders(res, settleResult.headers);\n }\n\n if (res) replaceContextResponse(c, res);\n return;\n }\n }\n };\n}\n"],"mappings":"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","names":["result","SETTLEMENT_OVERRIDES_HEADER","withPrivateCacheControl","x402ResourceServer","FACILITATOR_SYNC_RETRY_FLOOR_MS","toHeaderRecord","SETTLEMENT_OVERRIDES_HEADER","withPrivateCacheControl","x402ResourceServer","res"]}
|