Skip to content

Commit

Permalink
feat: Move to TypeScript 5 non-experimental decorators (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl committed Feb 25, 2024
1 parent 55b910c commit 05bde46
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 155 deletions.
33 changes: 28 additions & 5 deletions main/hooks/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { AsyncMiddleware, compose } from './compose.ts';
import { convertOptions, HookContext, HookContextData, HookOptions, setManager, setMiddleware } from './base.ts';
import {
convertOptions,
HookContext,
HookContextData,
HookOptions,
setManager,
setMiddleware
} from './base.ts';
import { copyFnProperties, copyProperties } from './utils.ts';

export function getOriginal(fn: any): any {
Expand All @@ -23,7 +30,7 @@ export function functionHooks<F>(fn: F, managerOrMiddleware: HookOptions) {
// Assemble the hook chain
const hookChain: AsyncMiddleware[] = [
// Return `ctx.result` or the context
(ctx, next) => next().then(() => returnContext ? ctx : ctx.result),
(ctx, next) => next().then(() => (returnContext ? ctx : ctx.result))
];

// Create the hook chain by calling the `collectMiddleware function
Expand All @@ -41,7 +48,7 @@ export function functionHooks<F>(fn: F, managerOrMiddleware: HookOptions) {
ctx.result = result;

return next();
},
}
);
}

Expand All @@ -60,7 +67,7 @@ export function functionHooks<F>(fn: F, managerOrMiddleware: HookOptions) {
Context: manager.getContextClass(),
createContext: (data: HookContextData = {}) => {
return new wrapper.Context(data);
},
}
});
}

Expand Down Expand Up @@ -90,10 +97,26 @@ export function objectHooks(obj: any, hooks: HookMap | AsyncMiddleware[]) {
}

export const hookDecorator = (managerOrMiddleware?: HookOptions) => {
return (target: any, context: DecoratorContext) => {
const manager = convertOptions(managerOrMiddleware);

if (context.kind === 'class') {
setManager(target.prototype, manager);
return target;
} else if (context.kind === 'method') {
const method = String(context.name);
return functionHooks(target, manager.props({ method }));
}

throw new Error('Can not apply hooks.');
};
};

export const legacyDecorator = (managerOrMiddleware?: HookOptions) => {
const wrapper: any = (
_target: any,
method: string,
descriptor: TypedPropertyDescriptor<any>,
descriptor: TypedPropertyDescriptor<any>
): TypedPropertyDescriptor<any> => {
const manager = convertOptions(managerOrMiddleware);

Expand Down
14 changes: 8 additions & 6 deletions main/hooks/test/decorator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ it('hook decorator on method and classes with inheritance', async () => {
])
class TopLevel {}

@hooks([async (ctx, next) => {
ctx.arguments[0] += ' NameFromDummyClass';
@hooks([
async (ctx, next) => {
ctx.arguments[0] += ' NameFromDummyClass';

await next();
await next();

ctx.result += ' ResultFromDummyClass';
}])
ctx.result += ' ResultFromDummyClass';
},
])
class DummyClass extends TopLevel {
@hooks(
middleware([
Expand Down Expand Up @@ -63,6 +65,6 @@ it('error cases', () => {
assertThrows(
() => hooks([])({}, 'test', { value: 'not a function' }),
undefined,
`Can not apply hooks. 'test' is not a function`,
`Can not apply hooks.`,
);
});
Loading

0 comments on commit 05bde46

Please sign in to comment.