Commit a1ed745f authored by nanahira's avatar nanahira

allow middleware next pass args to override

parent 6a288824
......@@ -6,6 +6,7 @@ import {
MiddlewareAcceptResult,
MiddlewareErrorHandler,
MiddlewareReturn,
MiddlewareNextArgs,
} from './types';
export class DynamicMiddlewareDispatcher<F extends AnyFunc> {
......@@ -21,34 +22,42 @@ export class DynamicMiddlewareDispatcher<F extends AnyFunc> {
this.options.acceptResult || ((res) => res != null);
const errorHandler: MiddlewareErrorHandler<F> =
this.options.errorHandler || ((e, args, next) => next());
const dispatch = async (i: number): MiddlewareResult<F> => {
const dispatch = async (
i: number,
useArgs: Parameters<F>,
): MiddlewareResult<F> => {
if (i >= mws.length) return undefined;
const mw = mws[i];
let nextCalled = false;
const next = async (): MiddlewareResult<F> => {
const next = async (
...passedArgs: MiddlewareNextArgs<F>
): MiddlewareResult<F> => {
if (nextCalled) {
return undefined;
}
nextCalled = true;
return dispatch(i + 1);
return dispatch(
i + 1,
passedArgs.length === 0 ? useArgs : (passedArgs as Parameters<F>),
);
};
const runMw = async (cb: () => MiddlewareReturn<F>) => {
const res = await cb();
if (!nextCalled && !(await acceptResult(res))) {
return dispatch(i + 1);
return dispatch(i + 1, useArgs);
}
return res;
};
try {
return await runMw(() => mw(...args, next));
return await runMw(() => mw(...useArgs, next));
} catch (e) {
return await runMw(() => errorHandler(e, args, next));
return await runMw(() => errorHandler(e, useArgs, next));
}
};
return dispatch(0);
return dispatch(0, args);
}
}
import { Middleware, MiddlewareResult } from './types';
import { Middleware, MiddlewareNext, MiddlewareResult } from './types';
import { AnyClass, ClassType } from '../types';
import { DynamicMiddlewareDispatcher } from './dynamic-middleware-dispatcher';
......@@ -93,6 +93,10 @@ export class ProtoMiddlewareDispatcher<
}
}
result.push((...args) => {
return args[args.length - 2]; // inst
});
return result;
}
}
......@@ -4,7 +4,10 @@ export type AnyFunc = (...args: any[]) => any;
export type MiddlewareValue<F extends AnyFunc> = Awaited<ReturnType<F>>;
export type MiddlewareResult<F extends AnyFunc> = Promise<MiddlewareValue<F>>;
export type MiddlewareNext<F extends AnyFunc> = () => MiddlewareResult<F>;
export type MiddlewareNextArgs<F extends AnyFunc> = Parameters<F> | [];
export type MiddlewareNext<F extends AnyFunc> = (
...args: MiddlewareNextArgs<F>
) => MiddlewareResult<F>;
export type MiddlewareArgs<F extends AnyFunc> = [
...args: Parameters<F>,
next: MiddlewareNext<F>,
......
import { ProtoMiddlewareDispatcher } from '../src/middleware-dispatcher';
describe('ProtoMiddlewareDispatcher', () => {
class Base {}
class Base {
value: number;
}
class Sub extends Base {}
it('builds middlewares by prototype chain (prior: Base->Sub, normal: Sub->Base)', async () => {
......@@ -26,20 +28,31 @@ describe('ProtoMiddlewareDispatcher', () => {
);
d.middleware(Sub, async (x, inst, next) => {
order.push('sub:normal');
return next();
expect(inst).toBeInstanceOf(Sub);
expect(inst.value).toBe(5);
const newSub = new Sub();
newSub.value = inst.value + x;
return next(7, newSub); // override args
});
d.middleware(Base, async (x, inst) => {
d.middleware(Base, async (x, inst, next) => {
order.push('base:normal');
return x * 10;
expect(inst).toBeInstanceOf(Base);
expect(inst.value).toBe(8); // 5 + 3
expect(x).toBe(7);
++inst.value;
return next();
});
const res = await d.dispatch(3, new Sub());
expect(res).toBe(30);
const sub = new Sub();
sub.value = 5;
const res = await d.dispatch(3, sub);
expect(order).toEqual([
'base:prior',
'sub:prior',
'sub:normal',
'base:normal',
]);
expect(res).toBeInstanceOf(Sub);
expect(res.value).toBe(9); // 5 + 3 + 1
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment