New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

hook-app

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hook-app

A dynamic framework to supercharge your Node.js applications with hooks.

latest
Source
npmnpm
Version
1.0.0
Version published
Weekly downloads
2
Maintainers
1
Weekly downloads
 
Created
Source

hook-app

npm version License: ISC

A WordPress-style hooks system for Node.js applications. Build modular, traceable, and extensible apps with lifecycle hooks, services, and features.

Installation

npm install hook-app
import hookApp from 'hook-app';

Quick Start

Create a simple app with a feature that runs during initialization:

import hookApp, { type RegisterContext } from 'hook-app';

const myFeature = ({ registerAction }: RegisterContext) => {
  registerAction({
    hook: '$INIT_FEATURE',
    handler: () => {
      console.log('Hello, Hook App!');
    },
  });
};

await hookApp({ features: [myFeature] });

Core Concepts

Hooks

Named extension points where actions can attach. Reference built-in hooks with $HOOK_NAME syntax:

registerAction({
  hook: '$INIT_FEATURE',  // Built-in lifecycle hook
  handler: () => { /* ... */ },
});

Actions

Functions that execute when a hook is triggered. Actions have a name, priority, and handler:

registerAction({
  hook: '$START',
  name: 'my-action',
  priority: 10,  // Higher = runs first
  handler: (args, ctx) => {
    // Your logic here
  },
});

Services & Features

  • Services - Core integrations that set up shared functionality (databases, logging, etc.)
  • Features - Application-specific logic built on top of services

Both use the same RegisterContext interface:

const myService = ({ registerAction, registerHook, createHook }: RegisterContext) => {
  // Register custom hooks, actions, etc.
};

await hookApp({
  services: [myService],
  features: [myFeature],
});

Lifecycle

Boot phases execute in this order:

START → SETTINGS → INIT_SERVICES → INIT_SERVICE → INIT_FEATURES → INIT_FEATURE
      → START_SERVICES → START_SERVICE → START_FEATURES → START_FEATURE → FINISH

Key Patterns

Custom Hook Communication

Features communicate through custom hooks:

import hookApp, { type RegisterContext } from 'hook-app';

// Feature 1: Registers and triggers a custom hook
const notifier = ({ registerHook, registerAction, createHook }: RegisterContext) => {
  registerHook({ NOTIFY: 'notify' });

  registerAction({
    hook: '$INIT_FEATURE',
    handler: () => {
      createHook.sync('notify', { message: 'Hello from notifier!' });
    },
  });
};

// Feature 2: Listens to the custom hook
const listener = ({ registerAction }: RegisterContext) => {
  registerAction({
    hook: '$NOTIFY',
    handler: (args) => {
      console.log('Received:', (args as { message: string }).message);
    },
  });
};

await hookApp({ features: [notifier, listener] });

Settings & Configuration

Access and modify settings using dot-notation paths:

import hookApp, { type RegisterContext } from 'hook-app';

const app = await hookApp({
  settings: {
    api: {
      baseUrl: 'https://api.example.com',
      timeout: 5000,
    },
  },
  features: [
    ({ registerAction }: RegisterContext) => {
      registerAction({
        hook: '$INIT_FEATURE',
        handler: ({ getConfig, setConfig }: RegisterContext) => {
          const url = getConfig<string>('api.baseUrl');
          console.log('API URL:', url);

          // Modify settings
          setConfig('api.timeout', 10000);
        },
      });
    },
  ],
});

// Access final settings
console.log(app.settings);

Hook Execution Modes

Choose how actions execute when a hook is triggered:

ModeMethodDescription
synccreateHook.sync(name, args?)Synchronous execution
seriecreateHook.serie(name, args?)Async, one at a time
parallelcreateHook.parallel(name, args?)Async, all at once
waterfallcreateHook.waterfall(name, initial)Pass result to next handler

Waterfall example:

registerAction('transform', (value: number) => value + 1);
registerAction('transform', (value: number) => value * 2);

const result = createHook.waterfall('transform', 5);
// result.value === 12  (5 + 1 = 6, then 6 * 2 = 12)

Lifecycle Hooks Reference

HookExecutionDescription
$STARTserieApp starting
$SETTINGSserieConfigure settings
$INIT_SERVICESparallelInitialize all services
$INIT_SERVICEserieInitialize each service
$INIT_FEATURESparallelInitialize all features
$INIT_FEATUREserieInitialize each feature
$START_SERVICESparallelStart all services
$START_SERVICEserieStart each service
$START_FEATURESparallelStart all features
$START_FEATUREserieStart each feature
$FINISHserieApp ready

API Quick Reference

Main Entry

import hookApp from 'hook-app';

const app = await hookApp({
  services?: ServiceDef[],
  features?: FeatureDef[],
  settings?: Record<string, unknown> | ((ctx: RegisterContext) => Record<string, unknown>),
  context?: Record<string, unknown>,
  trace?: string | null,
});

// Returns: { settings, context }

Registration (inside services/features)

// Register an action on a hook
registerAction({
  hook: '$INIT_FEATURE',
  handler: (args, ctx) => { /* ... */ },
  name?: string,
  priority?: number,
});

// Shorthand forms
registerAction('hook-name', handler);
registerAction('hook-name', handler, { priority: 10 });

// Register a custom hook
registerHook({ MY_HOOK: 'my-hook' });

Hook Execution

// Synchronous
const results = createHook.sync('hook-name', args?);

// Async sequential
const results = await createHook.serie('hook-name', args?);

// Async parallel
const results = await createHook.parallel('hook-name', args?);

// Waterfall (pass value through handlers)
const { value, results } = createHook.waterfall('hook-name', initialValue);

Config & Context Access

// Get/set configuration
const value = getConfig<T>('path.to.value', defaultValue?);
setConfig('path.to.value', newValue);

// Get/set custom context
const value = getContext<T>('path.to.value', defaultValue?);
setContext('path.to.value', newValue);

Tracing

Enable boot tracing to debug your app's lifecycle:

await hookApp({
  trace: 'compact',  // 'full' | 'normal' | 'compact' | null
  features: [/* ... */],
});

License

ISC

Keywords

hooks

FAQs

Package last updated on 26 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts