Summary

Sails.js v1.5 enhances its Waterline ORM with built-in real-time features: automatic WebSocket support for models, pub/sub events on CRUD operations, and flexible blueprint actions. You can now expose live data endpoints with minimal code, letting clients subscribe to model changes and receive updates instantly (sailsjs.com, sailsjs.com).

1. Introduction

Sails.js follows an MVC pattern with Waterline as its ORM. Real-time interactivity, like live chats or dashboards, used to require manual Socket.io wiring or external libraries. In v1.5, Waterline emits lifecycle events you can subscribe to, and Sails’ blueprints auto-generate WebSocket endpoints, dramatically reducing boilerplate.

2. Real-Time ORM Enhancements in v1.5

2.1 Model Pub/Sub API

Every Waterline model now supports .publish(), .publishCreate(), .publishUpdate(), and .publishDestroy() methods inside lifecycle callbacks, and .subscribe() on the client to listen for these events. For example, in api/models/Message.js:

// api/models/Message.js
module.exports = {
  attributes: {
    text: { type: 'string' },
    user: { model: 'User' }
  },

  afterCreate: async function(newlyInsertedRecord, proceed) {
    // Broadcast to all subscribers
    Message.publishCreate(newlyInsertedRecord);
    return proceed();
  }
};

Clients connect via Socket.io and call Message.subscribe() to start receiving new message events automatically (sailsjs.com).

2.2 WebSocket Blueprints

Enable real-time blueprints in config/blueprints.js:

module.exports.blueprints = {
  shortcuts: true,
  rest: true,
  actions: false,
  sockets: true
};

This generates routes like GET /message/subscribe and server-side handlers that wire up Waterline subscriptions without extra code.

2.3 Optimistic Updates & Live Queries

Use skipAllLifecycleCallbacks on queries to reduce latency and push changes directly, and leverage watch() to observe query result changes in real-time:

// Subscribe to 'online' users
User.watch(req);
User.find({ online: true }).exec((err, users) => {
  // initial data
});
// Later, when a User updates online=true, subscribers get notified

(sailsjs.com).

3. Enabling Real-Time Endpoints

  1. Configure Sockets (config/sockets.js):

    module.exports.sockets = {
      onlyAllowOrigins: ['http://localhost:1337'],
      grant3rdPartyCookie: false
    };
    
  2. CORS for WebSockets: Ensure origin settings allow your client domain.

  3. Auto-Room Naming: Models use auto-generated rooms (modelName), e.g., all Message subscribers join the message room.

4. Use Cases & Code Examples

4.1 Live Chat

Server (Message model):

// afterCreate in Message.js (shown above)

Client (browser):

<script src="/js/socket.io.js"></script>
<script>
  const socket = io();
  socket.get('/message/subscribe', (data, jwr) => {
    console.log('Subscribed to Message room');
  });
  socket.on('message', msg => {
    if (msg.verb === 'created') {
      renderMessage(msg.data);
    }
  });
</script>

4.2 Real-Time Dashboard

Track order counts:

// api/models/Order.js
afterCreate(newRec, next) {
  Order.publishCount({ count: await Order.count() });
  next();
}

Clients subscribe to Order.subscribe() and listen for 'order' events to update charts live.

4.3 Collaborative Editing

Use granular rooms per record:

// Client: subscribe to specific document
socket.get(`/document/${docId}/subscribe`, () => {});
socket.on('document', update => applyPatch(update));

Server emits via Document.publishUpdate(record.id, patch), notifying only clients in that doc room.

5. Security & Best Practices

  • Authenticate Socket Connections: Use sails.config.session or custom middleware to validate tokens on onConnect (sailsjs.com).
  • Scope Subscriptions: Avoid global pub/sub; keep clients in specific rooms to reduce noise and enforce permissions.
  • Rate Limiting: Implement server-side checks to prevent event floods (e.g., max messages/sec per user).

6. Full Example Walkthrough

  1. Generate a new Sails app:

    sails new realtime-app
    cd realtime-app
    sails generate api Message
    
  2. Update Message.js with afterCreate hook.

  3. Enable blueprints in config/blueprints.js.

  4. Set CORS origins in config/sockets.js.

  5. Run the app:

    sails lift
    
  6. Open client: Use the browser snippet to subscribe and send GET/POST requests via Socket.io or the REST endpoint to create messages.

7. Conclusion & Further Reading

In Sails v1.5, Waterline’s real-time pub/sub and WebSocket blueprints let you build live APIs with minimal setup. From chat apps to dashboards and collaborative tools, you can expose and secure real-time endpoints directly from your models.

Further Reading