Sails lift
│
├─ loads all hooks from modules/
│ └─ calls initialize(cb) for each ← src/initialize.js
│
├─ config/bootstrap.js of each module ← runs after all hooks loaded
│
└─ app is ready
There are two entry points for startup code:
| File | When it runs | Use for |
|---|---|---|
src/initialize.js |
During hook load (early) | Binding models, registering routes |
config/bootstrap.js |
After all hooks loaded | Anything that needs other hooks (adminpanel, restocore, MCP) |
src/initialize.jsCalled by index.js. Must invoke cb() when done.
// src/initialize.js
import { HookTools } from '@webresto/core';
import { resolve } from 'path';
import afterHook from './hook/afterHook';
const requiredHooks = ['adminpanel', 'restocore'];
export default async function (sails, cb) {
// 1. Bind models first
await HookTools.default.bindModels(resolve(__dirname, '../models'));
// 2. Schedule code that runs after required hooks are ready
HookTools.default.waitForHooks('my-module', requiredHooks, afterHook);
// 3. Signal that this hook finished initialising
cb();
}
afterHook.jswaitForHooks calls your function once all listed hooks have emitted their
loaded events. This is the right place for anything that needs models from
restocore or the admin panel to be ready.
// src/hook/afterHook.js
import bindAdminpanelconfig from '../lib/bindAdminpanelconfig';
export default async function () {
// Safe to use sails.hooks.adminpanel, Dish, Group, etc. here
bindAdminpanelconfig();
}
config/bootstrap.jsRuns after all hooks in the app are loaded. Follows the same convention as
api/bootstrap/ files — export a default async function that receives sails.
// config/bootstrap.js
'use strict';
module.exports.default = async function (sails) {
sails.log.info('my-module > bootstrap running');
// Example: register an MCP tool (see docs/mcp-modules.md)
if (process.env.MCP_ENABLED === 'true') {
const mcp = require('../../api/mcp/McpServer');
mcp.registerTool({
name: 'my-module-status',
description: 'Returns my-module status.',
mode: 'public',
schema: { type: 'object', properties: {} },
handler: async () => ({ ok: true }),
});
}
};
Use sails.on(event, fn) to react to specific moments in the lifecycle:
module.exports.default = async function (sails) {
// After the ORM is ready
sails.on('hook:orm:loaded', () => {
sails.log.debug('my-module > ORM is ready');
});
// After a specific hook
sails.on('hook:restocore:loaded', async () => {
const count = await Dish.count();
sails.log.info(`my-module > ${count} dishes in the database`);
});
};
Common events:
| Event | Fires when |
|---|---|
hook:orm:loaded |
Waterline ORM and all models are ready |
hook:restocore:loaded |
@webresto/core finished loading |
hook:adminpanel:loaded |
Admin panel hook is ready |
Adminpanel:loaded |
Admin panel fully configured (use for UI registration) |
ready |
All hooks loaded, app accepting requests |