{"id":11977,"library":"sails","title":"Sails.js Web Framework","description":"Sails.js is an MVC-based Node.js web framework designed for building custom, enterprise-grade applications, particularly those requiring real-time features using WebSockets. It aims to provide a Rails-like developer experience but with a data-oriented approach suitable for modern APIs. The current stable version is 1.5.17, with patch releases occurring periodically to address dependencies and minor fixes. Major version updates, like the transition to v1.0, introduced significant breaking changes, prioritizing developer experience over strict backward compatibility. Sails differentiates itself through its convention-over-configuration philosophy, automatic RESTful API generation, integrated ORM (Waterline) with multi-database support, and native Socket.io integration for real-time communication. It also embraced `async/await` syntax from v1.0 onwards, streamlining asynchronous code.","status":"active","version":"1.5.17","language":"javascript","source_language":"en","source_url":"git://github.com/balderdashy/sails","tags":["javascript","mvc","web-framework","express","sailsjs","sails.js","REST","API","orm"],"install":[{"cmd":"npm install sails","lang":"bash","label":"npm"},{"cmd":"yarn add sails","lang":"bash","label":"yarn"},{"cmd":"pnpm add sails","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core HTTP server and middleware layer.","package":"express","optional":false},{"reason":"Core for real-time communication features.","package":"socket.io","optional":false},{"reason":"The ORM for database interactions, with a robust adapter system.","package":"waterline","optional":false},{"reason":"Runtime environment. Requires Node.js >= 0.10.0, but v1.0+ requires Node.js >= 4.x.","package":"node","optional":false}],"imports":[{"note":"For programmatic interaction (e.g., in tests or scripts), instantiate `Sails` using its constructor to avoid singleton issues and to manage multiple app instances. Direct `import` syntax is not natively supported for the core framework in Node.js applications unless a transpiler like Babel is used.","wrong":"import Sails from 'sails';","symbol":"Sails (for programmatic use)","correct":"const Sails = require('sails').constructor;"},{"note":"Within a running Sails application (e.g., in controllers, services, or models), a singleton `sails` instance is automatically available, often globally. `require('sails')` will return this singleton instance. Using `import` directly for `sails` in application code might require Babel or other transpilation for full ESM support.","wrong":"import sails from 'sails';","symbol":"sails (global instance)","correct":"const sails = require('sails');"},{"note":"In a Sails application, models are typically accessed via the global `sails.models` object (e.g., `sails.models.mything`) or, by default, directly as global variables (e.g., `Mything`) if `sails.config.globals.models` is `true`. Direct file imports for models are generally not the idiomatic Sails way.","wrong":"import { User } from '../api/models/User';","symbol":"Model access (e.g., User)","correct":"const User = sails.models.user; // Or simply `User` if globals are enabled"}],"quickstart":{"code":"```bash\n# Install Sails CLI globally\nnpm install sails -g\n\n# Create a new Sails project\nsails new my-sails-app --no-template\ncd my-sails-app\n\n# Generate a simple User model\nsails generate model User name:string email:string\n\n# Generate a UserController\nsails generate controller User --actions 'find,create'\n\n# Lift the Sails application (start the server)\nsails lift\n\n# --- Example of programmatic interaction (after lifting) ---\n# In a separate script, e.g., `test.js`:\n# const Sails = require('sails').constructor;\n# const sailsApp = new Sails();\n#\n# sailsApp.lift({ log: { level: 'warn' } }, async (err) => {\n#   if (err) {\n#     console.error('Error lifting Sails app:', err);\n#     return;\n#   }\n#   console.log('Sails app lifted successfully!');\n#\n#   try {\n#     // Access a model and create a record\n#     const User = sailsApp.models.user; // Access the model instance\n#     const newUser = await User.create({\n#       name: 'Alice Smith',\n#       email: 'alice@example.com'\n#     }).fetch();\n#     console.log('Created user:', newUser);\n#\n#     // Find all users\n#     const users = await User.find();\n#     console.log('All users:', users);\n#   } catch (queryErr) {\n#     console.error('Database query error:', queryErr);\n#   } finally {\n#     sailsApp.lower((lowerErr) => {\n#       if (lowerErr) console.error('Error lowering Sails app:', lowerErr);\n#       else console.log('Sails app lowered.');\n#     });\n#   }\n# });\n```","lang":"typescript","description":"This quickstart demonstrates how to set up a new Sails.js project using its CLI, generate basic model and controller files, lift the application, and then programmatically interact with the lifted app's models from an external script."},"warnings":[{"fix":"Refer to the official Sails.js upgrade guides (e.g., 'Upgrading to Sails v1.0') and consider using the `sails upgrade` tool. Migrate your application incrementally, addressing database configuration, model attribute definitions, and asynchronous API usage.","message":"Upgrading to Sails v1.0 from any v0.x version involved significant breaking changes, including changes to configuration (especially datastores), model definitions (e.g., `autoPK` removed), and the results of `.create()`, `.update()`, and `.destroy()` methods. Many core hooks became direct dependencies.","severity":"breaking","affected_versions":"<1.0"},{"fix":"Pass configuration overrides directly to the `.lift()` or `.load()` methods. For `.sailsrc` specific configurations, use `require('sails/accessible/rc')('sails')` and pass them in. Disable unnecessary hooks and globals (`globals: false`) when running multiple instances or in test environments.","message":"When programmatically lifting Sails applications, such as for testing, environment variables like `.sailsrc` settings are not automatically applied. Additionally, running multiple Sails app instances in the same process with globals enabled can lead to collisions.","severity":"gotcha","affected_versions":">=0.10.0"},{"fix":"Standardize on `async/await` for all asynchronous model methods and other operations. Ensure proper `try/catch` blocks are used. If using `.then()` chains, always include a `.catch()` to prevent unhandled promise rejections.","message":"Sails v1.0+ fully embraces `async/await` for asynchronous operations. While traditional `.exec()` with callbacks is still supported, mixing styles or neglecting error handling with promises (`.then().catch()`) can lead to unhandled rejections and instability.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Always sanitize and escape user-provided or dynamic data before rendering it in views or sending it in HTTP responses to prevent Cross-Site Scripting (XSS) attacks. Utilize templating engine auto-escaping features or specific sanitization libraries.","message":"From v1.3.1, an update to the `machine-as-action` dependency included a reminder about escaping strings with dynamic data when injected into views or responses, indicating a potential XSS vulnerability if not handled correctly.","severity":"gotcha","affected_versions":">=1.3.1"},{"fix":"For new logic, use 'helpers' instead of 'services'. Adopt the 'Actions2' syntax for new controller actions to benefit from automatic parameter validation and clear exit definitions.","message":"The `sails.services` object, while still accessible, has been superseded by 'helpers' since Sails v1.0. The new 'Actions2' syntax for controllers also streamlines definition and validation.","severity":"deprecated","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure that each request handler (action, policy, middleware) sends only one response. Use `return` before `res.send()`, `res.json()`, `res.serverError()`, etc., to prevent further code execution after a response has been dispatched. Implement robust error handling.","cause":"Attempting to send multiple HTTP responses for a single request, often due to improper `res.send()` or `res.json()` usage after another response has already been sent, or due to unhandled errors that implicitly send a default response.","error":"TypeError: Cannot set headers after they are sent to the client"},{"fix":"Check server logs for more specific error messages from individual hooks, models, or configurations. Verify database connection settings in `config/datastores.js` and model definitions for correctness. Review the `config/bootstrap.js` file for any problematic logic. Incrementally comment out hooks or custom logic to isolate the problematic component.","cause":"A common startup error in Sails, indicating an issue during the application bootstrap or hook initialization phase. This can be due to misconfigured database connections, invalid model definitions, syntax errors in config files, or unhandled exceptions in bootstrap logic.","error":"Error: An app failed to lift. (Usually means a hook threw an error)"},{"fix":"Before creating or updating, perform a check to see if a record with the unique value already exists. Handle the `E_UNIQUE` error specifically in `try/catch` blocks or promise `.catch()` handlers, providing appropriate feedback to the user or logic to resolve the conflict.","cause":"Attempting to create or update a record with a value for an attribute that has been defined with a `unique: true` constraint, and that value already exists in the database.","error":"E_UNIQUE: A uniqueness constraint was violated"}],"ecosystem":"npm"}