Socket
Socket
Sign inDemoInstall

@poppinss/hooks

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@poppinss/hooks - npm Package Compare versions

Comparing version 7.0.0-0 to 7.1.0-0

14

build/src/hooks.d.ts
import { Runner } from './runner.js';
import { HookHandler, HookProvider } from './types.js';
import { HookHandler, HookHandlerProvider } from './types.js';
export declare class Hooks<Events extends Record<string, [any[], any[]]>> {
#private;
all(): { [Event in keyof Events]: Map<Event, Set<HookHandler<Events[Event][0], Events[Event][1]>>>; }[keyof Events];
providers(): Set<HookProvider>;
has<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]>): boolean;
add<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]>): this;
remove<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]>): boolean;
all(): { [Event in keyof Events]: Map<Event, Set<HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>>>; }[keyof Events];
has<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;
add<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): this;
remove<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;
clear(event?: keyof Events): void;
provider(provider: HookProvider): this;
hasProvider(provider: HookProvider): boolean;
removeProvider(provider: HookProvider): boolean;
merge(hooks: Hooks<Events>): void;
runner<Event extends Extract<keyof Events, string>>(action: Event): Runner<Events[Event][0], Events[Event][1]>;
}
import { Runner } from './runner.js';
export class Hooks {
#hooks = new Map();
#hookProviders = new Set();
all() {
return this.#hooks;
}
providers() {
return this.#hookProviders;
}
has(event, handler) {

@@ -40,12 +36,2 @@ const handlers = this.#hooks.get(event);

}
provider(provider) {
this.#hookProviders.add(provider);
return this;
}
hasProvider(provider) {
return this.#hookProviders.has(provider);
}
removeProvider(provider) {
return this.#hookProviders.delete(provider);
}
merge(hooks) {

@@ -57,9 +43,6 @@ hooks.all().forEach((actionHooks, action) => {

});
hooks.providers().forEach((provider) => {
this.provider(provider);
});
}
runner(action) {
return new Runner(action, this.#hookProviders, this.#hooks.get(action));
return new Runner(action, this.#hooks.get(action));
}
}

@@ -1,2 +0,2 @@

import { HookHandler, HookProvider, HandlerExecutor, ProviderExecutor } from './types.js';
import { HookHandler, HookHandlerProvider } from './types.js';
export declare class Runner<HookArgs extends any[], CleanUpArgs extends any[]> {

@@ -6,8 +6,6 @@ #private;

get isCleanupPending(): boolean;
constructor(action: string, hookProviders: Set<HookProvider>, hookHandlers?: Set<HookHandler<HookArgs, CleanUpArgs>>);
constructor(action: string, hookHandlers?: Set<HookHandler<HookArgs, CleanUpArgs> | HookHandlerProvider<HookArgs, CleanUpArgs>>);
without(handlersToIgnore?: string[]): this;
executor(callback: HandlerExecutor): this;
providerExecutor(callback: ProviderExecutor): this;
run(...data: HookArgs): Promise<void>;
cleanup(...data: CleanUpArgs): Promise<void>;
}

@@ -1,12 +0,4 @@

const defaultHandlerExecutor = (handler, _, ...data) => handler(...data);
const defaultProviderExecutor = (provider, event, ...data) => {
const providerInstance = new provider();
if (typeof providerInstance[event] === 'function') {
return providerInstance[event](...data);
}
};
export class Runner {
action;
#hookHandlers;
#hookProviders;
#cleanupHandlers = [];

@@ -16,10 +8,7 @@ #state = 'idle';

#skipAllHooks = false;
#handlerExecutor = defaultHandlerExecutor;
#providerExecutor = defaultProviderExecutor;
get isCleanupPending() {
return this.#state === 'cleanup_pending';
}
constructor(action, hookProviders, hookHandlers) {
constructor(action, hookHandlers) {
this.action = action;
this.#hookProviders = hookProviders;
this.#hookHandlers = hookHandlers || new Set();

@@ -40,10 +29,2 @@ }

}
executor(callback) {
this.#handlerExecutor = callback;
return this;
}
providerExecutor(callback) {
this.#providerExecutor = callback;
return this;
}
async run(...data) {

@@ -59,3 +40,5 @@ if (this.#state !== 'idle') {

if (this.#filter(handler.name)) {
const result = await this.#handlerExecutor(handler, false, ...data);
const result = await (typeof handler === 'function'
? handler(...data)
: handler.handle(this.action, ...data));
if (typeof result === 'function') {

@@ -66,10 +49,2 @@ this.#cleanupHandlers.push(result);

}
for (let provider of this.#hookProviders) {
if (this.#filter(`${provider.name}.${this.action}`)) {
const result = await this.#providerExecutor(provider, this.action, ...data);
if (typeof result === 'function') {
this.#cleanupHandlers.push(result);
}
}
}
}

@@ -83,3 +58,3 @@ async cleanup(...data) {

while (startIndex--) {
await this.#handlerExecutor(this.#cleanupHandlers[startIndex], true, ...data);
await this.#cleanupHandlers[startIndex](...data);
}

@@ -86,0 +61,0 @@ this.#state = 'cleanup_completed';

export declare type CleanupHandler<Args extends any[]> = (...args: Args) => void | Promise<void>;
export declare type HookHandler<Args extends any[], CleanUpArgs extends any[]> = (...args: Args) => void | CleanupHandler<CleanUpArgs> | Promise<void> | Promise<CleanupHandler<CleanUpArgs>>;
export declare type HandlerExecutor = (handler: (...args: any[]) => any, isCleanupHandler: boolean, ...args: any[]) => void | Promise<void>;
export declare type HookProvider = new (...args: any[]) => any;
export declare type ProviderExecutor = (Provider: HookProvider, event: string, ...args: any[]) => void | Promise<void>;
export declare type HookHandlerProvider<Args extends any[], CleanUpArgs extends any[]> = {
name: string;
handle(event: string, ...args: Args): void | CleanupHandler<CleanUpArgs> | Promise<void> | Promise<CleanupHandler<CleanUpArgs>>;
};
{
"name": "@poppinss/hooks",
"version": "7.0.0-0",
"version": "7.1.0-0",
"description": "A no brainer hooks module for execute before/after lifecycle hooks",

@@ -5,0 +5,0 @@ "main": "build/index.js",

@@ -10,3 +10,2 @@ # @poppinss/hooks

- Hooks can return cleanup functions that are executed to perform the cleanup.
- Alongside "hooks as functions", you can also register hook providers, which encapsulate event handlers inside a class.
- Super lightweight

@@ -50,2 +49,15 @@

You can also define hook as an object with the `name` and the `handle` method property. This is usually helpful when you want to specify a custom name for the hook, or re-use the same handle method multiple times.
```ts
const hooks = new Hooks()
function handleSave() {}
hooks.add('saving', { name: 'beforeSave', handle: handleSave })
hooks.add('creating', { name: 'beforeCreate', handle: handleSave })
```
The `handle` method receives the first argument as the event name, followed by the rest of the arguments supplied during runtime.
## Running hooks

@@ -118,35 +130,2 @@ You can execute hooks using the Hooks Runner. You can create a new runner instance by calling the `hooks.runner` method and passing the event name for which you want to execute hooks.

## Hook Providers
Hook providers are classes with the event lifecycle methods on them. Providers are great when you want to listen to multiple events to create a single cohesive feature. Again, taking the example of models, you can make a hook provider listen for all the hooks and manage a changelog of table columns.
```ts
class ChangeSetProvider {
created() {
// listens for created event
}
updated() {
// listens for updated event
}
deleted() {
// listens for deleted event
}
}
```
Next, register the provider as follows.
```ts
hooks.provider(ChangeSetProvider)
```
Run hooks
```ts
await hooks.runner('created').run()
await hooks.runner('updated').run()
await hooks.runner('deleted').run()
```
## Run without hook handlers

@@ -167,57 +146,2 @@ You can exclude certain hook handlers from executing using the `without` method.

You can specify the provider class and the method name with hook providers.
```ts
class ChangeSetProvider {
created() {}
}
hooks.provider(ChangeSetProvider)
await hooks
.runner('created')
.without(['ChangeSetProvider.created'])
.run()
```
## Custom executors
The hooks runner allows you to define custom executors for calling the hook callback functions or the provider lifecycle methods. They are helpful when you want to tweak how a method should run.
For example, AdonisJS uses the IoC container to call the provider lifecycle methods.
In the following example, the custom executor is responsible for calling the hook callback functions.
```ts
hooks.add('saving', function hashPassword () {})
hooks.add('saving', function generateDefaultAvatar () {})
hooks
.runner('saving')
.executor((handler, isCleanupFunction, ...data) => {
console.log(handler.name)
return handler(...data)
})
.run(model)
```
Similarly, you can also define a custom executor for the provider classes.
```ts
class ChangeSetProvider {
created() {}
}
hooks.provider(ChangeSetProvider)
await hooks
.runner('created')
.providerExecutor((Provider, event, ...data) => {
const provider = new Provider()
if (typeof provider[event] === 'function') {
return provider[event](...data)
}
})
.run(model)
```
## Event types

@@ -224,0 +148,0 @@ You can also specify the types of supported events and their arguments well in advance as follows.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc