Skip to content

Commit

Permalink
feat: Add support for regular before, after and error hooks (#92)
Browse files Browse the repository at this point in the history
This pulls over the code for Regular hooks from this PR: feathersjs/feathers#2483

Co-authored-by: marshall_thompson2 <marshall_thompson2@apple.com>
Co-authored-by: daffl <daff@neyeon.com>
  • Loading branch information
3 people committed Nov 19, 2021
1 parent 73c4dc0 commit 8e4328f
Show file tree
Hide file tree
Showing 8 changed files with 570 additions and 304 deletions.
134 changes: 58 additions & 76 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions packages/hooks/src/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Middleware } from './compose';
import { AsyncMiddleware } from './compose';
import { copyToSelf, copyProperties } from './utils';

export const HOOKS: string = Symbol('@feathersjs/hooks') as any;
Expand Down Expand Up @@ -30,7 +30,7 @@ export type HookDefaultsInitializer = (self?: any, args?: any[], context?: HookC
export class HookManager {
_parent?: this|null = null;
_params: string[]|null = null;
_middleware: Middleware[]|null = null;
_middleware: AsyncMiddleware[]|null = null;
_props: HookContextData|null = null;
_defaults?: HookDefaultsInitializer;

Expand All @@ -40,13 +40,13 @@ export class HookManager {
return this;
}

middleware (middleware?: Middleware[]) {
middleware (middleware?: AsyncMiddleware[]) {
this._middleware = middleware?.length ? middleware : null;

return this;
}

getMiddleware (): Middleware[]|null {
getMiddleware (): AsyncMiddleware[]|null {
const previous = this._parent?.getMiddleware();

if (previous && this._middleware) {
Expand All @@ -56,7 +56,7 @@ export class HookManager {
return previous || this._middleware;
}

collectMiddleware (self: any, _args: any[]): Middleware[] {
collectMiddleware (self: any, _args: any[]): AsyncMiddleware[] {
const otherMiddleware = getMiddleware(self);
const middleware = this.getMiddleware();

Expand Down Expand Up @@ -178,7 +178,7 @@ export class HookManager {
}
}

export type HookOptions = HookManager|Middleware[]|null;
export type HookOptions = HookManager|AsyncMiddleware[]|null;

export function convertOptions (options: HookOptions = null) {
if (!options) {
Expand All @@ -200,13 +200,13 @@ export function setManager<T> (target: T, manager: HookManager) {
return target;
}

export function getMiddleware (target: any): Middleware[]|null {
export function getMiddleware (target: any): AsyncMiddleware[]|null {
const manager = getManager(target);

return manager ? manager.getMiddleware() : null;
}

export function setMiddleware<T> (target: T, middleware: Middleware[]) {
export function setMiddleware<T> (target: T, middleware: AsyncMiddleware[]) {
const manager = new HookManager().middleware(middleware);

return setManager(target, manager);
Expand Down
9 changes: 5 additions & 4 deletions packages/hooks/src/compose.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// TypeScript port of koa-compose (https://github.com/koajs/compose)
export type NextFunction = () => Promise<any>;

export type Middleware<T = any> = (context: T, next: NextFunction) => Promise<any>;
export type AsyncMiddleware<T = any> = (context: T, next: NextFunction) => Promise<any>;
export type Middleware<T = any> = AsyncMiddleware<T>;

export function compose<T = any> (middleware: Middleware<T>[]) {
export function compose<T = any> (middleware: AsyncMiddleware<T>[]) {
if (!Array.isArray(middleware)) {
throw new TypeError('Middleware stack must be an array!');
}
Expand All @@ -14,7 +15,7 @@ export function compose<T = any> (middleware: Middleware<T>[]) {
}
}

return function (this: any, context: T, next?: Middleware<T>) {
return function (this: any, context: T, next?: AsyncMiddleware<T>) {
// last called middleware #
let index: number = -1;

Expand All @@ -27,7 +28,7 @@ export function compose<T = any> (middleware: Middleware<T>[]) {

index = i;

let fn: Middleware|undefined = middleware[i];
let fn: AsyncMiddleware|undefined = middleware[i];

if (i === middleware.length) {
fn = next;
Expand Down
6 changes: 3 additions & 3 deletions packages/hooks/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { compose, Middleware } from './compose';
import { compose, AsyncMiddleware } from './compose';
import {
HookContext, setManager, HookContextData, HookOptions, convertOptions, setMiddleware
} from './base';
Expand All @@ -23,7 +23,7 @@ export function functionHooks <F> (fn: F, managerOrMiddleware: HookOptions) {
// Initialize the context
const context = manager.initializeContext(this, args, base);
// Assemble the hook chain
const hookChain: Middleware[] = [
const hookChain: AsyncMiddleware[] = [
// Return `ctx.result` or the context
(ctx, next) => next().then(() => returnContext ? ctx : ctx.result)
];
Expand Down Expand Up @@ -68,7 +68,7 @@ export type HookMap<O = any> = {
[L in keyof O]?: HookOptions;
}

export function objectHooks (_obj: any, hooks: HookMap|Middleware[]) {
export function objectHooks (_obj: any, hooks: HookMap|AsyncMiddleware[]) {
const obj = typeof _obj === 'function' ? _obj.prototype : _obj;

if (Array.isArray(hooks)) {
Expand Down
Loading

0 comments on commit 8e4328f

Please sign in to comment.