Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@poppinss/hooks

Package Overview
Dependencies
Maintainers
3
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.1.1-6 to 7.2.0

49

build/index.d.ts

@@ -1,1 +0,48 @@

export { Hooks as default } from './src/hooks.js';
import { HookHandler, HookHandlerProvider, Runner } from './src/types.js';
/**
* Quite simple implementation register lifecycle hooks around specific events.
*
* ```ts
* const hooks = new Hooks()
*
* hooks.add('saving', function hashPassword(entity) {
* })
* ```
*/
declare class Hooks<Events extends Record<string, [any[], any[]]>> {
#private;
/**
* Get access to all the registered hooks. The return value is
* a map of the event name and a set of handlers.
*/
all(): { [Event_1 in keyof Events]: Map<Event_1, Set<HookHandler<Events[Event_1][0], Events[Event_1][1]> | HookHandlerProvider<Events[Event_1][0], Events[Event_1][1]>>>; }[keyof Events];
/**
* Find if a handler for a given event exists.
*/
has<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;
/**
* Add a hook handler for a given event. Adding the same handler twice will
* result in a noop.
*/
add<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): this;
/**
* Remove hook handler for a given event.
*/
remove<Event extends keyof Events>(event: Event, handler: HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;
/**
* Clear all the hooks for a specific event or all the
* events.
*/
clear(event?: keyof Events): void;
/**
* Merge hooks from an existing hooks instance.
*/
merge(hooks: Hooks<Events>): void;
/**
* Returns an instance of the runner to run hooks
*/
runner<Event extends Extract<keyof Events, string>>(action: Event): Runner<Events[Event][0], Events[Event][1]>;
}
export { Hooks as default };

@@ -1,9 +0,180 @@

