CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sails

API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)

Pending
Overview
Eval results
Files

hooks.mddocs/

Built-in Hooks

Sails.js includes 18+ built-in hooks that provide core framework functionality, from HTTP server management to automatic API generation. Hooks follow a standardized lifecycle and can be extended or customized to modify framework behavior.

Hook System Architecture

Hook Base Class

All hooks inherit from a common base class with standardized lifecycle methods:

// Hook constructor factory
function Hook(definition: Dictionary): Hook

// Hook lifecycle methods
Hook.defaults(): Dictionary
Hook.configure(): void
Hook.loadModules(cb: Function): void  
Hook.initialize(cb: Function): void

Hook Lifecycle

Hooks execute in a specific sequence during application startup:

  1. defaults() - Provide default configuration values
  2. configure() - Normalize and validate configuration
  3. loadModules() - Load modules as dictionary
  4. initialize() - Prepare hook functionality

Hook Properties

hook.identity        // String - Hook name/identifier
hook.config         // Dictionary - Hook-specific configuration  
hook.middleware     // Dictionary - Hook middleware functions
hook.routes         // Dictionary - Hook route definitions
hook.routes.before  // Routes bound before app routes
hook.routes.after   // Routes bound after app routes

Core Built-in Hooks

HTTP Hook

Purpose: HTTP server and middleware management
Location: /lib/hooks/http/index.js

// Default configuration
{
  port: 1337,
  explicitHost: undefined,
  ssl: {},
  paths: { public: '.tmp/public' },
  http: {
    middleware: {
      order: ['cookieParser', 'session', 'bodyParser', 'compress', 'faveicon', 'router', 'www', 'methodOverride']
    },
    cache: 1, // 1ms in development, ~1 year in production
    trustProxy: false
  }
}

Key Features:

  • Express.js application integration
  • Middleware configuration and ordering
  • SSL certificate support
  • Static file serving configuration
  • Request/response object enhancement

Configuration Example:

// config/http.js
module.exports.http = {
  port: 3000,
  middleware: {
    order: ['cookieParser', 'session', 'myCustomMiddleware', 'bodyParser', 'router'],
    myCustomMiddleware: (req, res, next) => {
      console.log('Custom middleware executed');
      next();
    }
  },
  trustProxy: true
};

Blueprints Hook

Purpose: Automatic REST API generation for models
Location: /lib/hooks/blueprints/index.js

// Default configuration
{
  blueprints: {
    actions: false,     // Action shadow routes
    shortcuts: true,    // GET-only CRUD shortcuts  
    rest: true,        // RESTful routes
    prefix: '',        // Route prefix
    restPrefix: '',    // REST-specific prefix
    pluralize: false,  // Pluralize model names in URLs
    autoWatch: true    // Auto-subscribe to model changes
  }
}

Generated Actions:

  • create - Create new record
  • find - Find records with filtering
  • findOne - Find single record by ID
  • update - Update existing record
  • destroy - Delete record
  • populate - Populate associations
  • add - Add to collection association
  • remove - Remove from collection association
  • replace - Replace collection association

Route Generation Examples:

// For User model, generates:

// RESTful routes (rest: true)
'GET /user'           → UserController.find
'POST /user'          → UserController.create  
'GET /user/:id'       → UserController.findOne
'PUT /user/:id'       → UserController.update
'DELETE /user/:id'    → UserController.destroy

// Shortcut routes (shortcuts: true)  
'GET /user/find'      → UserController.find
'GET /user/create'    → UserController.create
'GET /user/update/:id' → UserController.update
'GET /user/destroy/:id' → UserController.destroy

// Action routes (actions: true)
'GET /user/customAction' → UserController.customAction

Security Hook

Purpose: CORS and CSRF protection
Location: /lib/hooks/security/index.js

Sub-hooks:

  • CORS: Cross-Origin Resource Sharing protection
  • CSRF: Cross-Site Request Forgery protection

Configuration Example:

// config/security.js  
module.exports.security = {
  cors: {
    allRoutes: true,
    allowOrigins: ['http://localhost:3000', 'https://myapp.com'],
    allowCredentials: false,
    allowRequestMethods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    allowRequestHeaders: 'content-type'
  },
  
  csrf: {
    grantTokenViaAjax: true,
    origin: 'https://myapp.com'
  }
};

