@parallel-protocol/x402 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/express.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkTH77IB3T_cjs = require('./chunk-TH77IB3T.cjs');
4
- require('./chunk-KZZY5LS6.cjs');
3
+ var chunkAYMDIX7A_cjs = require('./chunk-AYMDIX7A.cjs');
4
+ require('./chunk-4CEMNRCZ.cjs');
5
5
 
6
6
  // src/express/adapter.ts
7
7
  function chunkBytes(args) {
@@ -56,6 +56,9 @@ var ExpressAdapter = class {
56
56
  getPath() {
57
57
  return this.req.path;
58
58
  }
59
+ getFullPath() {
60
+ return this.req.baseUrl + this.req.path;
61
+ }
59
62
  getUrl() {
60
63
  return `${this.req.protocol}://${this.req.headers.host}${this.req.originalUrl}`;
61
64
  }
@@ -67,9 +70,19 @@ var ExpressAdapter = class {
67
70
  async runHandler(options) {
68
71
  const res = this.res;
69
72
  const next = this.next;
73
+ chunkAYMDIX7A_cjs.dropConditionalHeaders(this.req.headers);
70
74
  const originalWriteHead = res.writeHead.bind(res);
71
75
  const originalWrite = res.write.bind(res);
72
76
  const originalEnd = res.end.bind(res);
77
+ const headersBefore = structuredClone(res.getHeaders());
78
+ const dropHandlerHeaders = () => {
79
+ for (const name of res.getHeaderNames())
80
+ if (!Object.hasOwn(headersBefore, name)) res.removeHeader(name);
81
+ for (const [name, value] of Object.entries(headersBefore))
82
+ if (value !== void 0) res.setHeader(name, value);
83
+ res.statusMessage = "";
84
+ };
85
+ const nodeWriters = Object.getPrototypeOf(res);
73
86
  const buffered = [];
74
87
  let settled = false;
75
88
  let discarded = false;
@@ -108,8 +121,8 @@ var ExpressAdapter = class {
108
121
  return originalEnd(...args);
109
122
  });
110
123
  next();
111
- const outcome = await chunkTH77IB3T_cjs.raceTimeout(endPromise, options?.timeoutMs);
112
- if (outcome === chunkTH77IB3T_cjs.HANDLER_TIMEOUT) {
124
+ const outcome = await chunkAYMDIX7A_cjs.raceTimeout(endPromise, options?.timeoutMs);
125
+ if (outcome === chunkAYMDIX7A_cjs.HANDLER_TIMEOUT) {
113
126
  discarded = true;
114
127
  return {
115
128
  status: 504,
@@ -121,8 +134,17 @@ var ExpressAdapter = class {
121
134
  },
122
135
  sendResponse: () => {
123
136
  if (res.headersSent) return;
124
- originalWriteHead(504, { "Content-Type": "application/json" });
125
- originalEnd(TIMEOUT_BODY);
137
+ dropHandlerHeaders();
138
+ nodeWriters.writeHead.call(res, 504, {
139
+ "Content-Type": "application/json",
140
+ "Content-Length": Buffer.byteLength(TIMEOUT_BODY)
141
+ });
142
+ nodeWriters.end.call(res, TIMEOUT_BODY, "utf8");
143
+ res.setHeader = (() => res);
144
+ res.setHeaders = (() => res);
145
+ res.appendHeader = (() => res);
146
+ res.removeHeader = () => {
147
+ };
126
148
  },
127
149
  discardResponse: () => {
128
150
  }
@@ -146,7 +168,7 @@ var ExpressAdapter = class {
146
168
  const chunk = chunkBytes(args);
147
169
  if (chunk) bytes.push(chunk);
148
170
  }
149
- return chunkTH77IB3T_cjs.parseJsonBody(
171
+ return chunkAYMDIX7A_cjs.parseJsonBody(
150
172
  contentType,
151
173
  Buffer.concat(bytes).toString("utf8")
152
174
  );
@@ -162,7 +184,9 @@ var ExpressAdapter = class {
162
184
  },
163
185
  discardResponse: () => {
164
186
  settled = true;
165
- restore();
187
+ dropHandlerHeaders();
188
+ for (const name of ["writeHead", "write", "end"])
189
+ Reflect.deleteProperty(res, name);
166
190
  }
167
191
  };
168
192
  }
@@ -170,11 +194,12 @@ var ExpressAdapter = class {
170
194
 
171
195
  // src/express/index.ts
172
196
  function paymentMiddleware(config) {
173
- const middleware = chunkTH77IB3T_cjs.createPaymentMiddleware(config);
197
+ const middleware = chunkAYMDIX7A_cjs.createPaymentMiddleware(config);
174
198
  return async (req, res, next) => {
175
199
  const result = await middleware(new ExpressAdapter(req, res, next));
176
200
  if ("pass" in result) {
177
201
  if (result.handlerRan) return;
202
+ if (result.preflight) chunkAYMDIX7A_cjs.answerAsPreflight(res);
178
203
  return next();
179
204
  }
180
205
  for (const [key, value] of Object.entries(result.headers)) {
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
- import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.cjs';
2
+ import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.cjs';
3
3
  import 'viem';
4
4
 
5
5
  declare class ExpressAdapter implements HTTPAdapter {
@@ -10,6 +10,7 @@ declare class ExpressAdapter implements HTTPAdapter {
10
10
  getHeader(name: string): string | undefined;
11
11
  getMethod(): string;
12
12
  getPath(): string;
13
+ getFullPath(): string;
13
14
  getUrl(): string;
14
15
  getBody(): Promise<unknown>;
15
16
  runHandler(options?: RunHandlerOptions): Promise<RunHandlerResult>;
package/dist/express.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
- import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.js';
2
+ import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.js';
3
3
  import 'viem';
4
4
 
5
5
  declare class ExpressAdapter implements HTTPAdapter {
@@ -10,6 +10,7 @@ declare class ExpressAdapter implements HTTPAdapter {
10
10
  getHeader(name: string): string | undefined;
11
11
  getMethod(): string;
12
12
  getPath(): string;
13
+ getFullPath(): string;
13
14
  getUrl(): string;
14
15
  getBody(): Promise<unknown>;
15
16
  runHandler(options?: RunHandlerOptions): Promise<RunHandlerResult>;
package/dist/express.js CHANGED
@@ -1,5 +1,5 @@
1
- import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-G7HSURPM.js';
2
- import './chunk-QAECRSWF.js';
1
+ import { dropConditionalHeaders, raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware, answerAsPreflight } from './chunk-CNASNROQ.js';
2
+ import './chunk-MZCHBBUN.js';
3
3
 
4
4
  // src/express/adapter.ts
5
5
  function chunkBytes(args) {
@@ -54,6 +54,9 @@ var ExpressAdapter = class {
54
54
  getPath() {
55
55
  return this.req.path;
56
56
  }
57
+ getFullPath() {
58
+ return this.req.baseUrl + this.req.path;
59
+ }
57
60
  getUrl() {
58
61
  return `${this.req.protocol}://${this.req.headers.host}${this.req.originalUrl}`;
59
62
  }
@@ -65,9 +68,19 @@ var ExpressAdapter = class {
65
68
  async runHandler(options) {
66
69
  const res = this.res;
67
70
  const next = this.next;
71
+ dropConditionalHeaders(this.req.headers);
68
72
  const originalWriteHead = res.writeHead.bind(res);
69
73
  const originalWrite = res.write.bind(res);
70
74
  const originalEnd = res.end.bind(res);
75
+ const headersBefore = structuredClone(res.getHeaders());
76
+ const dropHandlerHeaders = () => {
77
+ for (const name of res.getHeaderNames())
78
+ if (!Object.hasOwn(headersBefore, name)) res.removeHeader(name);
79
+ for (const [name, value] of Object.entries(headersBefore))
80
+ if (value !== void 0) res.setHeader(name, value);
81
+ res.statusMessage = "";
82
+ };
83
+ const nodeWriters = Object.getPrototypeOf(res);
71
84
  const buffered = [];
72
85
  let settled = false;
73
86
  let discarded = false;
@@ -119,8 +132,17 @@ var ExpressAdapter = class {
119
132
  },
120
133
  sendResponse: () => {
121
134
  if (res.headersSent) return;
122
- originalWriteHead(504, { "Content-Type": "application/json" });
123
- originalEnd(TIMEOUT_BODY);
135
+ dropHandlerHeaders();
136
+ nodeWriters.writeHead.call(res, 504, {
137
+ "Content-Type": "application/json",
138
+ "Content-Length": Buffer.byteLength(TIMEOUT_BODY)
139
+ });
140
+ nodeWriters.end.call(res, TIMEOUT_BODY, "utf8");
141
+ res.setHeader = (() => res);
142
+ res.setHeaders = (() => res);
143
+ res.appendHeader = (() => res);
144
+ res.removeHeader = () => {
145
+ };
124
146
  },
125
147
  discardResponse: () => {
126
148
  }
@@ -160,7 +182,9 @@ var ExpressAdapter = class {
160
182
  },
161
183
  discardResponse: () => {
162
184
  settled = true;
163
- restore();
185
+ dropHandlerHeaders();
186
+ for (const name of ["writeHead", "write", "end"])
187
+ Reflect.deleteProperty(res, name);
164
188
  }
165
189
  };
166
190
  }
@@ -173,6 +197,7 @@ function paymentMiddleware(config) {
173
197
  const result = await middleware(new ExpressAdapter(req, res, next));
174
198
  if ("pass" in result) {
175
199
  if (result.handlerRan) return;
200
+ if (result.preflight) answerAsPreflight(res);
176
201
  return next();
177
202
  }
178
203
  for (const [key, value] of Object.entries(result.headers)) {
package/dist/fastify.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkTH77IB3T_cjs = require('./chunk-TH77IB3T.cjs');
4
- require('./chunk-KZZY5LS6.cjs');
3
+ var chunkAYMDIX7A_cjs = require('./chunk-AYMDIX7A.cjs');
4
+ require('./chunk-4CEMNRCZ.cjs');
5
5
  var fp = require('fastify-plugin');
6
6
 
7
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -37,9 +37,39 @@ var FastifyAdapter = class {
37
37
  // src/fastify/index.ts
38
38
  function payloadJson(contentType, payload) {
39
39
  const text = typeof payload === "string" ? payload : payload instanceof Uint8Array ? Buffer.from(payload).toString("utf8") : void 0;
40
- return chunkTH77IB3T_cjs.parseJsonBody(contentType, text);
40
+ return chunkAYMDIX7A_cjs.parseJsonBody(contentType, text);
41
41
  }
42
- function refuse(reply, result) {
42
+ function keepCookiesBefore(reply, cookies) {
43
+ const raw = reply.raw;
44
+ const writeHead = raw.writeHead;
45
+ raw.writeHead = ((...args) => {
46
+ for (const arg of args)
47
+ if (typeof arg === "object" && arg !== null && !Array.isArray(arg))
48
+ delete arg["set-cookie"];
49
+ raw.removeHeader("set-cookie");
50
+ if (cookies !== void 0) raw.setHeader("set-cookie", cookies);
51
+ return writeHead.apply(raw, args);
52
+ });
53
+ }
54
+ function release(payload) {
55
+ if (payload instanceof ReadableStream) payload.cancel().catch(() => {
56
+ });
57
+ else if (typeof payload?.destroy === "function")
58
+ payload.destroy();
59
+ }
60
+ function refuse(reply, result, before, payload) {
61
+ release(payload);
62
+ if (before) {
63
+ for (const name of Object.keys(reply.getHeaders()))
64
+ reply.removeHeader(name);
65
+ for (const [name, value] of Object.entries(before.headers))
66
+ if (value !== void 0) reply.header(name, value);
67
+ for (const name of before.trailers) reply.removeTrailer(name);
68
+ for (const name of ["writeHead", "write", "end"])
69
+ Reflect.deleteProperty(reply.raw, name);
70
+ keepCookiesBefore(reply, before.headers["set-cookie"]);
71
+ }
72
+ reply.raw.statusMessage = "";
43
73
  const json = JSON.stringify(result.body);
44
74
  reply.status(result.status);
45
75
  for (const [name, value] of Object.entries(result.headers)) {
@@ -54,35 +84,51 @@ function headerValue(value) {
54
84
  }
55
85
  function paymentMiddleware(config) {
56
86
  return fp__default.default(async (fastify) => {
57
- const gate = chunkTH77IB3T_cjs.createPaymentGate(config);
87
+ const gate = chunkAYMDIX7A_cjs.createPaymentGate(config);
58
88
  const verifiedMap = /* @__PURE__ */ new WeakMap();
59
89
  const rawWriters = /* @__PURE__ */ new WeakMap();
90
+ const replyBefore = /* @__PURE__ */ new WeakMap();
91
+ const routes = chunkAYMDIX7A_cjs.routeTable(config.routes);
92
+ const needsBodyByRequest = /* @__PURE__ */ new WeakMap();
60
93
  const needsBody = (req) => {
61
- const route = chunkTH77IB3T_cjs.matchRoute(
62
- new FastifyAdapter(req).getPath(),
63
- config.routes
64
- );
65
- return typeof route?.price === "function" || route?.meter !== void 0;
94
+ let needs = needsBodyByRequest.get(req);
95
+ if (needs === void 0) {
96
+ const { route } = chunkAYMDIX7A_cjs.findRoute(new FastifyAdapter(req).getPath(), routes);
97
+ needs = typeof route?.price === "function" || route?.meter !== void 0;
98
+ needsBodyByRequest.set(req, needs);
99
+ }
100
+ return needs;
66
101
  };
67
102
  fastify.addHook("onRequest", async (req, reply) => {
68
103
  if (needsBody(req)) return;
69
- await runGate(req, reply);
104
+ return runGate(req, reply);
70
105
  });
71
106
  fastify.addHook("preHandler", async (req, reply) => {
72
107
  if (!needsBody(req)) return;
73
- await runGate(req, reply);
108
+ return runGate(req, reply);
74
109
  });
75
110
  async function runGate(req, reply) {
76
111
  const gateResult = await gate(new FastifyAdapter(req));
77
- if (gateResult.type === "pass") return;
112
+ if (gateResult.type === "pass") {
113
+ if (gateResult.preflight) chunkAYMDIX7A_cjs.answerAsPreflight(reply.raw);
114
+ return;
115
+ }
78
116
  if (gateResult.type === "error") {
79
117
  for (const [key, value] of Object.entries(gateResult.result.headers)) {
80
118
  reply.header(key, value);
81
119
  }
82
- reply.status(gateResult.result.status).send(gateResult.result.body);
83
- return;
120
+ return reply.status(gateResult.result.status).send(gateResult.result.body);
84
121
  }
85
122
  verifiedMap.set(req, gateResult);
123
+ chunkAYMDIX7A_cjs.dropConditionalHeaders(req.headers);
124
+ const trailers = /* @__PURE__ */ new Set();
125
+ const headers = structuredClone(reply.getHeaders());
126
+ replyBefore.set(req, { headers, trailers });
127
+ const trailer = reply.trailer.bind(reply);
128
+ reply.trailer = ((name, fn) => {
129
+ trailers.add(name.toLowerCase());
130
+ return trailer(name, fn);
131
+ });
86
132
  const raw = reply.raw;
87
133
  rawWriters.set(req, {
88
134
  write: raw.write,
@@ -111,29 +157,39 @@ function paymentMiddleware(config) {
111
157
  if (!verified) return payload;
112
158
  let raw;
113
159
  if (verified.scheme === "upto") {
114
- raw = headerValue(reply.getHeader(chunkTH77IB3T_cjs.SETTLE_AMOUNT_HEADER));
115
- reply.removeHeader(chunkTH77IB3T_cjs.SETTLE_AMOUNT_HEADER);
160
+ raw = headerValue(reply.getHeader(chunkAYMDIX7A_cjs.SETTLE_AMOUNT_HEADER));
161
+ reply.removeHeader(chunkAYMDIX7A_cjs.SETTLE_AMOUNT_HEADER);
116
162
  }
117
163
  if (reply.statusCode < 200 || reply.statusCode >= 300) {
118
164
  return payload;
119
165
  }
120
166
  let settleOptions;
121
167
  if (verified.scheme === "upto") {
122
- const resolved = await chunkTH77IB3T_cjs.resolveCharge(verified, raw, {
168
+ const resolved = await chunkAYMDIX7A_cjs.resolveCharge(verified, raw, {
123
169
  status: reply.statusCode,
124
170
  header: (name) => headerValue(reply.getHeader(name)),
125
171
  body: async () => payloadJson(headerValue(reply.getHeader("content-type")), payload)
126
172
  });
127
173
  if (resolved.kind === "invalid") {
128
- return refuse(reply, chunkTH77IB3T_cjs.invalidSettleAmountResponse(resolved.reason));
174
+ return refuse(
175
+ reply,
176
+ chunkAYMDIX7A_cjs.invalidSettleAmountResponse(resolved.reason),
177
+ replyBefore.get(req),
178
+ payload
179
+ );
129
180
  }
130
181
  if (resolved.kind === "skip") return payload;
131
182
  settleOptions = { amount: resolved.amount };
132
183
  }
133
- const outcome = await chunkTH77IB3T_cjs.settleVerified(verified, settleOptions);
184
+ const outcome = await chunkAYMDIX7A_cjs.settleVerified(verified, settleOptions);
134
185
  if (!outcome.settled)
135
- return refuse(reply, chunkTH77IB3T_cjs.settlementFailureResponse(outcome));
136
- reply.header("payment-response", chunkTH77IB3T_cjs.encodeBase64(outcome.confirmation));
186
+ return refuse(
187
+ reply,
188
+ chunkAYMDIX7A_cjs.settlementFailureResponse(outcome),
189
+ replyBefore.get(req),
190
+ payload
191
+ );
192
+ reply.header("payment-response", chunkAYMDIX7A_cjs.encodeBase64(outcome.confirmation));
137
193
  reply.header("access-control-expose-headers", "payment-response");
138
194
  return payload;
139
195
  });
@@ -1,5 +1,5 @@
1
1
  import { FastifyRequest, FastifyPluginAsync } from 'fastify';
2
- import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.cjs';
2
+ import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.cjs';
3
3
  import 'viem';
4
4
 
5
5
  declare class FastifyAdapter implements HTTPAdapter {
package/dist/fastify.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FastifyRequest, FastifyPluginAsync } from 'fastify';
2
- import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.js';
2
+ import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.js';
3
3
  import 'viem';
4
4
 
5
5
  declare class FastifyAdapter implements HTTPAdapter {
package/dist/fastify.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-G7HSURPM.js';
2
- import './chunk-QAECRSWF.js';
1
+ import { createPaymentGate, routeTable, answerAsPreflight, dropConditionalHeaders, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, findRoute, parseJsonBody } from './chunk-CNASNROQ.js';
2
+ import './chunk-MZCHBBUN.js';
3
3
  import fp from 'fastify-plugin';
4
4
 
5
5
  // src/fastify/adapter.ts
@@ -33,7 +33,37 @@ function payloadJson(contentType, payload) {
33
33
  const text = typeof payload === "string" ? payload : payload instanceof Uint8Array ? Buffer.from(payload).toString("utf8") : void 0;
34
34
  return parseJsonBody(contentType, text);
35
35
  }
36
- function refuse(reply, result) {
36
+ function keepCookiesBefore(reply, cookies) {
37
+ const raw = reply.raw;
38
+ const writeHead = raw.writeHead;
39
+ raw.writeHead = ((...args) => {
40
+ for (const arg of args)
41
+ if (typeof arg === "object" && arg !== null && !Array.isArray(arg))
42
+ delete arg["set-cookie"];
43
+ raw.removeHeader("set-cookie");
44
+ if (cookies !== void 0) raw.setHeader("set-cookie", cookies);
45
+ return writeHead.apply(raw, args);
46
+ });
47
+ }
48
+ function release(payload) {
49
+ if (payload instanceof ReadableStream) payload.cancel().catch(() => {
50
+ });
51
+ else if (typeof payload?.destroy === "function")
52
+ payload.destroy();
53
+ }
54
+ function refuse(reply, result, before, payload) {
55
+ release(payload);
56
+ if (before) {
57
+ for (const name of Object.keys(reply.getHeaders()))
58
+ reply.removeHeader(name);
59
+ for (const [name, value] of Object.entries(before.headers))
60
+ if (value !== void 0) reply.header(name, value);
61
+ for (const name of before.trailers) reply.removeTrailer(name);
62
+ for (const name of ["writeHead", "write", "end"])
63
+ Reflect.deleteProperty(reply.raw, name);
64
+ keepCookiesBefore(reply, before.headers["set-cookie"]);
65
+ }
66
+ reply.raw.statusMessage = "";
37
67
  const json = JSON.stringify(result.body);
38
68
  reply.status(result.status);
39
69
  for (const [name, value] of Object.entries(result.headers)) {
@@ -51,32 +81,48 @@ function paymentMiddleware(config) {
51
81
  const gate = createPaymentGate(config);
52
82
  const verifiedMap = /* @__PURE__ */ new WeakMap();
53
83
  const rawWriters = /* @__PURE__ */ new WeakMap();
84
+ const replyBefore = /* @__PURE__ */ new WeakMap();
85
+ const routes = routeTable(config.routes);
86
+ const needsBodyByRequest = /* @__PURE__ */ new WeakMap();
54
87
  const needsBody = (req) => {
55
- const route = matchRoute(
56
- new FastifyAdapter(req).getPath(),
57
- config.routes
58
- );
59
- return typeof route?.price === "function" || route?.meter !== void 0;
88
+ let needs = needsBodyByRequest.get(req);
89
+ if (needs === void 0) {
90
+ const { route } = findRoute(new FastifyAdapter(req).getPath(), routes);
91
+ needs = typeof route?.price === "function" || route?.meter !== void 0;
92
+ needsBodyByRequest.set(req, needs);
93
+ }
94
+ return needs;
60
95
  };
61
96
  fastify.addHook("onRequest", async (req, reply) => {
62
97
  if (needsBody(req)) return;
63
- await runGate(req, reply);
98
+ return runGate(req, reply);
64
99
  });
65
100
  fastify.addHook("preHandler", async (req, reply) => {
66
101
  if (!needsBody(req)) return;
67
- await runGate(req, reply);
102
+ return runGate(req, reply);
68
103
  });
69
104
  async function runGate(req, reply) {
70
105
  const gateResult = await gate(new FastifyAdapter(req));
71
- if (gateResult.type === "pass") return;
106
+ if (gateResult.type === "pass") {
107
+ if (gateResult.preflight) answerAsPreflight(reply.raw);
108
+ return;
109
+ }
72
110
  if (gateResult.type === "error") {
73
111
  for (const [key, value] of Object.entries(gateResult.result.headers)) {
74
112
  reply.header(key, value);
75
113
  }
76
- reply.status(gateResult.result.status).send(gateResult.result.body);
77
- return;
114
+ return reply.status(gateResult.result.status).send(gateResult.result.body);
78
115
  }
79
116
  verifiedMap.set(req, gateResult);
117
+ dropConditionalHeaders(req.headers);
118
+ const trailers = /* @__PURE__ */ new Set();
119
+ const headers = structuredClone(reply.getHeaders());
120
+ replyBefore.set(req, { headers, trailers });
121
+ const trailer = reply.trailer.bind(reply);
122
+ reply.trailer = ((name, fn) => {
123
+ trailers.add(name.toLowerCase());
124
+ return trailer(name, fn);
125
+ });
80
126
  const raw = reply.raw;
81
127
  rawWriters.set(req, {
82
128
  write: raw.write,
@@ -119,14 +165,24 @@ function paymentMiddleware(config) {
119
165
  body: async () => payloadJson(headerValue(reply.getHeader("content-type")), payload)
120
166
  });
121
167
  if (resolved.kind === "invalid") {
122
- return refuse(reply, invalidSettleAmountResponse(resolved.reason));
168
+ return refuse(
169
+ reply,
170
+ invalidSettleAmountResponse(resolved.reason),
171
+ replyBefore.get(req),
172
+ payload
173
+ );
123
174
  }
124
175
  if (resolved.kind === "skip") return payload;
125
176
  settleOptions = { amount: resolved.amount };
126
177
  }
127
178
  const outcome = await settleVerified(verified, settleOptions);
128
179
  if (!outcome.settled)
129
- return refuse(reply, settlementFailureResponse(outcome));
180
+ return refuse(
181
+ reply,
182
+ settlementFailureResponse(outcome),
183
+ replyBefore.get(req),
184
+ payload
185
+ );
130
186
  reply.header("payment-response", encodeBase64(outcome.confirmation));
131
187
  reply.header("access-control-expose-headers", "payment-response");
132
188
  return payload;
package/dist/hono.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkTH77IB3T_cjs = require('./chunk-TH77IB3T.cjs');
4
- require('./chunk-KZZY5LS6.cjs');
3
+ var chunkAYMDIX7A_cjs = require('./chunk-AYMDIX7A.cjs');
4
+ require('./chunk-4CEMNRCZ.cjs');
5
5
 
6
6
  // src/hono/adapter.ts
7
7
  var TIMEOUT_BODY = JSON.stringify({
@@ -30,7 +30,7 @@ var HonoAdapter = class {
30
30
  // Hono caches the parsed body on the request, so the handler can still read
31
31
  // it after the price function did.
32
32
  async getBody() {
33
- if (!chunkTH77IB3T_cjs.isJsonContentType(this.c.req.header("content-type"))) return void 0;
33
+ if (!chunkAYMDIX7A_cjs.isJsonContentType(this.c.req.header("content-type"))) return void 0;
34
34
  try {
35
35
  return await this.c.req.json();
36
36
  } catch {
@@ -38,8 +38,15 @@ var HonoAdapter = class {
38
38
  }
39
39
  }
40
40
  async runHandler(options) {
41
- const outcome = await chunkTH77IB3T_cjs.raceTimeout(this.next(), options?.timeoutMs);
42
- if (outcome === chunkTH77IB3T_cjs.HANDLER_TIMEOUT) {
41
+ const headersBefore = new Headers(this.c.res.headers);
42
+ const replace = (body, status) => {
43
+ const headers = new Headers(headersBefore);
44
+ if (body !== null) headers.set("Content-Type", "application/json");
45
+ this.c.res = void 0;
46
+ this.c.res = new Response(body, { status, headers });
47
+ };
48
+ const outcome = await chunkAYMDIX7A_cjs.raceTimeout(this.next(), options?.timeoutMs);
49
+ if (outcome === chunkAYMDIX7A_cjs.HANDLER_TIMEOUT) {
43
50
  return {
44
51
  status: 504,
45
52
  setResponseHeader: () => {
@@ -47,12 +54,7 @@ var HonoAdapter = class {
47
54
  getResponseHeader: () => void 0,
48
55
  removeResponseHeader: () => {
49
56
  },
50
- sendResponse: () => {
51
- this.c.res = new Response(TIMEOUT_BODY, {
52
- status: 504,
53
- headers: { "Content-Type": "application/json" }
54
- });
55
- },
57
+ sendResponse: () => replace(TIMEOUT_BODY, 504),
56
58
  discardResponse: () => {
57
59
  }
58
60
  };
@@ -64,7 +66,7 @@ var HonoAdapter = class {
64
66
  getResponseHeader: (name) => res.headers.get(name) ?? void 0,
65
67
  removeResponseHeader: (name) => res.headers.delete(name),
66
68
  // Read from a clone: the response body streams once, to the client.
67
- getResponseBody: () => chunkTH77IB3T_cjs.jsonFromResponse(res),
69
+ getResponseBody: () => chunkAYMDIX7A_cjs.jsonFromResponse(res),
68
70
  sendResponse: () => {
69
71
  },
70
72
  // The response is replaced: release its body (and whatever upstream
@@ -72,6 +74,7 @@ var HonoAdapter = class {
72
74
  discardResponse: () => {
73
75
  res.body?.cancel().catch(() => {
74
76
  });
77
+ replace(null);
75
78
  }
76
79
  };
77
80
  }
@@ -79,15 +82,20 @@ var HonoAdapter = class {
79
82
 
80
83
  // src/hono/index.ts
81
84
  function paymentMiddleware(config) {
82
- const middleware = chunkTH77IB3T_cjs.createPaymentMiddleware(config);
85
+ const middleware = chunkAYMDIX7A_cjs.createPaymentMiddleware(config);
83
86
  return async (c, next) => {
84
87
  const result = await middleware(new HonoAdapter(c, next));
85
88
  if ("pass" in result) {
86
89
  if (result.handlerRan) return;
87
90
  await next();
91
+ if (result.preflight) {
92
+ const init = chunkAYMDIX7A_cjs.preflightInit(c.res);
93
+ c.res = void 0;
94
+ c.res = new Response(null, init);
95
+ }
88
96
  return;
89
97
  }
90
- return new Response(JSON.stringify(result.body), {
98
+ c.res = new Response(JSON.stringify(result.body), {
91
99
  status: result.status,
92
100
  headers: { ...result.headers, "Content-Type": "application/json" }
93
101
  });
package/dist/hono.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Next, MiddlewareHandler } from 'hono';
2
- import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.cjs';
2
+ import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.cjs';
3
3
  import 'viem';
4
4
 
5
5
  declare class HonoAdapter implements HTTPAdapter {
package/dist/hono.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Next, MiddlewareHandler } from 'hono';
2
- import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.js';
2
+ import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-CRBMTQaq.js';
3
3
  import 'viem';
4
4
 
5
5
  declare class HonoAdapter implements HTTPAdapter {