/*
* @poppinss/hooks
*
* (c) Poppinss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { Hooks as default } from './src/hooks.js';
// src/runner.ts
var Runner = class {
constructor(action, hookHandlers) {
this.action = action;
this.#hookHandlers = hookHandlers || /* @__PURE__ */ new Set();
}
/**
* A collection of registered hook handlers
*/
#hookHandlers;
/**
* Cleanup handlers should always be an array of functions. Using a set will
* discard duplicates and it is very much possible for two hooks to return
* a shared cleanup handler.
*/
#cleanupHandlers = [];
/**
* State to perform the cleanup
*/
#state = "idle";
/**
* A collection of handlers to ignore when executed them
*/
#handlersToIgnore = [];
/**
* Whether or not to skip all the hooks
*/
#skipAllHooks = false;
/**
* Find if cleanup is pending or not
*/
get isCleanupPending() {
return this.#state === "cleanup_pending";
}
/**
* Filter to check if we should run the handler
*/
#filter(handlerName) {
return !this.#handlersToIgnore.includes(handlerName);
}
/**
* Ignore specific or all hook handlers. Calling this
* method multiple times will result in overwriting
* the existing state.
*/
without(handlersToIgnore) {
if (!handlersToIgnore) {
this.#skipAllHooks = true;
} else {
this.#skipAllHooks = false;
this.#handlersToIgnore = handlersToIgnore;
}
return this;
}
/**
* Executing hooks
*/
async #exec(reverse, data) {
if (this.#state !== "idle") {
return;
}
this.#state = "cleanup_pending";
if (this.#skipAllHooks) {
return;
}
const handlers = reverse ? Array.from(this.#hookHandlers).reverse() : this.#hookHandlers;
for (let handler of handlers) {
if (this.#filter(handler.name)) {
const result = await (typeof handler === "function" ? handler(...data) : handler.handle(this.action, ...data));
if (typeof result === "function") {
this.#cleanupHandlers.push(result);
}
}
}
}
/**
* Execute handlers
*/
async run(...data) {
return this.#exec(false, data);
}
/**
* Execute handlers in reverse order
*/
async runReverse(...data) {
return this.#exec(true, data);
}
/**
* Execute cleanup actions
*/
async cleanup(...data) {
if (!this.isCleanupPending) {
return;
}
this.#state = "cleanup_initiated";
let startIndex = this.#cleanupHandlers.length;
while (startIndex--) {
await this.#cleanupHandlers[startIndex](...data);
}
this.#state = "cleanup_completed";
this.#cleanupHandlers = [];
}
};
// src/hooks.ts
var Hooks = class {
/**
* A collection of registered hooks
*/
#hooks = /* @__PURE__ */ new Map();
/**
* Get access to all the registered hooks. The return value is
* a map of the event name and a set of handlers.
*/
all() {
return this.#hooks;
}
/**
* Find if a handler for a given event exists.
*/
has(event, handler) {
const handlers = this.#hooks.get(event);
if (!handlers) {
return false;
}
return handlers.has(handler);
}
/**
* Add a hook handler for a given event. Adding the same handler twice will
* result in a noop.
*/
add(event, handler) {
const handlers = this.#hooks.get(event);
if (!handlers) {
this.#hooks.set(event, /* @__PURE__ */ new Set());
}
this.#hooks.get(event).add(handler);
return this;
}
/**
* Remove hook handler for a given event.
*/
remove(event, handler) {
const handlers = this.#hooks.get(event);
if (!handlers) {
return false;
}
return handlers.delete(handler);
}
/**
* Clear all the hooks for a specific event or all the
* events.
*/
clear(event) {
if (!event) {
this.#hooks.clear();
return;
}
this.#hooks.delete(event);
}
/**
* Merge hooks from an existing hooks instance.
*/
merge(hooks) {
hooks.all().forEach((actionHooks, action) => {
actionHooks.forEach((handler) => {
this.add(action, handler);
});
});
}
/**
* Returns an instance of the runner to run hooks
*/
runner(action) {
return new Runner(action, this.#hooks.get(action));
}
};
export {
Hooks as default
};

@@ -1,24 +0,59 @@

import type { Runner } from './runner.js';
/**
* Exporting hooks runner as a type
*/
export { Runner };
/**
* Shape of the cleanup handler
*/
export type CleanupHandler<Args extends any[]> = (...args: Args) => void | Promise<void>;
type CleanupHandler<Args extends any[]> = (...args: Args) => void | Promise<void>;
/**
* Shape of the hook handler
*/
export type HookHandler<Args extends any[], CleanUpArgs extends any[]> = (...args: Args) => void | CleanupHandler<CleanUpArgs> | Promise<void> | Promise<CleanupHandler<CleanUpArgs>>;
type HookHandler<Args extends any[], CleanUpArgs extends any[]> = (...args: Args) => void | CleanupHandler<CleanUpArgs> | Promise<void> | Promise<CleanupHandler<CleanUpArgs>>;
/**
* Extracts args from a hook handler type
*/
export type ExtractHookHandlerArgs<Handler> = Handler extends HookHandler<infer A, infer B> ? [A, B] : never;
type ExtractHookHandlerArgs<Handler> = Handler extends HookHandler<infer A, infer B> ? [A, B] : never;
/**
* Hook represented as an object with handle method
*/
export type HookHandlerProvider<Args extends any[], CleanUpArgs extends any[]> = {
type HookHandlerProvider<Args extends any[], CleanUpArgs extends any[]> = {
name: string;
handle(event: string, ...args: Args): void | CleanupHandler<CleanUpArgs> | Promise<void> | Promise<CleanupHandler<CleanUpArgs>>;
};
/**
* Runner allows running a set of specific hook handlers for a given
* event. You can grab the instance of the runner using the "hook.runner" method.
*
* ```ts
* const hooks = new Hooks()
*
* await hooks.runner('saving').run()
* ```
*/
declare class Runner<HookArgs extends any[], CleanUpArgs extends any[]> {
#private;
action: string;
/**
* Find if cleanup is pending or not
*/
get isCleanupPending(): boolean;
constructor(action: string, hookHandlers?: Set<HookHandler<HookArgs, CleanUpArgs> | HookHandlerProvider<HookArgs, CleanUpArgs>>);
/**
* Ignore specific or all hook handlers. Calling this
* method multiple times will result in overwriting
* the existing state.
*/
without(handlersToIgnore?: string[]): this;
/**
* Execute handlers
*/
run(...data: HookArgs): Promise<void>;
/**
* Execute handlers in reverse order
*/
runReverse(...data: HookArgs): Promise<void>;
/**
* Execute cleanup actions
*/
cleanup(...data: CleanUpArgs): Promise<void>;
}
export { CleanupHandler, ExtractHookHandlerArgs, HookHandler, HookHandlerProvider, Runner };

34

package.json
{
"name": "@poppinss/hooks",
"version": "7.1.1-6",
"version": "7.2.0",
"description": "A no brainer hooks module for execute before/after lifecycle hooks",

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

"files": [
"build/src",
"build/index.d.ts",
"build/index.js"
"build"
],

@@ -25,3 +23,3 @@ "engines": {

"typecheck": "tsc --noEmit",
"compile": "npm run lint && npm run clean && tsc",
"compile": "npm run lint && npm run clean && tsup-node",
"build": "npm run compile",

@@ -48,7 +46,7 @@ "release": "np",

"@commitlint/config-conventional": "^17.7.0",
"@japa/assert": "^2.0.0-1",
"@japa/expect-type": "^2.0.0-0",
"@japa/runner": "^3.0.0-2",
"@japa/assert": "^2.0.0",
"@japa/expect-type": "^2.0.0",
"@japa/runner": "^3.0.1",
"@swc/core": "1.3.82",
"@types/node": "^20.8.3",
"@types/node": "^20.8.6",
"c8": "^8.0.1",

@@ -62,2 +60,3 @@ "del-cli": "^5.1.0",

"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typescript": "^5.2.2"

@@ -80,7 +79,7 @@ },

"access": "public",
"tag": "next"
"tag": "latest"
},
"np": {
"message": "chore(release): %s",
"tag": "next",
"tag": "latest",
"branch": "main",

@@ -101,3 +100,14 @@ "anyBranch": false

},
"prettier": "@adonisjs/prettier-config"
"prettier": "@adonisjs/prettier-config",
"tsup": {
"entry": [
"./index.ts",
"./src/types.ts"
],
"outDir": "./build",
"clean": true,
"format": "esm",
"dts": true,
"target": "esnext"
}
}
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