Views Hook

Purpose: View engine configuration and rendering
Location: /lib/hooks/views/index.js

Key Features:

  • Multiple template engine support (EJS, Handlebars, Jade, etc.)
  • View caching in production
  • Layout and partial support
  • Custom view helpers

Configuration Example:

// config/views.js
module.exports.views = {
  engine: 'ejs',
  layout: 'layouts/layout',
  extension: 'ejs',
  
  // View locals available to all templates
  locals: {
    siteName: 'My Sails App',
    title: 'Welcome'
  }
};

Session Hook

Purpose: Session management and storage
Location: /lib/hooks/session/index.js

Key Features:

  • Multiple session store support (memory, Redis, MongoDB)
  • Session configuration and middleware
  • Cookie settings and security

Configuration Example:

// config/session.js
module.exports.session = {
  secret: 'your-session-secret',
  adapter: 'redis',
  host: 'localhost',
  port: 6379,
  db: 0,
  
  cookie: {
    secure: false,      // Set true for HTTPS
    maxAge: 24 * 60 * 60 * 1000  // 24 hours
  }
};

Logger Hook

Purpose: Logging system setup
Location: /lib/hooks/logger/index.js

// Default configuration  
{
  log: {
    level: 'info'  // silly, verbose, info, warn, error, silent
  }
}

// Available log methods
sails.log.error()    // Error level
sails.log.warn()     // Warning level  
sails.log.info()     // Info level (default)
sails.log.verbose()  // Verbose level
sails.log.silly()    // Debug level
sails.log.ship()     // ASCII art ship (special method)

Features:

  • CaptainsLog integration
  • Configurable log levels
  • Color-coded console output
  • ASCII art ship display

Policies Hook

Purpose: Policy enforcement middleware
Location: /lib/hooks/policies/index.js

Key Features:

  • Policy auto-loading from api/policies/
  • Policy mapping to controllers and actions
  • Middleware chain execution

Configuration Example:

// config/policies.js
module.exports.policies = {
  '*': 'isLoggedIn',  // Apply to all controllers
  
  UserController: {
    '*': 'isLoggedIn',        // All actions
    'create': ['isLoggedIn', 'isAdmin'],  // Multiple policies
    'find': true              // Open access
  },
  
  'user/profile': 'isOwnerOrAdmin'  // Standalone action policy
};

Services Hook

Purpose: Service auto-loading and global exposure
Location: /lib/hooks/services/index.js

Key Features:

  • Automatic service discovery in api/services/
  • Global service exposure
  • Service dependency injection

Service Example:

// api/services/EmailService.js
module.exports = {
  sendWelcomeEmail: async function(userEmail, userName) {
    // Email sending logic
    console.log(`Sending welcome email to ${userEmail}`);
    return { sent: true };
  },
  
  sendPasswordReset: async function(userEmail, resetToken) {
    // Password reset email logic
    return { sent: true, token: resetToken };
  }
};

// Usage anywhere in the app
await EmailService.sendWelcomeEmail('user@example.com', 'John');

Helpers Hook

Purpose: Helper function loading and management
Location: /lib/hooks/helpers/index.js

Key Features:

  • Machine-based helper definitions
  • Helper auto-loading from api/helpers/
  • Input validation and output formatting

Helper Example:

// api/helpers/format-date.js
module.exports = {
  friendlyName: 'Format date',
  description: 'Format a date for display',
  
  inputs: {
    date: {
      type: 'ref',
      required: true
    },
    format: {
      type: 'string',
      defaultsTo: 'YYYY-MM-DD'
    }
  },
  
  fn: async function(inputs) {
    const moment = require('moment');
    return moment(inputs.date).format(inputs.format);
  }
};

// Usage
const formatted = await sails.helpers.formatDate(new Date(), 'MMM DD, YYYY');

Internationalization Hook (i18n)

Purpose: Internationalization and localization support
Location: /lib/hooks/i18n/index.js

Key Features:

  • Multiple language support
  • Locale switching and detection
  • Template integration

Configuration Example:

// config/i18n.js
module.exports.i18n = {
  locales: ['en', 'es', 'fr'],
  defaultLocale: 'en',
  directory: './config/locales',
  
  // Request locale detection
  requestLocaleProperty: 'locale',
  queryParameter: 'lang'
};

Infrastructure Hooks

