tempo.ts 0.7.3 → 0.7.4
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/CHANGELOG.md +6 -0
- package/dist/server/Handler.d.ts +7 -4
- package/dist/server/Handler.d.ts.map +1 -1
- package/dist/server/Handler.js +37 -2
- package/dist/server/Handler.js.map +1 -1
- package/package.json +1 -1
- package/src/server/Handler.test.ts +316 -0
- package/src/server/Handler.ts +58 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# tempo.ts
|
|
2
2
|
|
|
3
|
+
## 0.7.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`1b5c63b`](https://github.com/tempoxyz/tempo-ts/commit/1b5c63bfd3ebb348049b3051baf093620af2b2a6) Thanks [@jxom](https://github.com/jxom)! - Added `headers` to `Handler` functions.
|
|
8
|
+
|
|
3
9
|
## 0.7.3
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/server/Handler.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type Handler = Router & {
|
|
|
11
11
|
};
|
|
12
12
|
export declare function compose(handlers: Handler[], options?: compose.Options): Handler;
|
|
13
13
|
export declare namespace compose {
|
|
14
|
-
type Options = {
|
|
14
|
+
type Options = from.Options & {
|
|
15
15
|
/** The path to use for the handler. */
|
|
16
16
|
path?: string | undefined;
|
|
17
17
|
};
|
|
@@ -24,7 +24,10 @@ export declare namespace compose {
|
|
|
24
24
|
*/
|
|
25
25
|
export declare function from(options?: from.Options): Handler;
|
|
26
26
|
export declare namespace from {
|
|
27
|
-
type Options = RouterOptions
|
|
27
|
+
type Options = RouterOptions & {
|
|
28
|
+
/** Headers to add to the response. */
|
|
29
|
+
headers?: Headers | Record<string, string> | undefined;
|
|
30
|
+
};
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
30
33
|
* Defines a Key Manager request handler.
|
|
@@ -135,7 +138,7 @@ export declare namespace from {
|
|
|
135
138
|
*/
|
|
136
139
|
export declare function keyManager(options: keyManager.Options): Handler;
|
|
137
140
|
export declare namespace keyManager {
|
|
138
|
-
type Options = {
|
|
141
|
+
type Options = from.Options & {
|
|
139
142
|
/** The KV store to use for key management. */
|
|
140
143
|
kv: Kv.Kv;
|
|
141
144
|
/** The path to use for the handler. */
|
|
@@ -336,7 +339,7 @@ export declare namespace keyManager {
|
|
|
336
339
|
*/
|
|
337
340
|
export declare function feePayer(options: feePayer.Options): Handler;
|
|
338
341
|
export declare namespace feePayer {
|
|
339
|
-
type Options = {
|
|
342
|
+
type Options = from.Options & {
|
|
340
343
|
/** Account to use as the fee payer. */
|
|
341
344
|
account: LocalAccount;
|
|
342
345
|
/** Function to call before handling the request. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Handler.d.ts","sourceRoot":"","sources":["../../src/server/Handler.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Handler.d.ts","sourceRoot":"","sources":["../../src/server/Handler.ts"],"names":[],"mappings":"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"}
|
package/dist/server/Handler.js
CHANGED
|
@@ -10,6 +10,7 @@ import * as RequestListener from './internal/requestListener.js';
|
|
|
10
10
|
export function compose(handlers, options = {}) {
|
|
11
11
|
const path = options.path ?? '/';
|
|
12
12
|
return from({
|
|
13
|
+
...options,
|
|
13
14
|
async defaultHandler(context) {
|
|
14
15
|
const url = new URL(context.request.url);
|
|
15
16
|
if (!url.pathname.startsWith(path))
|
|
@@ -32,7 +33,10 @@ export function compose(handlers, options = {}) {
|
|
|
32
33
|
* @returns Handler instance
|
|
33
34
|
*/
|
|
34
35
|
export function from(options = {}) {
|
|
35
|
-
const router = createRouter(
|
|
36
|
+
const router = createRouter({
|
|
37
|
+
...options,
|
|
38
|
+
middleware: [headers(options.headers), preflight(options.headers)],
|
|
39
|
+
});
|
|
36
40
|
return {
|
|
37
41
|
...router,
|
|
38
42
|
listener: RequestListener.fromFetchHandler((request) => {
|
|
@@ -160,7 +164,7 @@ export function keyManager(options) {
|
|
|
160
164
|
};
|
|
161
165
|
return undefined;
|
|
162
166
|
})();
|
|
163
|
-
const router = from();
|
|
167
|
+
const router = from(options);
|
|
164
168
|
// Get challenge for WebAuthn credential creation
|
|
165
169
|
router.get(`${path}/challenge`, async () => {
|
|
166
170
|
// Generate a random challenge
|
|
@@ -465,4 +469,35 @@ export function feePayer(options) {
|
|
|
465
469
|
});
|
|
466
470
|
return router;
|
|
467
471
|
}
|
|
472
|
+
/** @internal */
|
|
473
|
+
function normalizeHeaders(headers) {
|
|
474
|
+
if (!headers)
|
|
475
|
+
return new Headers();
|
|
476
|
+
if (headers instanceof Headers)
|
|
477
|
+
return headers;
|
|
478
|
+
return new Headers(headers);
|
|
479
|
+
}
|
|
480
|
+
/** @internal */
|
|
481
|
+
function headers(headers) {
|
|
482
|
+
const normalizedHeaders = normalizeHeaders(headers);
|
|
483
|
+
return async (_, next) => {
|
|
484
|
+
const response = await next();
|
|
485
|
+
const headers = new Headers(response.headers);
|
|
486
|
+
for (const [key, value] of normalizedHeaders.entries())
|
|
487
|
+
headers.set(key, value);
|
|
488
|
+
return new Response(response.body, {
|
|
489
|
+
headers,
|
|
490
|
+
status: response.status,
|
|
491
|
+
statusText: response.statusText,
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
/** @internal */
|
|
496
|
+
function preflight(headers) {
|
|
497
|
+
const normalizedHeaders = normalizeHeaders(headers);
|
|
498
|
+
return async (context) => {
|
|
499
|
+
if (context.request.method === 'OPTIONS')
|
|
500
|
+
return new Response(null, { headers: normalizedHeaders });
|
|
501
|
+
};
|
|
502
|
+
}
|
|
468
503
|
//# sourceMappingURL=Handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Handler.js","sourceRoot":"","sources":["../../src/server/Handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"Handler.js","sourceRoot":"","sources":["../../src/server/Handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAIb,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,GAAG,MAAM,QAAQ,CAAA;AAE7B,OAAO,EAA2B,YAAY,EAAkB,MAAM,MAAM,CAAA;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,KAAK,WAAW,MAAM,wBAAwB,CAAA;AACrD,OAAO,KAAK,eAAe,MAAM,+BAA+B,CAAA;AAOhE,MAAM,UAAU,OAAO,CACrB,QAAmB,EACnB,UAA2B,EAAE;IAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAA;IAEhC,OAAO,IAAI,CAAC;QACV,GAAG,OAAO;QACV,KAAK,CAAC,cAAc,CAAC,OAAO;YAC1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACxC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;gBAChC,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAEnD,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YAC7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;gBACzD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;oBAAE,OAAO,QAAQ,CAAA;YAC9C,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QACnD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,UAAwB,EAAE;IAC7C,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,GAAG,OAAO;QACV,UAAU,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KACnE,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE;YACrD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC9B,CAAC,CAAC;KACH,CAAA;AACH,CAAC;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AACH,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAA;IAEtB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAA;IAE/B,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE;QACf,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ;YAChC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAA;QAC7C,IAAI,OAAO,CAAC,EAAE;YACZ,OAAO;gBACL,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE;gBACjB,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,EAAE;aACvC,CAAA;QACH,OAAO,SAAS,CAAA;IAClB,CAAC,CAAC,EAAE,CAAA;IAEJ,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IAE5B,iDAAiD;IACjD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,YAAY,EAAE,KAAK,IAAI,EAAE;QACzC,8BAA8B;QAC9B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAEhC,iDAAiD;QACjD,MAAM,EAAE,CAAC,GAAG,CAAC,aAAa,SAAS,EAAE,EAAE,GAAG,CAAC,CAAA;QAE3C,OAAO,QAAQ,CAAC,IAAI,CAAC;YACnB,SAAS;YACT,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACiB,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,kCAAkC;IAClC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC7C,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAA;QAErB,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,GAAG,CAAU,cAAc,EAAE,EAAE,CAAC,CAAA;QAE3D,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,QAAQ,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAE5E,OAAO,QAAQ,CAAC,IAAI,CAAC;YACnB,SAAS;SACV,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,kCAAkC;IAClC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACvD,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAA;QACrB,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAQ,CAAA;QAE/D,IAAI,CAAC,UAAU;YACb,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC1E,IAAI,CAAC,SAAS;YACZ,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAEzE,mCAAmC;QACnC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAC/B,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAmC,CAAC,CACzE,CAAA;QAED,mBAAmB;QACnB,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;QAExD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAS,aAAa,SAAS,EAAE,CAAC,CAAC;YACnD,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,gCAAgC,EAAE,EAC3C,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QAEH,cAAc;QACd,IAAI,cAAc,CAAC,IAAI,KAAK,iBAAiB;YAC3C,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,+BAA+B,EAAE,EAC1C,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QAEH,gBAAgB;QAChB,IACE,EAAE,EAAE,EAAE;YACN,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC5B,cAAc,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM;YAE5D,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,iCAAiC,EAAE,EAC5C,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QAEH,0BAA0B;QAC1B,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CACrC,UAAU,CAAC,QAAgB,CAAC,iBAAiB,CAC/C,CAAA;QAED,wBAAwB;QACxB,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK;YACR,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,6BAA6B,EAAE,EACxC,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QAEH,uCAAuC;QACvC,MAAM,WAAW,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,WAAW;YACd,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAEtE,0DAA0D;QAC1D,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,SAAS,EAAE,CAAC,CAAA;QAEzC,uBAAuB;QACvB,MAAM,EAAE,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,EAAE,SAAS,CAAC,CAAA;QAE3C,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4KG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAyB;IAChD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,OAAO,CAAA;IAElD,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;QACnB,IAAI,QAAQ,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC,MAAO,CAAA;QAC/C,IAAI,OAAO,IAAI,OAAO,IAAI,WAAW,IAAI,OAAO;YAC9C,OAAO,YAAY,CAAC;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAA;QACJ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC,CAAC,EAAE,CAAA;IAEJ,MAAM,MAAM,GAAG,IAAI,EAAE,CAAA;IAErB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAQ,CAAC,CAAA;QAE1D,IAAI,CAAC;YACH,MAAM,SAAS,EAAE,CAAC,OAAO,CAAC,CAAA;YAE1B,IAAI,OAAO,CAAC,MAAM,KAAK,qBAAqB,EAAE,CAAC;gBAC7C,MAAM,kBAAkB,GAAG,iBAAiB,CAC1C,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAU,CAC7B,CAAA;gBAED,MAAM,qBAAqB,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE;oBAC1D,GAAG,kBAAkB;oBACrB,OAAO;oBACP,mBAAmB;oBACnB,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;gBAEF,OAAO,QAAQ,CAAC,IAAI,CAClB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CACjE,CAAA;YACH,CAAC;YAED,IAAK,OAAe,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;gBACzD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAoB,CAAA;gBACzD,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;gBAEvD,MAAM,qBAAqB,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE;oBAC1D,GAAG,WAAW;oBACd,OAAO;oBACP,mBAAmB;oBACnB,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;gBAEF,OAAO,QAAQ,CAAC,IAAI,CAClB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CACjE,CAAA;YACH,CAAC;YAED,IACE,OAAO,CAAC,MAAM,KAAK,wBAAwB;gBAC3C,OAAO,CAAC,MAAM,KAAK,4BAA4B,EAC/C,CAAC;gBACD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAoB,CAAA;gBACzD,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;gBAEvD,MAAM,qBAAqB,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE;oBAC1D,GAAG,WAAW;oBACd,OAAO;oBACP,mBAAmB;oBACnB,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;gBAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;oBAClC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,MAAM,EAAE,CAAC,qBAAqB,CAAC;iBAChC,CAAC,CAAA;gBAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;YACjE,CAAC;YAED,OAAO,QAAQ,CAAC,IAAI,CAClB,WAAW,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,IAAI,WAAW,CAAC,uBAAuB,CAAC;oBAC7C,OAAO,EAAE,yBAAyB,OAAO,CAAC,MAAM,EAAE;iBACnD,CAAC;aACH,EACD,EAAE,OAAO,EAAE,CACZ,CACF,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,IAAI,CAClB,WAAW,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,IAAI,WAAW,CAAC,aAAa,CAAC;oBACnC,OAAO,EAAG,KAAe,CAAC,OAAO;iBAClC,CAAC;aACH,EACD,EAAE,OAAO,EAAE,CACZ,CACF,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC;AAwBD,gBAAgB;AAChB,SAAS,gBAAgB,CAAC,OAA0C;IAClE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,OAAO,EAAE,CAAA;IAClC,IAAI,OAAO,YAAY,OAAO;QAAE,OAAO,OAAO,CAAA;IAC9C,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;AAC7B,CAAC;AAED,gBAAgB;AAChB,SAAS,OAAO,CAAC,OAA0C;IACzD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACnD,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAA;QAC7B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,iBAAiB,CAAC,OAAO,EAAE;YACpD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACzB,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;YACjC,OAAO;YACP,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;SAChC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC;AAED,gBAAgB;AAChB,SAAS,SAAS,CAAC,OAA0C;IAC3D,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACnD,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;YACtC,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAA;IAC7D,CAAC,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -74,6 +74,211 @@ describe('compose', () => {
|
|
|
74
74
|
}
|
|
75
75
|
})
|
|
76
76
|
|
|
77
|
+
test('behavior: headers', async () => {
|
|
78
|
+
const handler1 = Handler.from()
|
|
79
|
+
handler1.get('/test', () => new Response('test'))
|
|
80
|
+
const handler2 = Handler.from()
|
|
81
|
+
handler2.get('/test2', () => new Response('test2'))
|
|
82
|
+
|
|
83
|
+
const headers = new Headers({
|
|
84
|
+
'Access-Control-Allow-Origin': '*',
|
|
85
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
86
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const handler = Handler.compose([handler1, handler2], {
|
|
90
|
+
headers,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
95
|
+
expect(response.status).toBe(200)
|
|
96
|
+
expect(await response.text()).toBe('test')
|
|
97
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
98
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
99
|
+
'POST, OPTIONS',
|
|
100
|
+
)
|
|
101
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
102
|
+
'Content-Type, Authorization',
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
{
|
|
107
|
+
const response = await handler.fetch(
|
|
108
|
+
new Request('http://localhost/test2'),
|
|
109
|
+
)
|
|
110
|
+
expect(response.status).toBe(200)
|
|
111
|
+
expect(await response.text()).toBe('test2')
|
|
112
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('behavior: headers + path', async () => {
|
|
117
|
+
const handler1 = Handler.from()
|
|
118
|
+
handler1.get('/test', () => new Response('test'))
|
|
119
|
+
const handler2 = Handler.from()
|
|
120
|
+
handler2.get('/test2', () => new Response('test2'))
|
|
121
|
+
|
|
122
|
+
const headers = new Headers({
|
|
123
|
+
'Access-Control-Allow-Origin': '*',
|
|
124
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const handler = Handler.compose([handler1, handler2], {
|
|
128
|
+
headers,
|
|
129
|
+
path: '/api',
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
{
|
|
133
|
+
const response = await handler.fetch(
|
|
134
|
+
new Request('http://localhost/api/test'),
|
|
135
|
+
)
|
|
136
|
+
expect(response.status).toBe(200)
|
|
137
|
+
expect(await response.text()).toBe('test')
|
|
138
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
139
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
140
|
+
'POST, OPTIONS',
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
{
|
|
145
|
+
const response = await handler.fetch(
|
|
146
|
+
new Request('http://localhost/api/test2'),
|
|
147
|
+
)
|
|
148
|
+
expect(response.status).toBe(200)
|
|
149
|
+
expect(await response.text()).toBe('test2')
|
|
150
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('behavior: headers + OPTIONS', async () => {
|
|
155
|
+
const handler1 = Handler.from()
|
|
156
|
+
handler1.get('/test', () => new Response('test'))
|
|
157
|
+
|
|
158
|
+
const headers = new Headers({
|
|
159
|
+
'Access-Control-Allow-Origin': '*',
|
|
160
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
161
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
162
|
+
'Access-Control-Max-Age': '86400',
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
const handler = Handler.compose([handler1], {
|
|
166
|
+
headers,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
const response = await handler.fetch(
|
|
170
|
+
new Request('http://localhost/test', {
|
|
171
|
+
method: 'OPTIONS',
|
|
172
|
+
}),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
expect(response.status).toBe(200)
|
|
176
|
+
expect(await response.text()).toBe('')
|
|
177
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
178
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
179
|
+
'POST, OPTIONS',
|
|
180
|
+
)
|
|
181
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
182
|
+
'Content-Type, Authorization',
|
|
183
|
+
)
|
|
184
|
+
expect(response.headers.get('Access-Control-Max-Age')).toBe('86400')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
test('behavior: headers + 404', async () => {
|
|
188
|
+
const handler1 = Handler.from()
|
|
189
|
+
handler1.get('/test', () => new Response('test'))
|
|
190
|
+
|
|
191
|
+
const headers = new Headers({
|
|
192
|
+
'Access-Control-Allow-Origin': '*',
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
const handler = Handler.compose([handler1], {
|
|
196
|
+
headers,
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
const response = await handler.fetch(
|
|
200
|
+
new Request('http://localhost/nonexistent'),
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
expect(response.status).toBe(404)
|
|
204
|
+
expect(await response.text()).toBe('Not Found')
|
|
205
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
test('behavior: headers propagation from child handlers', async () => {
|
|
209
|
+
const handler1 = Handler.from()
|
|
210
|
+
handler1.get('/test', () => {
|
|
211
|
+
const response = new Response('test')
|
|
212
|
+
response.headers.set('X-Custom-Header', 'custom-value')
|
|
213
|
+
return response
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
const headers = new Headers({
|
|
217
|
+
'Access-Control-Allow-Origin': '*',
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const handler = Handler.compose([handler1], {
|
|
221
|
+
headers,
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
225
|
+
|
|
226
|
+
expect(response.status).toBe(200)
|
|
227
|
+
expect(await response.text()).toBe('test')
|
|
228
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
229
|
+
expect(response.headers.get('X-Custom-Header')).toBe('custom-value')
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('behavior: headers with child handler headers', async () => {
|
|
233
|
+
const childHeaders = new Headers({
|
|
234
|
+
'X-Child-Header': 'child-value',
|
|
235
|
+
})
|
|
236
|
+
const handler1 = Handler.from({ headers: childHeaders })
|
|
237
|
+
handler1.get('/test', () => new Response('test'))
|
|
238
|
+
|
|
239
|
+
const parentHeaders = new Headers({
|
|
240
|
+
'Access-Control-Allow-Origin': '*',
|
|
241
|
+
'X-Parent-Header': 'parent-value',
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
const handler = Handler.compose([handler1], {
|
|
245
|
+
headers: parentHeaders,
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
249
|
+
|
|
250
|
+
expect(response.status).toBe(200)
|
|
251
|
+
expect(await response.text()).toBe('test')
|
|
252
|
+
// Both parent and child headers should be present
|
|
253
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
254
|
+
expect(response.headers.get('X-Parent-Header')).toBe('parent-value')
|
|
255
|
+
expect(response.headers.get('X-Child-Header')).toBe('child-value')
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
test('behavior: headers as object', async () => {
|
|
259
|
+
const handler1 = Handler.from()
|
|
260
|
+
handler1.get('/test', () => new Response('test'))
|
|
261
|
+
|
|
262
|
+
const handler = Handler.compose([handler1], {
|
|
263
|
+
headers: {
|
|
264
|
+
'Access-Control-Allow-Origin': '*',
|
|
265
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
266
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
267
|
+
},
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
271
|
+
expect(response.status).toBe(200)
|
|
272
|
+
expect(await response.text()).toBe('test')
|
|
273
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
274
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
275
|
+
'POST, OPTIONS',
|
|
276
|
+
)
|
|
277
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
278
|
+
'Content-Type, Authorization',
|
|
279
|
+
)
|
|
280
|
+
})
|
|
281
|
+
|
|
77
282
|
describe('integration', () => {
|
|
78
283
|
const handler1 = Handler.from()
|
|
79
284
|
handler1.get('/foo', () => new Response('foo'))
|
|
@@ -256,6 +461,117 @@ describe('from', () => {
|
|
|
256
461
|
expect(data).toEqual({ message: 'hello from listener' })
|
|
257
462
|
})
|
|
258
463
|
|
|
464
|
+
test('behavior: headers', async () => {
|
|
465
|
+
const headers = new Headers({
|
|
466
|
+
'Access-Control-Allow-Origin': '*',
|
|
467
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
468
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
const handler = Handler.from({ headers })
|
|
472
|
+
handler.get('/test', () => new Response('test'))
|
|
473
|
+
|
|
474
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
475
|
+
expect(response.status).toBe(200)
|
|
476
|
+
expect(await response.text()).toBe('test')
|
|
477
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
478
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
479
|
+
'POST, OPTIONS',
|
|
480
|
+
)
|
|
481
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
482
|
+
'Content-Type, Authorization',
|
|
483
|
+
)
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
test('behavior: headers + OPTIONS', async () => {
|
|
487
|
+
const headers = new Headers({
|
|
488
|
+
'Access-Control-Allow-Origin': '*',
|
|
489
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
490
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
491
|
+
'Access-Control-Max-Age': '86400',
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
const handler = Handler.from({ headers })
|
|
495
|
+
handler.get('/test', () => new Response('test'))
|
|
496
|
+
|
|
497
|
+
const response = await handler.fetch(
|
|
498
|
+
new Request('http://localhost/test', {
|
|
499
|
+
method: 'OPTIONS',
|
|
500
|
+
}),
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
expect(response.status).toBe(200)
|
|
504
|
+
expect(await response.text()).toBe('')
|
|
505
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
506
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
507
|
+
'POST, OPTIONS',
|
|
508
|
+
)
|
|
509
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
510
|
+
'Content-Type, Authorization',
|
|
511
|
+
)
|
|
512
|
+
expect(response.headers.get('Access-Control-Max-Age')).toBe('86400')
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
test('behavior: headers + 404', async () => {
|
|
516
|
+
const headers = new Headers({
|
|
517
|
+
'Access-Control-Allow-Origin': '*',
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
const handler = Handler.from({ headers })
|
|
521
|
+
handler.get('/test', () => new Response('test'))
|
|
522
|
+
|
|
523
|
+
const response = await handler.fetch(
|
|
524
|
+
new Request('http://localhost/nonexistent'),
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
expect(response.status).toBe(404)
|
|
528
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
test('behavior: headers propagation from routes', async () => {
|
|
532
|
+
const headers = new Headers({
|
|
533
|
+
'Access-Control-Allow-Origin': '*',
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
const handler = Handler.from({ headers })
|
|
537
|
+
handler.get('/test', () => {
|
|
538
|
+
const response = new Response('test')
|
|
539
|
+
response.headers.set('X-Custom-Header', 'custom-value')
|
|
540
|
+
response.headers.set('Content-Type', 'text/plain')
|
|
541
|
+
return response
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
545
|
+
|
|
546
|
+
expect(response.status).toBe(200)
|
|
547
|
+
expect(await response.text()).toBe('test')
|
|
548
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
549
|
+
expect(response.headers.get('X-Custom-Header')).toBe('custom-value')
|
|
550
|
+
expect(response.headers.get('Content-Type')).toBe('text/plain')
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
test('behavior: headers as object', async () => {
|
|
554
|
+
const handler = Handler.from({
|
|
555
|
+
headers: {
|
|
556
|
+
'Access-Control-Allow-Origin': '*',
|
|
557
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
558
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
559
|
+
},
|
|
560
|
+
})
|
|
561
|
+
handler.get('/test', () => new Response('test'))
|
|
562
|
+
|
|
563
|
+
const response = await handler.fetch(new Request('http://localhost/test'))
|
|
564
|
+
expect(response.status).toBe(200)
|
|
565
|
+
expect(await response.text()).toBe('test')
|
|
566
|
+
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
567
|
+
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
568
|
+
'POST, OPTIONS',
|
|
569
|
+
)
|
|
570
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
571
|
+
'Content-Type, Authorization',
|
|
572
|
+
)
|
|
573
|
+
})
|
|
574
|
+
|
|
259
575
|
describe('integration', () => {
|
|
260
576
|
const handler = Handler.from()
|
|
261
577
|
handler.get('/foo', () => new Response('foo'))
|
package/src/server/Handler.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRouter,
|
|
3
|
+
type Middleware,
|
|
3
4
|
type Router,
|
|
4
5
|
type RouterOptions,
|
|
5
6
|
} from '@remix-run/fetch-router'
|
|
@@ -27,6 +28,7 @@ export function compose(
|
|
|
27
28
|
const path = options.path ?? '/'
|
|
28
29
|
|
|
29
30
|
return from({
|
|
31
|
+
...options,
|
|
30
32
|
async defaultHandler(context) {
|
|
31
33
|
const url = new URL(context.request.url)
|
|
32
34
|
if (!url.pathname.startsWith(path))
|
|
@@ -44,7 +46,7 @@ export function compose(
|
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
export declare namespace compose {
|
|
47
|
-
export type Options = {
|
|
49
|
+
export type Options = from.Options & {
|
|
48
50
|
/** The path to use for the handler. */
|
|
49
51
|
path?: string | undefined
|
|
50
52
|
}
|
|
@@ -57,7 +59,11 @@ export declare namespace compose {
|
|
|
57
59
|
* @returns Handler instance
|
|
58
60
|
*/
|
|
59
61
|
export function from(options: from.Options = {}): Handler {
|
|
60
|
-
const router = createRouter(
|
|
62
|
+
const router = createRouter({
|
|
63
|
+
...options,
|
|
64
|
+
middleware: [headers(options.headers), preflight(options.headers)],
|
|
65
|
+
})
|
|
66
|
+
|
|
61
67
|
return {
|
|
62
68
|
...router,
|
|
63
69
|
listener: RequestListener.fromFetchHandler((request) => {
|
|
@@ -67,7 +73,10 @@ export function from(options: from.Options = {}): Handler {
|
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
export declare namespace from {
|
|
70
|
-
export type Options = RouterOptions
|
|
76
|
+
export type Options = RouterOptions & {
|
|
77
|
+
/** Headers to add to the response. */
|
|
78
|
+
headers?: Headers | Record<string, string> | undefined
|
|
79
|
+
}
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
/**
|
|
@@ -193,7 +202,7 @@ export function keyManager(options: keyManager.Options) {
|
|
|
193
202
|
return undefined
|
|
194
203
|
})()
|
|
195
204
|
|
|
196
|
-
const router = from()
|
|
205
|
+
const router = from(options)
|
|
197
206
|
|
|
198
207
|
// Get challenge for WebAuthn credential creation
|
|
199
208
|
router.get(`${path}/challenge`, async () => {
|
|
@@ -295,7 +304,7 @@ export function keyManager(options: keyManager.Options) {
|
|
|
295
304
|
}
|
|
296
305
|
|
|
297
306
|
export declare namespace keyManager {
|
|
298
|
-
export type Options = {
|
|
307
|
+
export type Options = from.Options & {
|
|
299
308
|
/** The KV store to use for key management. */
|
|
300
309
|
kv: Kv.Kv
|
|
301
310
|
/** The path to use for the handler. */
|
|
@@ -607,7 +616,7 @@ export function feePayer(options: feePayer.Options) {
|
|
|
607
616
|
}
|
|
608
617
|
|
|
609
618
|
export declare namespace feePayer {
|
|
610
|
-
export type Options = {
|
|
619
|
+
export type Options = from.Options & {
|
|
611
620
|
/** Account to use as the fee payer. */
|
|
612
621
|
account: LocalAccount
|
|
613
622
|
/** Function to call before handling the request. */
|
|
@@ -615,15 +624,47 @@ export declare namespace feePayer {
|
|
|
615
624
|
/** Path to use for the handler. */
|
|
616
625
|
path?: string | undefined
|
|
617
626
|
} & OneOf<
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
627
|
+
| {
|
|
628
|
+
/** Client to use. */
|
|
629
|
+
client: Client
|
|
630
|
+
}
|
|
631
|
+
| {
|
|
632
|
+
/** Chain to use. */
|
|
633
|
+
chain: Chain
|
|
634
|
+
/** Transport to use. */
|
|
635
|
+
transport: Transport
|
|
636
|
+
}
|
|
637
|
+
>
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** @internal */
|
|
641
|
+
function normalizeHeaders(headers?: Headers | Record<string, string>): Headers {
|
|
642
|
+
if (!headers) return new Headers()
|
|
643
|
+
if (headers instanceof Headers) return headers
|
|
644
|
+
return new Headers(headers)
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** @internal */
|
|
648
|
+
function headers(headers?: Headers | Record<string, string>): Middleware {
|
|
649
|
+
const normalizedHeaders = normalizeHeaders(headers)
|
|
650
|
+
return async (_, next) => {
|
|
651
|
+
const response = await next()
|
|
652
|
+
const headers = new Headers(response.headers)
|
|
653
|
+
for (const [key, value] of normalizedHeaders.entries())
|
|
654
|
+
headers.set(key, value)
|
|
655
|
+
return new Response(response.body, {
|
|
656
|
+
headers,
|
|
657
|
+
status: response.status,
|
|
658
|
+
statusText: response.statusText,
|
|
659
|
+
})
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/** @internal */
|
|
664
|
+
function preflight(headers?: Headers | Record<string, string>): Middleware {
|
|
665
|
+
const normalizedHeaders = normalizeHeaders(headers)
|
|
666
|
+
return async (context) => {
|
|
667
|
+
if (context.request.method === 'OPTIONS')
|
|
668
|
+
return new Response(null, { headers: normalizedHeaders })
|
|
669
|
+
}
|
|
629
670
|
}
|