Find file
215 lines (188 sloc) 23.6 KB

Sails Roadmap

This file contains the development roadmap for the upcoming release of Sails, as well as the project backlog.



This section is an early list of some of the features, enhancements, and other improvements tentatively planned or already implemented for the v1.0 release of Sails. Note that this is by no means a comprehensive changelog or release plan, and may exclude important additions, bug fixes, and documentation tasks; it is just a reference point with the highlights. Please also realize that the following notes may be slightly out of date from time to time. Until the release is finalized, API changes, deprecation announcements, additions, etc. are all tentative. (But we're getting close.)

  • Built-in Support for Database Projections (i.e. SELECT)
    • This is already implemented in Waterline, but not yet exposed in Sails.
    • We may do a minor release of Sails prior to v1.0 so that folks can take advantage of this today.
    • If you want to use Waterline 0.12 in your Sails app in the mean time, fork sails-hook-orm, upgrade its waterline dependency, then NPM install your forked version as a dependency in your Sails app project, and it will take effect automatically (see this comment for more details).
  • Built-in Support for Dynamic Database Connections
  • Advanced Joins (using compiled statements based on Knex)
  • Built-in Support for Native Database Transactions (for databases that support it)
  • Native Queries
    • Model-based usage like User.native() and User.query() will be deprecated.
    • Instead, native queries (e.g. SQL or Mongo queries) will be performed by accessing the appropriate datastore.
    • API is similar to above: sails.hooks.orm.datastore('foo').sendNativeQuery(nativeQuery).usingConnection(optionalDbConnection).meta(optionalMD).exec(afterFinished)
  • Nested create / nested update
    • Will be disabled by default (and likely completely deferred to userland).
  • More granular .save()
    • Three new static model methods will be available:
      • addToCollection(3)
      • removeFromCollection(12)
      • .resetCollection([1,2,3]) / .resetCollection([])
    • Out of the box, queries like the following will also be supported:
      • .create({ pets: [3,5,6] }).exec(...)
      • .create({ pets: [] }).exec(...)
      • .create({ favoritePet: 5 }).exec(...)
      • .create({ favoritePet: null }).exec(...)
  • Enhanced .stream() functionality
    • Simplify interface and remove reliance on emitters
  • Case sensitivity in criteria's where in Waterline find/findOne/count/update/destroy
    • Will be database-specific instead of normalized to be case-insensitive.
    • This is primarily in order to improve performance on PostgreSQL and to allow for more customizability with character sets/collations across all databases.
  • Automigrations
    • Will be moved out of Waterline and into sails-hook-orm.
    • Usage is unlikely to change.
  • ~~ Default res.ok() response will no longer accept arguments. ~~
    • (Modified this slightly -- default res.ok() can still accept a single data argument, but will no longer attempt to serve a view. It will always call res.json() with the data, unless the first argument is not specified or is undefined, in which case it will do return res.sendStatus(200).)
  • ~~ Default blueprint actions will no longer use res.ok() or serve matching views. ~~
    • (Due to the modification of res.ok() described above, it's okay for blueprints to continue using it.)
  • Built-in XSS Prevention (exposeLocalsToBrowser() view helper)
  • Federated hooks (custom builds)
  • Upgrade to Express 5
  • Built-In Support For Request Parameter Validation & Response Coercion
    • Declaratively specify request parameters, whether they are required, and other data type validations.
    • Assign default values for optional params
    • Declare schemas for responses
    • TODO: go ahead and branch v1 sails-docs and document request parameter validation, response standalone actions
  • Standalone Actions
    • Not all actions (whether it's a microservice, or an endpoint to serve a one-off view) fit nicely into controllers, and pointless categorization wastes developers' time and mental energy.
    • ✓ Run sails generate action to create a new standalone action file
  • Deprecate Built-in EJS/HBS Layouts Support (and instead emphasize partials)
    • Change sails-generate-new to build partials instead of layout (e.g. views/partials/head.ejs)
    • Update default EJS dep (see
  • Services & Helpers
    • Services will continue to work exactly as they today, but the folder will no longer be generated in new Sails apps by default.
    • Instead, new Sails projects will include api/helpers/, a new type of Sails project module.
      • sails.helpers.fetchRecentFBMessages({ ... }).exec(function (err, fbMsgs) { ... });
      • sails.helpers.computeAverage({ ... }).execSync();
      •{ ... }).exec(...)
    • Running sails generate helper creates a new helper file
  • Interalize Seldom-Used Resourceful Pubsub (RPS) Methods
    • RPS methods were originally internal to blueprints, and while a few of them are particularly useful (because they manage room names for you), the public exposure of other methods was more or less incidental.
    • To support more intuitive use, Sails v1.0 trims down the RPS API to just three methods:
      • publish()
      • subscribe()
      • unsubscribe()
  • Improved parsing of configuration overrides
    • This expands the possibilities of env vars for setting configuration. The only reason this hasn't been implemented up until now is that it requires knowing where configuration exported by rc is coming from (see
    • Instead of receiving JSON-encoded values (numbers/booleans/dictionaries/arrays/null) as strings, they'll be parsed.
    • See rttc.parseHuman() for details
  • Validation errors in blueprints, res.jsonx(), & error handling in custom responses
  • Error handling (in general)
    • Default implementation of res.serverError() will continue to never send error data in production
    • But default impl of res.ok() and res.badRequest() will always send the provided argument as response data, even in production.
    • Default implementations of res.forbidden() and res.notFound() will no longer send a response body at all.
    • The default error handler in Sails (i.e. next(err)) will call res.serverError() instead of res.negotiate().
    • Support for res.negotiate() will likely still exist, but will log a warning.
    • For more details, see
    • For historical context, see also #3568
  • JSONP support in blueprints
    • Will be deprecated (along with res.jsonx, as mentioned above)
    • CORS support is so widespread in browsers today (IE8 and up) that JSONP is rarely necessary-- and certainly isn't worth the complexity/weight in core. After upgrading to v1, if you want to implement support for JSONP within the blueprint API, it is still achievable by modifying the relevant default responses (api/responses/badRequest.js, api/responses/serverError.js, and api/responses/notFound.js) to use res.jsonp() instead of res.json() (or to determine which to use based on the value of a request param).
  • sails.config.environment and the NODE_ENV environment variable
    • Sails will no longer set the NODE_ENV environment variable automatically by default.
    • Apps will need to set NODE_ENV themselves in addition to sails.config.environment.
    • If NODE_ENV is set to "production but sails.config.environment is not specified, then sails.config.environment will still be set to "production" automatically.
    • But if both NODE_ENV and sails.config.environment are specified, then no changes will be made to either.
    • If sails.config.environment is set to "production" and the NODE_ENV environment variable is not also set to production, Sails will log a warning.
      • ^^needs tests.
  • The deprecated sails.config.dontFlattenConfig will be removed. BORN DEPRECATED
    • The dontFlattenConfig setting was originally added for backards-compatibility with what was essentially a bug.
    • It will be completely removed in Sails v1.0 for simplicity.
  • Better built-in support for command-line scripts that require access to the Sails app instance
  • Normalize usage of routesDisabled config keys
  • ✓ ~~Strip Out Deprecated Sockets Methods
    • Remove the implementation of deprecated sails.sockets.* methods from Sails core.
    • (These were deprecated, but left in place with warning messages, in Sails v0.12)
  • sails-stdlib
    • Library of well-tested, well-documented, and officially supported modules for the most common everyday tasks in apps (e.g. password encryption)

1.1.0 and beyond

  • Expand express-session/Connect session store interface
    • Expose a method in session stores which can be used to do an initial, asynchronous ping in order to check configuration.
    • Worst case, we should also be able to use .get() with a nonsense session id to do this-- the errors just won't be as nice, or as easy to negotiate.
    • The best middle-of-the-road solution is probably to get a couple of standardized error codes in the spec for .get()
      • Most likely, that's stuff like ECONNREFUSED
      • But would be a lot better if we could swing more specific error codes-- e.g. E_BAD_SESSION_STORE_CONFIG and E_COULD_NOT_CONNECT_TO_SESSION_STORE-- since that would eliminate the possibility of false positives due to throwing / cb(err)-ing.



The backlog consists of approved proposals for useful features which are not currently in the immediate-term roadmap above, but would be excellent places to contribute code to the Sails framework. We would exuberantly accept a pull request implementing any of the items below, so long as it was accompanied with reasonable tests that prove it, and it doesn't break other core functionality. Please see the Sails contribution guide to get started.

  • If you would like to see a new feature or an enhancement to an existing feature in Sails, please review the Sails contribution guide. When you are ready, submit a pull request adding a new row to the bottom of this table.
  • In your pull request, please include a detailed proposal with a short summary of your use case, the reason why you cannot implement the feature as a hook, adapter, or generator, and a well-reasoned explanation of how you think that feature could be implemented. Your proposal should include changes or additions to usage, expected return values, and any errors or exit conditions.
  • Once your pull request has been created, add an additional commit which links to it from your new row in the table below.
Feature Proposal Summary
Generate test/ folder in new Sails apps #2499 Generate a generic setup for mocha tests in all new Sails apps. Originally suggested by @jedd-ahyoung.
View helper for bootstrapping script tags #3522 Include a view helper for bootstrapping untrusted data from view locals onto the page via script tags in order to expose it to client-side JavaScript. The tricky part is ensuring protection from attempted XSS attacks.
Improve CORS implementation #3651 Minor changes to the current CORS hooks to better follow the specs/remove inconsistencies.


Pending Proposals

The backlog items below are from before the recent change to the Sails project's contribution guidelines, and are suggestions for features or enhancements, but are not yet accompanied by a complete proposal. Before any of the following backlog items can be implemented or a pull request can be merged, a detailed proposal needs to be submitted, discussed and signed off on by the project maintainers. For information on writing a proposal, see the Sails contribution guide. Please do not submit a pull request adding to this section.

  • If you are the original proposer of one of these items, someone from the core team has contacted you in the linked issue or PR, if one was provided. Thank you for your help!
  • If you are interested in seeing one of the features or enhancements below in Sails core, please create a new pull request moving the relevant item(s) to the backlog table with additional details about your use case (see the updated contribution guide for more information).
Feature Summary
Atomic update See this issue for details. Originally suggested by @leedm777.
Log key configuration info on lift For example, if config/local.js is present, log a message explaining that it will be used. See also Originally suggested by @mikermcneil.
Lock + unlock app in dev env Capability for a hook to "lock" and/or "unlock" the app (in a development env only). When "locked" all requests are intercepted by an endpoint which responds with either a page or JSON payload communicating a custom message. e.g. so the grunt hook can let us know as it syncs. e.g. sails.emit('lock'). Originally suggested by @mikermcneil.
Hook dependency/load order mgmt Rebase the hook dependency+optional depenency system. A detailed spec was originally proposed by @ragulka, but since then, custom hooks have complicated the equation.
Standalone router replace express dependency in lib/router with standalone router- either routification or @dougwilson's new project. See for more information.
Standalone view renderer Use @fishrock123's standalone views module (enables views over sockets). See for more information.
Standalone static middleware use static middleware directly in lib/router (enables static files over sockets) See for more information.
Break out core hooks into separate modules Makes Sails more composable, and removes most of its dependencies in core. Also allows for easier sharing of responsibility w/ the community, controls issue flow. Started with
Allow disabling session mw for static assets Allow session handling to be turned off for static assets. In certain situations, a request for a static asset concurrent to a request to a controller action can have undesirable consequences; specifically, a race condition can occur wherein the static asset response ends up overwriting changes that were made to the session in the controller action. Luckily, this is a very rare issue, and only occurs when there are race conditions from two different simultaneous requests sent from the same browser with the same cookies. If you encounter this issue today, first think about whether you actually need/want to do things this way. If you absolutely need this functionality, a workaround is to change the order of middleware or override the session middleware implementation in config/http.js. However, for the long-term, we need a better solution. It would be good to improve the default behavior of our dependency, express-session so that it uses a smarter heuristics. For more information, see the implementation of session persistence in express-session. However, the single cleanest solution to the general case of this issue would be the ability to turn off session handling features for all static assets (or on a per-route basis). This is easier said than done. If you'd like to have this feature, and have the cycles/chops to implement it, please tweet @sgress454 or @mikermcneil and we can dive in and work out a plan. Summary of what we could merge: We could remove the default session middleware from our http middleware configuration, and instead add it as a manual step in the virtual router that runs before the route action is triggered. Good news it that we're actually already doing this in order to support sessions in the virtual router (e.g. for use w/ So the actual implementation isn't a lot of work-- just needs some new automated tests written, as well as a lot of manual testing (including w/ redis sessions). We also need to update our HTTP docs to explain that requests for static assets no longer create a session by default, and that default HTTP session support is no longer configured via Express's middleware chain (handled by the virtual router instead.) Finally we'd also need to document how to enable sessions for assets (i.e. attaching the express-session middleware in config/http.js, but doing so directly before the static middleware runs so that other routes don't try to retrieve/save the session twice). @sgress454
Manual migrations in Sails CLI For production environments it would be nice to have a save/secure command that creates the db automatically for you; e.g. a sails migrate or sails create-db command. See sails-migrations and sails-db-migrate for inspiration. We should begin by contributing and using one or both of these modules in production in order to refine them further into a full fledged proposal (the Sails core team is using sails-migrations currently). Originally suggested by @globegitter.
Wildcard action policies Instead of only having one global action policy '*' it would be nice if we could define policies for a specific action in all controllers: '*/destroy': ['isOwner'] or something similar. Originally suggested by @ProLoser.
SPDY/HTTP2 protocol support See for background.