User Config Hook

Purpose: User configuration loading
Location: /lib/hooks/userconfig/index.js

Features:

  • Configuration file processing
  • Environment-specific config loading
  • Config validation and normalization

User Hooks Hook

Purpose: Custom user hook loading
Location: /lib/hooks/userhooks/index.js

Features:

  • Third-party hook integration
  • Custom hook discovery in api/hooks/
  • Hook dependency resolution

Module Loader Hook

Purpose: Dynamic module loading infrastructure
Location: /lib/hooks/moduleloader/index.js

Features:

  • Module discovery patterns
  • Dynamic require resolution
  • Circular dependency handling

Request Hook

Purpose: Request object enhancement
Location: /lib/hooks/request/index.js

Features:

  • Request parameter parsing
  • Input validation helpers
  • Request context enhancement

Responses Hook

Purpose: Response method injection
Location: /lib/hooks/responses/index.js

Features:

  • Custom response methods (res.ok, res.badRequest, etc.)
  • Response auto-loading from api/responses/
  • Status code and header management

Default Response Methods:

res.ok()              // 200 - Success
res.created()         // 201 - Created  
res.badRequest()      // 400 - Bad Request
res.unauthorized()    // 401 - Unauthorized
res.forbidden()       // 403 - Forbidden
res.notFound()        // 404 - Not Found
res.serverError()     // 500 - Internal Server Error

Pub/Sub Hook

Purpose: Publish/Subscribe functionality
Location: /lib/hooks/pubsub/index.js

Features:

  • Real-time communication support
  • Model subscription management
  • WebSocket integration

Usage Example:

// Subscribe to model updates
User.subscribe(req, [userId]);

// Publish model changes  
User.publishUpdate(userId, { status: 'active' });

// Room-based messaging
sails.sockets.join(req, 'chatroom1');
sails.sockets.broadcast('chatroom1', { message: 'Hello!' });

Custom Hook Development

Creating Custom Hooks

Custom hooks are created in the api/hooks/ directory:

// api/hooks/my-hook/index.js
module.exports = function myHook(sails) {
  return {
    // Hook configuration defaults
    defaults: {
      myHook: {
        enabled: true,
        customSetting: 'default-value'
      }
    },
    
    // Configuration normalization
    configure: function() {
      // Validate and normalize config
      if (!sails.config.myHook.enabled) {
        console.log('MyHook is disabled');
      }
    },
    
    // Module loading
    loadModules: function(cb) {
      // Load additional modules if needed
      return cb();
    },
    
    // Hook initialization
    initialize: function(cb) {
      console.log('MyHook initialized');
      
      // Add custom functionality to sails
      sails.myCustomMethod = function() {
        return 'Custom functionality';
      };
      
      return cb();
    },
    
    // Custom hook routes
    routes: {
      before: {
        'GET /hook-test': function(req, res) {
          return res.json({ hook: 'MyHook responding' });
        }
      }
    }
  };
};

Hook Installation

Custom hooks can be installed via npm:

npm install sails-hook-my-custom-hook

Or developed locally in api/hooks/my-hook/.

Hook Configuration

Hook behavior can be controlled through configuration:

// config/my-hook.js
module.exports.myHook = {
  enabled: true,
  customSetting: 'production-value',
  
  // Environment-specific settings
  environments: {
    development: {
      enabled: true,
      debugMode: true
    },
    production: {
      enabled: true,
      debugMode: false
    }
  }
};

Hook Utilities

Environment Filtering

Hooks can be configured to load only in specific environments:

module.exports = function(sails) {
  return {
    // Only load in development
    configure: function() {
      if (sails.config.environment !== 'development') {
        return;
      }
    }
  };
};

Hook Dependencies

Hooks can specify dependencies on other hooks:

module.exports = function(sails) {
  return {
    dependencies: ['orm', 'http'],
    
    initialize: function(cb) {
      // This hook will only initialize after orm and http hooks
      return cb();
    }
  };
};

The Sails.js hook system provides a powerful and flexible architecture for extending framework functionality, with comprehensive built-in hooks covering all core web application needs and extensive customization capabilities.

Install with Tessl CLI

npx tessl i tessl/npm-sails

docs

actions.md

application-lifecycle.md

cli.md

configuration.md

events.md

hooks.md

index.md

routing.md

tile.json