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
- Implemented via
sails.hooks.orm.datastore()
- See https://github.com/node-machine/driver-interface and https://github.com/particlebanana/waterline-query-docs/issues/2
- API:
sails.hooks.orm.datastore('foo').leaseConnection(during).meta(optionalMD).exec(afterDisconnecting)
- Also:
User.find().usingConnection(mySQLConnectionObtainedFromUsingRawDriver).exec();
- This is currently implemented at the driver level, as of early Oct 2016.
- Implemented via
- Advanced Joins (using compiled statements based on Knex)
- This is implemented at the driver layer, and will be exposed via
.datastore()
in Sails v1 - See https://github.com/particlebanana/waterline-query-docs/
- This is implemented at the driver layer, and will be exposed via
- Built-in Support for Native Database Transactions (for databases that support it)
- See postmanlabs/sails-mysql-transactions#26 (comment))
- API is similar to above:
sails.hooks.orm.datastore('foo').transaction(during).meta(optionalMD).exec(afterCommittingOrRollingBack)
- Native Queries
- Model-based usage like
User.native()
andUser.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)
- Model-based usage like
- 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:
.update({...}).set({ pets: [3,5,6] }).exec(...)
.update({...}).set({ pets: [] }).exec(...)
.update({...}).set({ favoritePet: 5 }).exec(...)
.update({...}).set({ favoritePet: null }).exec(...)
- Three new static model methods will be available:
- Enhanced
.stream()
functionality - Case sensitivity in criteria's
where
in Waterline find/findOne/count/update/destroy - 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 callres.json()
with the data, unless the first argument is not specified or isundefined
, in which case it will doreturn res.sendStatus(200)
.)
- (Modified this slightly -- default
- ~~ Default blueprint actions will no longer use
res.ok()
or serve matching views. ~~ - ✓
Built-in XSS Prevention (exposeLocalsToBrowser()
view helper)- ~~See balderdashy#3522~~~
- Federated hooks (custom builds)
- See balderdashy#3504
- Upgrade to Express 5
- Move implementation of
req.param()
from Express core into Sails core - Improve error handling and simplify Sails'
res.view()
- ✓
For performance reasons, on-lift view stat-ing will still be used to build handlers for{view: 'foo'}
route target syntax. - Use standalone Express router in virtual request interpreter, but continue using express core for handling HTTP requests
- Possibly: Expose context-free view rendering API (replace experimental sails.renderView() and internally, use
app.render()
or better yet, standalone module) - See also expressjs/express#2237 and https://expressjs.com/en/guide/migrating-5.html
- Move implementation of
- ✓
Built-In Support For Request Parameter Validation & Response Coercion - ✓
Standalone Actions - 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 https://github.com/mde/ejs)
- Change
- ✓
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 includeapi/helpers/
, a new type of Sails project module.sails.helpers.fetchRecentFBMessages({ ... }).exec(function (err, fbMsgs) { ... });
sails.helpers.computeAverage({ ... }).execSync();
sails.helpers.foo.bar.baz.doSomething({ ... }).exec(...)
- ✓
Runningsails 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 socket.io 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:
- ✓
Improved parsing of configuration overridesThis 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 byrc
is coming from (see dominictarr/rc#33)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- Will be handled by calling res.badRequest() directly
- The toJSON() function of errors will be called (since res.json will be used instead of res.jsonx)
- https://github.com/balderdashy/sails/commit/b8c3813281a041c0b24db381b046fecfa81a14b7#commitcomment-18455430
- Error handling (in general)
- Default implementation of res.serverError() will continue to never send error data in production
- But default impl of
res.ok()
andres.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 callres.serverError()
instead ofres.negotiate()
. - Support for
res.negotiate()
will likely still exist, but will log a warning. - For more details, see https://github.com/balderdashy/sails/commit/b8c3813281a041c0b24db381b046fecfa81a14b7#commitcomment-18455430
- For historical context, see also [#3568] (balderdashy#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
, andapi/responses/notFound.js
) to useres.jsonp()
instead ofres.json()
(or to determine which to use based on the value of a request param).
sails.config.environment
and theNODE_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 tosails.config.environment
. - If
NODE_ENV
is set to "production butsails.config.environment
is not specified, thensails.config.environment
will still be set to "production" automatically. - But if both
NODE_ENV
andsails.config.environment
are specified, then no changes will be made to either. - If
sails.config.environment
is set to "production" and theNODE_ENV
environment variable is not also set to production, Sails will log a warning.
- Sails will no longer set the
- ✓
The deprecatedBORN DEPRECATEDsails.config.dontFlattenConfig
will be removed.- 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.
- The
- ✓
Better built-in support for command-line scripts that require access to the Sails app instance - Normalize usage of
routesDisabled
config keys- Now applies only to sails.config.session: use Sails route address syntax
- ✓ ~~Strip Out Deprecated Sockets Methods
- sails-stdlib
- Library of well-tested, well-documented, and officially supported modules for the most common everyday tasks in apps (e.g. password encryption)
- 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
andE_COULD_NOT_CONNECT_TO_SESSION_STORE
-- since that would eliminate the possibility of false positives due to throwing /cb(err)
-ing.
- Most likely, that's stuff like
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. |
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 dominictarr/rc#23 (comment). 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 balderdashy#2351 (comment) for more information. |
Standalone view renderer | Use @fishrock123's standalone views module (enables views over sockets). See balderdashy#2351 (comment) for more information. |
Standalone static middleware | use static middleware directly in lib/router (enables static files over sockets) See balderdashy#2351 (comment) 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 github.com/balderdashy/sails-hook-sockets |
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/ socket.io). 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 balderdashy#80 for background. |