Skip to content

Commit

Permalink
fix(hooks): fix some errors for feathers integration (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
bertho-zero committed Dec 11, 2020
1 parent 73598a4 commit fcfc0ca
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 41 deletions.
42 changes: 19 additions & 23 deletions packages/hooks/src/base.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Middleware } from './compose';
import { copyToSelf } from './utils';
import { copyToSelf, copyProperties } from './utils';

export const HOOKS: string = Symbol('@feathersjs/hooks') as any;

Expand Down Expand Up @@ -46,50 +46,42 @@ export class HookManager {
getMiddleware (): Middleware[]|null {
const previous = this._parent?.getMiddleware();

if (previous) {
if (this._middleware) {
return previous.concat(this._middleware);
}

return previous;
if (previous && this._middleware) {

This comment has been minimized.

Copy link
@J3m5

J3m5 Dec 11, 2020

Suggestion: This type of condition can be simplified with an "early return" or "fail fast" logic.

  if (!previous) return this._middleware;
  return previous.concat(this._middleware);

This can be applied at line 60, 80 and 96 too.

This comment has been minimized.

Copy link
@bertho-zero

bertho-zero Dec 11, 2020

Author Collaborator

It is not because there is previous that there is middleware, the concat must be done only when there are 2.

It is the concat which is slow and should be avoided as soon as possible.

This comment has been minimized.

Copy link
@J3m5

J3m5 Dec 11, 2020

Ah yes, I went too fast, I assumed this._middleware was always truthy.

return previous.concat(this._middleware);
}

return this._middleware;
return previous || this._middleware;
}

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

if (otherMiddleware) {
if (middleware) {
return otherMiddleware.concat(middleware);
}

return otherMiddleware;
if (otherMiddleware && middleware) {
return otherMiddleware.concat(middleware);
}

return middleware;
return otherMiddleware || middleware;
}

props (props: HookContextData) {
if (!this._props) {
this._props = {};
}

Object.assign(this._props, props);
copyProperties(this._props, props);

return this;
}

getProps (): HookContextData {
const previous = this._parent?.getProps();

if (previous) {
return Object.assign({}, previous, this._props);
if (previous && this._props) {
return copyProperties({}, previous, this._props);
}

return this._props;
return previous || this._props;
}

params (...params: string[]) {
Expand All @@ -101,6 +93,10 @@ export class HookManager {
getParams (): string[] {
const previous = this._parent?.getParams();

if (previous && this._params) {
return previous.concat(this._params);
}

return previous || this._params;
}

Expand All @@ -114,11 +110,11 @@ export class HookManager {
const defaults = typeof this._defaults === 'function' ? this._defaults(self, args, context) : null;
const previous = this._parent?.getDefaults(self, args, context);

if (previous) {
return Object.assign({}, previous, this._props);
if (previous && defaults) {
return Object.assign({}, previous, defaults);
}

return defaults;
return previous || defaults;
}

getContextClass (Base: HookContextConstructor = HookContext): HookContextConstructor {
Expand Down Expand Up @@ -151,7 +147,7 @@ export class HookManager {
}

if (props) {
Object.assign(ContextClass.prototype, props);
copyProperties(ContextClass.prototype, props);
}

return ContextClass;
Expand Down
16 changes: 1 addition & 15 deletions packages/hooks/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,12 @@ import { compose, Middleware } from './compose';
import {
HookContext, setManager, HookContextData, HookOptions, convertOptions, setMiddleware
} from './base';
import { copyProperties } from './utils';

export function getOriginal (fn: any): any {
return typeof fn.original === 'function' ? getOriginal(fn.original) : fn;
}

function copyProperties <F> (target: F, original: any) {
const originalProps = (Object.keys(original) as any)
.concat(Object.getOwnPropertySymbols(original));

for (const prop of originalProps) {
const propDescriptor = Object.getOwnPropertyDescriptor(original, prop);

if (!target.hasOwnProperty(prop)) {
Object.defineProperty(target, prop, propDescriptor);
}
}

return target;
}

export function functionHooks <F> (fn: F, managerOrMiddleware: HookOptions) {
if (typeof fn !== 'function') {
throw new Error('Can not apply hooks to non-function');
Expand Down
2 changes: 1 addition & 1 deletion packages/hooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function middleware (mw?: Middleware[], options?: MiddlewareOptions) {

if (options) {
if (options.params) {
manager.params(options.params);
manager.params(...options.params);
}

if (options.defaults) {
Expand Down
26 changes: 24 additions & 2 deletions packages/hooks/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ export function copyToSelf (target: any) {
const getter = hasProtoDefinitions ? target.constructor.prototype.__lookupGetter__(key)
: Object.getOwnPropertyDescriptor(target, key);

if (getter && hasProtoDefinitions) {
if (hasProtoDefinitions && getter) {
target.__defineGetter__(key, getter);
target.__defineSetter__(key, target.constructor.prototype.__lookupSetter__(key));

const setter = target.constructor.prototype.__lookupSetter__(key);

if (setter) {
target.__defineSetter__(key, setter);
}
} else if (getter) {
Object.defineProperty(target, key, getter);
} else {
Expand All @@ -23,3 +28,20 @@ export function copyToSelf (target: any) {
}
}
}

export function copyProperties <F> (target: F, ...originals: any[]) {
for (const original of originals) {
const originalProps = (Object.keys(original) as any)
.concat(Object.getOwnPropertySymbols(original));

for (const prop of originalProps) {
const propDescriptor = Object.getOwnPropertyDescriptor(original, prop);

if (!target.hasOwnProperty(prop)) {
Object.defineProperty(target, prop, propDescriptor);
}
}
}

return target;
}

0 comments on commit fcfc0ca

Please sign in to comment.