1 | // deno-lint-ignore-file no-explicit-any
|
2 | export { pipe as combine } from 'ts-functional-pipe';
|
3 | import { ResolvablePromise } from '@worker-tools/resolvable-promise';
|
4 | import { AppendOnlyList } from "./utils/append-only-list.js";
|
5 | export class EffectsList extends AppendOnlyList {
|
6 | }
|
7 | /**
|
8 | * @deprecated Function might change name
|
9 | */
|
10 | export function executeEffects(effects, response) {
|
11 | var _a;
|
12 | // TODO: to reduce or reduceRight, that is the question...
|
13 | // reduceRight matches the behavior of my initial, non-compose friendly middleware model
|
14 | // which was just increasingly deep levels of wrapped function calls.
|
15 | // In that model, the effects (post-processes) of the last applied middleware were executed first.
|
16 | // Regular reduce matches the order in which middlewares are applied,
|
17 | // which probably is close what users expect to happen, anyway...
|
18 | return (_a = [...effects].reduceRight(async (response, effect) => { var _a; return (_a = effect(await response)) !== null && _a !== void 0 ? _a : response; }, response)) !== null && _a !== void 0 ? _a : response;
|
19 | }
|
20 | /**
|
21 | * A helper function to create user-defined middleware.
|
22 | *
|
23 | * Its main purpose is to allow developers to create correctly typed middleware without dealing with generics.
|
24 | * This is achieved via the `_defaultExt` parameter, which is used to infer the types of the *extension* added to the *context*.
|
25 | * As the `_` prefix implies, it is not actually used.
|
26 | * The purpose of the default extension object is solely to tell the type checker which additional keys to expect on the context object after this middleware is applied.
|
27 | * The job of adding (default) values to the context belongs to the middleware function.
|
28 | *
|
29 | * Here are some example usages. All are valid in JavaScript and TypeScript:
|
30 | *
|
31 | * ```ts
|
32 | * const fn = createMiddleware({}, _ => _)
|
33 | * const gn = createMiddleware({}, async ax => ({ ...await ax }))
|
34 | * const hn = createMiddleware({ foo: '' }, async ax => ({ ...await ax, foo: 'star' }))
|
35 | * const jn = createMiddleware({ bar: '' }, async ax => {
|
36 | * const x = await ax;
|
37 | * x.effects.push(resp => {
|
38 | * resp.headers.set('x-middleware', 'jn')
|
39 | * })
|
40 | * return { ...x, bar: 'star' }
|
41 | * })
|
42 | * const myMW = combine(fn, hn, jn, gn)
|
43 | * //=> Context & { foo: string } & { bar: string }
|
44 | * ```
|
45 | *
|
46 | * @param _defaultExt The default extension to the current context. Can also be a function that returns the extension object, to avoid unnecessary memory allocation.
|
47 | * @param middlewareFn A middleware functions: Adds the keys listed in `defaultExt` to the context
|
48 | * @returns The provided `middlewareFn` with type annotations inferred based on `defaultExt`
|
49 | */
|
50 | export function createMiddleware(_defaultExt, middlewareFn) {
|
51 | return middlewareFn;
|
52 | }
|
53 | /**
|
54 | * Takes a handler function of the form `(x: Request, ctx: Context) => Awaitable<Response>` and applies middleware to it.
|
55 | * @deprecated Name might change, errorHandler not implemented
|
56 | */
|
57 | export function withMiddleware(middleware, handler, _errorHandler) {
|
58 | return async (request, ...args) => {
|
59 | const handle = new ResolvablePromise();
|
60 | const handled = Promise.resolve(handle);
|
61 | const effects = new EffectsList();
|
62 | const ctx = { request, effects, handled, args: [request, ...args], waitUntil: () => { } };
|
63 | try {
|
64 | const userCtx = await middleware(ctx);
|
65 | const userRes = await handler(request, userCtx);
|
66 | const response = await executeEffects(effects, userRes);
|
67 | handle.resolve(response);
|
68 | return response;
|
69 | }
|
70 | catch (err) {
|
71 | throw err;
|
72 | // TODO
|
73 | // if (fallback && err instanceof Response) {
|
74 | // fallback(request, Object.assign(ctx, { response: err }))
|
75 | // }
|
76 | }
|
77 | };
|
78 | }
|
79 | //# sourceMappingURL=context.js.map |
\ | No newline at end of file |