Skip to content

Commit

Permalink
feat: allow unregistering hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoBechtel committed Apr 2, 2023
1 parent 2d2381c commit 56c4292
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
37 changes: 33 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

## Table of Contents

- [About](#About)
- [About](#about)
- [Features](#Features)
- [Installation](#Install)
- [Usage](#Usage)
- [Installation](#install)
- [Usage](#usage)
- [As a library author](#As-a-library-author)
- [As a plugin author](#As-a-plugin-author)
- [Used by](#Used-by)
- [Used by](#used-by)
- [Development / Contributing](#Development-Contributing)

## About
Expand Down Expand Up @@ -150,6 +150,35 @@ const { data } = await hooks.call('before:write', {
});
```

#### 4. Unregister hooks

You can unregister hooks by:

##### a) Calling the returned unregister function

```js
const unregister = hooks.register('before:write', myHookFunction);
unregister();

// for registerMany
const unregisterMany = hooks.registerMany({
'before:write': myHookFunction,
});
unregisterMany();
```

##### b) Calling `hooks.unregister`

```js
hooks.register('before:write', myHookFunction);

// unregister a specific callback for the 'before:write' hook
hooks.unregister('before:write', myHookFunction);

// unregister all callbacks for the 'before:write' hook
hooks.unregister('before:write');
```

### As plugin author

#### Create a plugin
Expand Down
42 changes: 42 additions & 0 deletions src/hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,45 @@ test('allow asynchronous functions as middleware', (done) => {
});
hooks.call('test:hook');
});

it('should unregister a specific hook', async () => {
const hooks = createHooks<{
'test:hook': Hook<number, void>;
}>();

hooks.register('test:hook', (value) => {
return value * 2;
});
const unregisterTestHook2 = hooks.register('test:hook', (value) => {
return value * 3;
});

let result = await hooks.call('test:hook', { args: 1 });
expect(result).toEqual(6);

// Unregister testHook2 and call the hooks again
unregisterTestHook2();
result = await hooks.call('test:hook', { args: 1 });
expect(result).toEqual(2);
});

it('should unregister all hooks for a given name', async () => {
const hooks = createHooks<{
'test:hook': Hook<number, void>;
}>();

hooks.register('test:hook', (value) => {
return value * 2;
});
hooks.register('test:hook', (value) => {
return value * 3;
});

let result = await hooks.call('test:hook', { args: 1 });
expect(result).toEqual(6);

// Unregister all hooks for 'test:hook' and call the hooks again
hooks.unregister('test:hook');
result = await hooks.call('test:hook', { args: 1 });
expect(result).toEqual(1);
});
18 changes: 18 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ export function createHooks<T extends Hooks>() {
function register(name: K, hook: T[K]) {
if (!hooks[name]) hooks[name] = [];
hooks[name]?.push(hook);

return () => unregister(name, hook);
}

function unregister(name: K, hook?: T[K]) {
if (!hooks[name]) return;
if (hook) {
hooks[name] = hooks[name]?.filter((h) => h !== hook);
} else {
hooks[name] = undefined;
}
}

/**
Expand All @@ -106,12 +117,19 @@ export function createHooks<T extends Hooks>() {
Object.entries(hooks).forEach(([hookName, hook]) => {
register(hookName, hook);
});

return () => {
Object.entries(hooks).forEach(([hookName, hook]) => {
unregister(hookName, hook);
});
};
}

return {
call,
wrap,
register,
unregister,
registerMany,
};
}
Expand Down

0 comments on commit 56c4292

Please sign in to comment.