# Technical Documentation: balderdashy/sails

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/balderdashy/sails)

### Overview (`README.md`)

# [](http://sailsjs.com)

### [Website](https://sailsjs.com/)  &nbsp; [Get Started](https://sailsjs.com/get-started) &nbsp;  [Docs](http://sailsjs.com/documentation)  &nbsp; [News](http://twitter.com/sailsjs) &nbsp; [Submit Issue](http://sailsjs.com/bugs)

[](http://badge.fury.io/js/sails) &nbsp; [](https://gitter.im/balderdashy/sails)  &nbsp; [](https://twitter.com/sailsjs)

Sails.js is a [web framework](http://sailsjs.com/whats-that) that makes it easy to build custom, enterprise-grade Node.js apps. It is designed to resemble the MVC architecture from frameworks like Ruby on Rails, but with support for the more modern, data-oriented style of web app & API development. It's especially good for building realtime features like chat.

Since version 1.0, Sails supports `await` out of the box.  This replaces nested callbacks (and the commensurate error handling) with simple, familiar usage:

```javascript
var orgs = await Organization.find();
```


## Installation &nbsp;
**With [node](http://nodejs.org) [installed](http://nodejs.org/en/download):**
```sh
# Get the latest stable release of Sails
$ npm install sails -g
```

> ##### Upgrading from an earlier version of Sails?
> Upgrade guides for all major releases since 2013 are available on the Sails website under [**Upgrading**](http://sailsjs.com/upgrading).


## Your First Sails Project

**Create a new app:**
```sh
# Create the app
sails new my-app
```

**Lift sails:**
```sh
# cd into the new folder
cd my-app

# fire up the server
sails lift
```

[](https://sailsjs.com/get-started)

For the most up-to-date introduction to Sails, [get started here](https://sailsjs.com/get-started).

## Compatibility

Sails is built on [Node.js](http://nodejs.org/), [Express](http://expressjs.com/), and [Socket.io](http://socket.io/).

Sails [actions](http://sailsjs.com/documentation/concepts/actions-and-controllers) are compatible with Connect middleware, so in most cases, you can paste code into Sails from an existing Express project and everything will work-- plus you'll be able to use WebSockets to talk to your API, and vice versa.

The ORM, [Waterline](https://github.com/balderdashy/waterline), has a well-defined adapter system for supporting all kinds of datastores.  Officially supported databases include [MySQL](https://npmjs.com/package/sails-mysql), [PostgreSQL](https://npmjs.com/package/sails-postgresql), [MongoDB](https://npmjs.com/package/sails-mongo), [Redis](https://npmjs.com/package/sails-redis), and [local disk / memory](https://npmjs.com/package/sails-disk).
Community adapters exist for [CouchDB](https://github.com/search?q=sails+couch&nwo=codeswarm%2Fsails-couchdb-orm&search_target=global&ref=cmdform), [neDB](https://github.com/adityamukho/sails-nedb), [SQLite](https://github.com/AndrewJo/sails-sqlite3/tree/0.10), [Oracle](https://github.com/search?utf8=%E2%9C%93&q=%22sails+oracle%22+OR+%22waterline+oracle%22&type=Repositories&ref=searchresults), [MSSQL](https://github.com/misterGF/sails-mssqlserver), [DB2](https://github.com/search?q=sails+db2&type=Repositories&ref=searchresults), [ElasticSearch](https://github.com/search?q=%28elasticsearch+AND+sails%29+OR+%28elasticsearch+AND+waterline%29+&type=Repositories&ref=searchresults), [Riak](https://github.com/search?q=sails+riak&type=Repositories&ref=searchresults),
[neo4j](https://www.npmjs.org/package/sails-neo4j), [OrientDB](https://github.com/appscot/sails-orientdb),
[Amazon RDS](https://github.com/TakenPilot/sails-rds), [DynamoDB](https://github.com/TakenPilot/sails-dynamodb), [Azure Tables](https://github.com/azuqua/sails-azuretables), [RethinkDB](https://github.com/gutenye/sails-rethinkdb) and [Solr](https://github.com/sajov/sails-solr); for various 3rd-party REST APIs like Quickbooks, Yelp, and Twitter, including a configurable generic [REST API adapter](https://github.com/zohararad/sails-rest); plus some [eclectic projects](https://www.youtube.com/watch?v=OmcQZD_LIAE).


<a target="_blank" href="http://www.mysql.com">
  <img width="75" src="http://www.mysql.com/common/logos/powered-by-mysql-125x64.png" alt="Powered by MySQL" title="sails-mysql: MySQL adapter for Sails"/>
</a>&nbsp; &nbsp; &nbsp; &nbsp;
<a target="_blank" href="http://www.postgresql.org/"><img width="50" title="PostgreSQL" src="http://i.imgur.com/OSlDDKv.png"/></a>&nbsp; &nbsp; &nbsp; &nbsp;
<a target="_blank" href="http://www.mongodb.org/"><img width="100" title="MongoDB" src="http://i.imgur.com/bC2j13z.png"/></a>&nbsp; &nbsp; &nbsp; &nbsp;
<a target="_blank" href="http://redis.io/"><img width="75" title="Redis" src="http://i.imgur.com/dozv0ub.jpg"/></a>&nbsp; &nbsp; &nbsp; &nbsp;


> For the latest core adapters and notable community adapters, see [Available Adapters](http://sailsjs.com/documentation/concepts/extending-sails/adapters/available-adapters).

## Tutorial Course
- [Sailscasts](https://sailscasts.com/), taught by [Kelvin Omereshone](https://twitter.com/Dominus_Kelvin) _(English)_
- [Full-Stack JavaScript with Sails.js and Vue.js](https://platzi.com/cursos/javascript-pro/), taught by [Mike McNeil](https://twitter.com/mikermcneil) _(in English, with optional Spanish subtitles)_


## Books
- [Sails.js in Action](https://www.manning.com/books/sails-js-in-action) by Mike McNeil and Irl Nathan (Manning Publications).
- [Sails.js Essentials](https://www.packtpub.com/web-development/sailsjs-essentials) by Shaikh Shahid (Packt)
- [Pro Express.js: Part 3](http://link.springer.com/chapter/10.1007%2F978-1-4842-0037-7_18) by Azat Mardan (Apress).

## Support
Need help or have a question?
- [Frequently Asked Questions (FAQ)](http://sailsjs.com/faq)
- [Tutorials](http://sailsjs.com/faq#?what-are-some-good-community-tutorials)
- [Community support](http://sailsjs.com/support)
- [Professional/Enterprise options](http://sailsjs.com/faq#?are-there-professional-support-options)


## Issue submission
Please read the [submission guidelines](http://sailsjs.com/documentation/contributing/issue-contributions) and [code of conduct](http://sailsjs.com/documentation/contributing/code-of-conduct) before opening a new issue.  Click [here](https://github.com/balderdashy/sails/search?q=&type=Issues) to search/post issues in this repository.

## Contribute
There are many different ways you can contribute to Sails:
- answering questions on [StackOverflow](http://stackoverflow.com/questions/tagged/sails.js), [Gitter](https://gitter.im/balderdashy/sails), [Facebook](https://www.facebook.com/sailsjs), or [Twitter](https://twitter.com/search?f=tweets&vertical=default&q=%40sailsjs%20OR%20%23sailsjs%20OR%20sails.js%20OR%20sailsjs&src=typd)
- improving the [documentation](https://github.com/balderdashy/sails-docs#contributing-to-the-docs)
- translating the [documentation](https://github.com/balderdashy/sails-docs/issues/580) to your native language
- writing [tests](https://github.com/balderdashy/sails/blob/master/test/README.md)
- writing a [tutorial](https://github.com/sails101/contribute-to-sails101), giving a [talk](https://speakerdeck.com/mikermcneil), or supporting [your local Sails meetup](https://www.meetup.com/find/?allMeetups=false&keywords=node.js&radius=Infinity&sort=default)
- troubleshooting [reported issues](http://sailsjs.com/bugs)
- and [submitting patches](http://sailsjs.com/documentation/contributing/code-submission-guidelines).

_Please carefully read our [contribution guide](http://sailsjs.com/documentation/contributing) and check the [build status](http://sailsjs.com/architecture) for the relevant branch before submitting a pull request with code changes._


## Links
- [Website](http://sailsjs.com/)
- [Documentation](http://sailsjs.com/documentation)
- [Ask a question](http://sailsjs.com/support)
- [Tutorial](https://platzi.com/cursos/javascript-pro/)
- [Roadmap](https://trello.com/b/s9zEnyG7/sails-v1)
- [Twitter (@sailsjs)](https://twitter.com/sailsjs)
- [Facebook](https://www.facebook.com/sailsjs)

## Team
Sails is actively maintained with the help of many amazing [contributors](https://github.com/balderdashy/sails/graphs/contributors).  Our core team consists of:

[](https://twitter.com/mikermcneil) |  [](https://twitter.com/dominus_kelvin) |  [](https://github.com/eashaw)
|:---:|:---:|:---:|
[Mike McNeil](http://github.com/mikermcneil) | [Kelvin Omereshone](https://github.com/DominusKelvin) | [Eric Shaw](https://github.com/eashaw)


[Our company](https://sailsjs.com/about) designs/builds Node.js websites and apps for startups and enterprise customers. After building a few applications and taking them into production, we realized that the Node.js development landscape was very much still the Wild West. Over time, after trying lots of different methodologies, we decided to crystallize all of our best practices into this framework.  Six years later, Sails is now one of the most widely-used web application frameworks in the world. I hope it saves you some time! :)

## License

[MIT License](https://opensource.org/licenses/MIT)  Copyright © 2012-present, Mike McNeil

> Sails is built around so many great open-source technologies that it would never have crossed our minds to keep it proprietary.  We owe huge gratitude and props to Ryan Dahl ([@ry](https://github.com/ry)), TJ Holowaychuk ([@tj](https://github.com/tj)), Doug Wilson ([@dougwilson](https://github.com/dougwilson)) and Guillermo Rauch ([@rauchg](https://github.com/rauchg)) for the work they've done, as well as the stewards of all the other open-source modules we use.  Sails could never have been developed without your tremendous contributions to the JavaScript community.

---

### Overview (`docs/README.md`)

# Sails.js Documentation

The official documentation for the current stable release of Sails is on the master branch of this repository.  Content for most sections on the [official Sails website](https://sailsjs.com) is compiled from here.


## In other languages

The documentation for Sails has been translated to a number of different languages.  The list below is a reference of the translation projects we are aware of.

| Language                     | [IETF Language Tag](https://en.wikipedia.org/wiki/IETF_language_tag)  | Version |  Maintainer(s)        | Repo                               |
| ---------------------------- | ------- | ------- | ------------------ | ---------------------------------- |
| Brazilian Portuguese         | `pt-BR` | **v1.0.x**  | [@Avlye](https://github.com/Avlye) | [sails-docs-pt-BR](https://github.com/Avlye/sails-docs-pt-BR)
| Chinese                      | `zh-cn`    | v0.12.x | [@linxiaowu66](https://github.com/linxiaowu66)   | [sails-docs-zh-cn](https://github.com/linxiaowu66/sails-docs-zh-cn)
| French                       | `fr`    | v0.12.x | [@marrouchi](https://github.com/marrouchi)   | [sails-docs-fr](https://github.com/marrouchi/sails-docs-fr)
| Spanish                      | `es`    | v0.12.x | [@eduartua](https://github.com/eduartua/) & [@alejandronanez](https://github.com/alejandronanez)   | [sails-docs-es](https://github.com/eduartua/sails-docs-es)
| Japanese                     | `ja`    | v0.11.x | [@kory-yhg](https://github.com/kory-yhg)      | [sails-docs-ja](https://github.com/balderdashy/sails-docs/tree/ja)
| Brazilian Portuguese         |         | v0.10.x | [@marceloboeira](https://github.com/marceloboeira)   | [sails-docs-pt-BR](https://github.com/balderdashy/sails-docs/tree/pt-BR)
| Korean                       | `ko`    | v0.10.x | [@sapsaldog](https://github.com/sapsaldog)   | [sails-docs-ko](https://github.com/balderdashy/sails-docs/tree/ko)
| Taiwanese Mandarin           | `zh-TW` | v0.10.x | [@CalvertYang](https://github.com/CalvertYang)   | [sails-docs-zh-TW](https://github.com/balderdashy/sails-docs/tree/zh-TW)

> Since we are now using branches to keep track of different versions of the Sails documentation, we are moving away from the original approach of using branches for different languages.  Before embarking on a new translation project, we ask that you review the [updated information below](#how-can-i-help-translate-the-documentation)-- the process has changed a little bit.

## Contributing to the Sails docs

We welcome your help!  Please send a pull request with corrections/additions and they'll be double-checked and merged as soon as possible.


#### How are these docs compiled and pushed to the website?

We use a module called `doc-templater` to convert the .md files to the html for the website. You can learn more about how it works in [the doc-templater repo](https://github.com/uncletammy/doc-templater).

Each .md file has its own page on the website (i.e. all reference, concepts, and anatomy files), and should include a special `<docmeta name="displayName">` tag with a `value` property specifying the title for the page.  This will impact how the doc page appears in search engine results, and it will also be used as its display name in the navigation menu on sailsjs.com.  For example:

```markdown
<docmeta name="displayName" value="Building Custom Homemade Puddings">
```

#### When will my change appear on the Sails website?

Once your change to the documentation is merged, you can see how it will appear on sailsjs.com by visiting [next.sailsjs.com](https://next.sailsjs.com). The preview site updates itself automatically as changes are merged.


#### How can I help translate the documentation?

A great way to help the Sails project, especially if you speak a language other than English natively, is to volunteer to translate the Sails documentation.  If you are interested in collaborating with any of the translation projects listed in the table above, contact the maintainer of the translation project using the instructions in the README of that fork.

If your language is not represented in the table above, and you are interested in beginning a translation project, follow these steps:

+ Bring the documentation folder (`balderdashy/sails/docs`) into a new repo named `sails-docs-{{IETF}}` where {{IETF}} is the [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) for your language.
+ Edit the README to summarize your progress so far, provide any other information you think would be helpful for others reading your translation, and let interested contributors know how to contact you.
+ Send a pull request editing the table above to add a link to your fork.
+ When you are satisfied with the first complete version of your translation, open an issue and someone from our docs team will be happy to help you get preview it in the context of the Sails website, get it live on a domain (yours, or a subdomain of sailsjs.com, whichever makes the most sense), and share it with the rest of the Sails community.


#### How else can I help?

For more information on contributing to Sails in general, see the [Contribution Guide](sailsjs.com/contributing).


## License

[MIT](https://sailsjs.com/license)

The [Sails framework](https://sailsjs.com) is free and open-source under the [MIT License](https://sailsjs.com/license).

---

### Overview (`errors/README.md`)

# errors/


> FUTURE:
> 1. Fold in messages inline instead of using the stringfile (`sails-stringfile` still isn't worth it, at least not until post-v1)
> 2. ~~Ideally we don't call `process.exit()` at all- instead, consistently call sails.lower().  See comment at bottom of `fatal.js`.~~ That's ok sometimes actually (We have process handlers anyway.)  The issue is that we really need to inline these, because it all depends on the context.
> 3. Inline these errors where they're being used.  Then this directory can be deleted.

---

### Overview (`lib/README.md`)

# Understanding Core

Welcome to the Sails.js Core.

The goal of this file is to provide a light overview of the structure and philosophy of Sails.js for core contributors, as well as establish code and documentation conventions.

Many of the subdirectories herein contain a `README.md` file with more information about that particular component.


## Overview

The Sails.js core runs when an app is fired up with `sails.load` or `sails.lift`.


## Stability Index

See the [Sails Project Stability Index](https://github.com/balderdashy/sails/blob/master/docs/contributing/stability-index.md) for more information.  We use a slight variation of the [stability index] used by [Node.js core](http://nodejs.org/api/documentation.html#documentation_stability_index); partially out of allegiance, but mostly for consistency.


## FAQ

> If you have an unanswered question that isn't covered here, and that you feel would add value for the community, please feel free to send a PR adding it to this section.

---

### Overview (`test/README.md`)

# Sails tests


## Run the tests

From the root directory of Sails core, run:

```bash
npm test
```

> Or if you're using Windows:
>
> ```cmd
> npm run custom-tests
> ```

## Goals

1. Identify latent inconsistencies or issues that we don't know about yet.
2. Provide low-level coverage of functionality that is difficult or time-consuming to QA / notice.
3. Protect the core from any future breaking changes.
4. Prevent regression.
5. Make merging pull requests easier by removing me (@mikermcneil) as the bottleneck for merging pull requests. (we can just run the tests to see if a change broke anything)
6. Make it easier for folks to contribute more tests, and help unify the style and structure of our existing tests.


## Writing tests
> For more information about writing tests (structural conventions, what to test, what _not_ to test) see the [Contribution guide](https://github.com/balderdashy/sails-docs/blob/master/contributing/code-submission-guidelines/writing-tests.md).

---

### Overview (`docs/anatomy/README.md`)

# docs/anatomy

This section contains the "Anatomy" documentation which is eventually available at https://sailsjs.com/documentation/anatomy.

### Notes
> - This README file **is not compiled to HTML** for the website.  It is just here to explain what you're looking at.
> - Depending on what branch of `sails` you are currently viewing, the domain may vary. See the top-level documentation README file for information about working with the markdown files in this repo, and to understand the branching/versioning strategy.

<docmeta name="notShownOnWebsite" value="true">

---

### Overview (`docs/concepts/README.md`)

# docs/concepts

This section contains the markdown files which are compiled to HTML and eventually made available as conceptual documentation for the Sails framework at https://sailsjs.com/documentation/concepts.

### Notes
> - This README file **is not compiled to HTML** for the website.  It is just here to explain what you're looking at.
> - Depending on what branch of `sails` you are currently viewing, the domain may vary. See the top-level documentation README file for information about working with the markdown files in this repo, and to understand the branching/versioning strategy.

<docmeta name="notShownOnWebsite" value="true">

---

### Overview (`docs/faq/README.md`)

# docs/faq

This section contains the contents that will live on sailsjs.com/faq.


### Notes
> - This README file **is not compiled to HTML** for the website.  It is just here to explain what you're looking at.

---

### Overview (`docs/reference/README.md`)

# docs/reference

This section contains the official reference documentation for Sails.  It is made available at https://sailsjs.com/documentation/reference.


### Notes
> - This README file **is not compiled to HTML** for the website.  It is just here to explain what you're looking at.
> - Depending on what branch of `sails` you are currently viewing, the domain may vary. See the top-level documentation README file for information about working with the markdown files in this repo, and to understand the branching/versioning strategy.

<docmeta name="notShownOnWebsite" value="true">

---

### Overview (`docs/security/README.md`)

# docs/security

This section contains the official policy for disclosing security vulnerabilities in Sails or our dependencies.  It is made available at https://sailsjs.com/security-policy.


### Notes
> - This README file **is not compiled to HTML** for the website.  It is just here to explain what you're looking at.
> - Depending on what branch of `sails` you are currently viewing, the domain may vary. See the top-level documentation README file for information about working with the markdown files in this repo, and to understand the branching/versioning strategy.

<docmeta name="notShownOnWebsite" value="true">

---

### Overview (`lib/app/README.md`)

# App Lifecycle


## API Status

> ##### Stability: [3](http://nodejs.org/api/documentation.html#documentation_stability_index) - Stable


## Purpose

The `app` directory contains logic concerned with the lifecycle of the Sails core itself.  This includes:

+ Loading and initializing hooks
+ Loading the router
+ Populating middleware library
+ Teardown and cleanup of the currently-running instance of sails


## Loading Steps

The Sails core has been iterated upon several times to make it easier to maintain and extend.
As a result, it has a very particular loading order, which its hooks depend on heavily.
This process is summarized below.

#### Prepare Configuration Object

Populate `sails.config` with core (hook-agnostic) implicit defaults. Then apply the initial known set of configuration overrides, including command-line options, environment variables, and programmatic configuration (i.e. options passed to `sails.load` or `sails.lift`.)
The most important core implicit default configuration is the set of built-in hooks.

#### Load Hooks

Load hooks in the proper order.

#### Populate Middleware Registry

Grab `this.middleware` from each hook and make it available on the `sails` object as `sails.middleware.[HOOK_ID]`.

#### Assemble Router

Prepare the core Router, then emit multiple events on the `sails` object informing hooks that they can safely bind routes.

#### Expose global variables

After all hooks have initialized, Sails exposes global variables
(by default: `sails` object, models, services, `_`, and `async`)

#### Initialize App Runtime

> This step does not run when `sails.load()` is used programmatically.
> To also run the initialization step, use `sails.lift()` instead.

+ Start attached servers (by default: Express and Socket.io)
+ Run the bootstrap function (`sails.config.bootstrap`)



## FAQ


+ What is the difference between `sails.lift()` and `sails.load()`?
  + `lift()` === `load()` + `initialize()`.  It does everything `load()` does, plus it starts any attached servers (e.g. HTTP) and logs a picture of a boat.

> If you have a question that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/hooks/README.md`)

#Hooks

## Status

> ##### Stability: [2](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Stable


## Purpose

Most of the non-essential Sails core has been pulled into hooks already.
These hooks may eventually be pulled out into separate modules, or they may continue to live in the main Sails repo (like Connect middleware).

Hooks were introduced to Sails as part of major refactor designed to make the framework more modular and testable. Their primary purpose was originally to pull all but the most minimal functionality of Sails into independent modules.
Today, most of the non-essential Sails core are hooks. These hooks may eventually be pulled out into separate modules, or they may continue to live in the main Sails repo (like Connect middleware).

This architecture has allowed for built-in hooks to be overridden or disabled, and even for new hooks to be mixed-in to projects.


This gave way to hooks becoming a proper plugin system.  Nowadays, the goal of hooks is to provide an API that is flexible and powerful enough for plugin developers or folks who need to hack Sails core, but also predictable, documented, and easy to install for end users.

See http://sailsjs.com/documentation/concepts/extending-sails/hooks for more information.


> **For historical purposes, here is the original proposal from the v0.9 days:**
> https://gist.github.com/mikermcneil/5746660



## FAQ

> If you have a question that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/router/README.md`)

# Router

## What does it do?

The core Router in Sails is the main (_but not ONLY_) player responsible for routing requests.
It is not involved with HTTP, WebSockets, or other internet protocols directly-- instead, it emits
events on the `sails` object (a Node EventEmitter) when a route should be bound, allowing flexibility
in hooks' implementations.

The core Router includes a latent Express instance which is used only for internal routing of requests,
and is not actually used by any application code in userland-- that's the job of hooks.  It _may_, however,
be used by app-level unit tests, in order to run test suites without having to lift a server and occupy a network port.


## Which hooks attach servers / use the Router?

At the time of this writing, the `http` hook listens for `bind` events emitted from the core Router
and binds them directly to an external instance of Express.

On the other hand, the `sockets` hook defers to the core router, emitting a `request` event whenever
it receives and interprets a new, appropriately-formatted, socket message.  The core Router intercepts this
and routes the request using its known middleware bindings. (core middleware, blueprint aka "shadow" routes,
and statically configured routes from the `routes.js` config file in userland)


## FAQ

+ When an HTTP request hits the server, does it hit the Sails router before it hits the Express router?
  + No- it only hits the Express router.

+ OK.. what requests DO hit the Sails router?
  + Requests to other attached servers that don't have their own routers, e.g. the Socket.io interpreter, will hit the Sails router's wildcard handler, which will then talk to the attached server and simulate the appropriate route.

+ What happens after an HTTP request hits the Express router?
  + Sails does not touch the Express router once it's been set up.

+ When and *how* are the routes in your `routes.js` file processed?
  + `routes.js` is read by the `userconfig` hook, which loads it into `sails.config.routes`.
  + `sails.config.routes` is used by the Sails router at lifttime (to bind routes to the external Express router) AND at runtime (to detect matches in wildcard routes coming from other attached servers like the Socket.io interpreter)

---

### Overview (`test/benchmarks/README.md`)

# Benchmarks

### Run the benchmarks

From the root directory of sails:

```sh
$ BENCHMARK=true mocha test/benchmarks
```

To get a more detailed report with millisecond timings for each benchmark, run:

```sh
$ BENCHMARK=true mocha test/benchmarks -v
```


### Goals

These tests are related to benchmarking the performance of different parts of Sails.  For now, our benchmark tests should be "integration" or "acceptance" tests.  By that, I mean they should measure a specific "user action" (e.g. running `sails new`, running `sails lift`, sending an HTTP request to a dummy endpoint, connecting a Socket.io client, etc.).



##### Why test features first, and not each individual method?

Feature-wide benchmarks are the "lowest-hanging fruit", if you will.  We'll spend much less development time, and still get valuable benchmarks that will give us ongoing data on Sails performance.  This way, we'll know where to start writing lower-level benchmarks to identify choke-points.


##### Writing good benchmarks
+ Pick what you want to test.
+ Whatever you choose does not have to be atomic (see examples above)-- in an ideal world, we would have benchmarks for every single function in our apps, but that is not how things work today.
+ Write a benchmark test that isolates that functionality. (the hard part)
+ Then see how many milliseconds it takes. (easy)

> **Advice from Felix Geisendörfer ([@felixge](https://github.com/felixge))**
>
>  + First of all, keep in mind our problems are definitely not the same as Felix's, and we must remember to follow [his own advice](https://github.com/felixge/faster-than-c#taking-performance-advice-from-strangers): `[What]...does not work is taking performance advise (euro-sic) from strangers...`  That said, he's got some great ideas.
>  + [Benchmark-Driven Optimization](https://github.com/felixge/faster-than-c#benchmark-driven-development)
>  + I also highly recommend this [talk on optimization and benchmarking](http://2012.jsconf.eu/speaker/2012/09/05/faster-than-c-parsing-node-js-streams-.html) ([slides](https://github.com/felixge/faster-than-c)).


### Things to test

Here are the most important things we need to benchmark:

##### Features:

+ Bootstrap
  + `sails.load` (programmatic)
  + `sails.lift` (programmatic) and `sails lift` (CLI)
  + `sails load`
  + `sails new` and `sails generate *`
    + (could be pulled into generic generator suite, like adapters)

+ Router
  + private Sails requests via `sails.emit('request')`
  + http requests to the HTTP server
  + http file uploads to the HTTP server
  + connections to the socket.io server
  + socket emissions to the socket.io server
  + socket broadcasts FROM the socket.io server (pubsub hook)


> Thankfully, the ORM is already covered by the benchmarks in Waterline core and its generic adapter tests.


##### Measuring:

+ Execution time
+ Memory usage

##### Under varying levels of stress:

+ Low concurrency (c1k)
+ High-moderate concurrency (c10k)

##### In varying environments:

+ Every permutation of the core hook configuration
+ With different configuration options set


### Considerations

Some important things to consider when benchmarking Node.js / Express-based apps in general:

+ Keep in mind that, unless you use the cluster module, or spin up multiple instances of the server, you're testing performance on one CPU.  Most production servers, cloud or not, have more than one CPU available.  This may or may not be relevant, depending on the benchmark and whether it is CPU-intensive.
+ Be sure to configure [`maxSockets`](http://nodejs.org/api/http.html#http_agent_maxsockets), since most of the requests in a benchmark test are likely to originate from the same source.

> **Sources:**
> + https://groups.google.com/forum/#!topic/nodejs/tgATyqF-HIc



### Benchmarking libraries

> Don't know the best route here yet-- but here are some links for reference.  Would love to hear your ideas!

+ https://github.com/spumko/flod
+ https://github.com/LearnBoost/mongoose/blob/3.8.x/benchmarks/benchjs/casting.js
+ https://npmjs.org/package/benchmark

---

### Overview (`test/integration/README.md`)

# Integration tests

The goal of these tests is to run Sails just like you or I would, and verify that no anomolies have been introduced in general.

This is a great place to jump in if you're interested in contributing code to Sails core!

## How Can I Help?

We could use your help writing more integration tests that test Sails under specific conditions.

#### Integration tests for each core hook

When writing an integration tests that verifies the behavior of a particular hook, the following assertions should be made:

1. Did the hook's default config make it into `sails.config`?
2. Did `sails.load` work as expected with the hook enabled and all the hooks it depends on enabled?
3. Did `sails.lift` work as expected with the hook enabled and all the hooks it depends on enabled?
4. Post-`sails.load`, is the process/application state correct? (i.e. did the hook do what it was supposed to do?)
5. Did the hook do what it was supposed to do after tearing down the server using `sails.lower()`?


#### Integration tests for the hook loader

We could really use more tests for the following cases:

1. If we `sails.load` using `loadHooks` to allow only specific hooks, or `hooks` to disable particular hooks, only the specified hooks should actually be loaded.
2. `sails.load()` should fail if a test tries to load a hook that depends on other hooks, but those other hooks are disabled.  Note that `sails.load` should _fail with a relevant error message_ and _should not_ hang in this case.

---

### Overview (`test/unit/README.md`)

# Unit tests

Unit tests shouldn't lift the server (i.e. bind an HTTP server or WebSocket server to a port). Instead, they should bootstrap the minimal set of necessary components to test a particular method (or sometimes a group of methods, if it makes more sense.)  The goal is to identify future breaking changes and isolate _exactly what broke_.  This makes would-be issues easier to spot in advance, and real bugs easier to track down after the fact.


## What _Not_ To Test
Since unit tests are more implementation-specific, we shouldn't unit test parts of Sails which are currently in flux or likely to change.

## How Can I Help?


#### Unit tests for the hook loader

1. If we run the hook loader with options for conditionally loading hooks, the server should start with the correct hooks applied.
2. The hook loader should fail if a hook has other hooks as dependencies, but those dependencies are omitted.
3. If a graph of circular dependencies is passed into the hook loader, it should fail.

> No one is currently working on this



#### Unit tests for each core hook

1. initialize()
2. loadModules()
3. configure()
3. Other important methods (hook-specific)

> No one is currently working on this

---

### Overview (`lib/hooks/blueprints/README.md`)

# sails-hook-blueprints

Implements support for the blueprint API in Sails.

> This is a core hook in the Sails.js framework.  You can override or disable it using your `.sailsrc` file or environment variables.  See [Concepts > Configuration](http://sailsjs.com/docs/concepts/configuration) for more information.


## Purpose

This hook's responsibilities are:

1. Use `sails.modules` to read blueprints from the user's app into `self.middleware`.
2. Bind shadow routes to blueprint actions and controller actions.
3. Listen for `route:typeUnknown` on `sails`, interpret route syntax which should match a blueprint action, and bind the appropriate middleware (this happens when the Router is loaded, after all the hooks.)


## Help

Have questions or having trouble?  Click [here](http://sailsjs.com/support).

> For more information on overriding core hooks, check out [Extending Sails > Hooks](http://sailsjs.com/documentation/concepts/extending-sails/hooks).


## Bugs &nbsp; [](http://npmjs.com/package/sails-hook-blueprints)

To report a bug, [click here](http://sailsjs.com/bugs).


## Contributing

Please observe the guidelines and conventions laid out in the [Sails project contribution guide](http://sailsjs.com/documentation/contributing) when opening issues or submitting pull requests.

[](http://npmjs.com/package/sails-hook-blueprints)

## License

The [Sails framework](http://sailsjs.com) is free and open-source under the [MIT License](http://sailsjs.com/license).

---

### Overview (`lib/hooks/http/README.md`)

# http (Core Hook)

## Status

> ##### Stability: [2](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Stable


## Dependencies

In order for this hook to load, the following other hooks must have already finished loading:

- moduleloader


## Peers

If the following other core hooks are enabled, the behavior of this hook will change:

- session
- views


## Dependents

If this hook is disabled, in order for Sails to load, the following other core hooks must also be disabled:

- views



## Purpose

This hook's responsibilities are:

##### Start an HTTP server and handle requests

This hook starts an http or https server and listens for incoming requests when Sails core
emits an event letting us know it's time to "lift" (rather than just "load").

##### Bind the configured middleware, along with built-in defaults

This hook binds built-in HTTP middleware, in addition to custom middleware functions (`sails.config.http.middleware`).
The order in which middleware can be bound is configurable in `sails.config.http.middleware.order`.

> Note that it is possible for the configured HTTP middleware stack to be shared with the
> core router built into Sails-- this would make the same stack take effect for all virtual requests
> including sockets.  Currently, an abbreviated version of this stack is built-in to `lib/router/`
> in an imperative way (rather than the declarative approach used here: a sorted array of named middleware).
>
> In Sails core, this has been explored in a number of different ways in the past.
> In the future, it would be possible to add a separate middleware stack configuration for virtual
> requests (including socket requests).  However, while this would certainly be more consistent, in practice,
> this would have an unwanted impact on performance.




## Implicit Defaults

This hook sets the following implicit default configuration on `sails.config`:

> **TODO: document**
>
> _(if you'd like to help, please send a pull request expanding this section.  See `hooks/logger/README.md` for an example)_



## Events

##### `hook:http:loaded`

Emitted when this hook has been automatically loaded by Sails core, and triggered the callback in its `initialize` function.



## Methods

> **TODO: document**
>
> _(if you'd like to help, please send a pull request expanding this section.  See `hooks/responses/README.md` for an example)_



## FAQ

> If you have a question about this hook that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer, a core maintainer will merge your PR and add an answer as soon as possible)

---

### Overview (`lib/hooks/logger/README.md`)

# logger (Core Hook)


## Status

> ##### Stability: [0](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Deprecated
>
> This hook will almost certainly be merged into core (see FAQ below).



## Dependencies

In order for this hook to load, the following other hooks must have already finished loading:

- moduleloader
- userconfig


## Dependents

If this hook is disabled, in order for Sails to load, the following other core hooks must also be disabled:

_N/A_


## Purpose
This hook's responsibilities are:


##### Set up CaptainsLog
Instantiate a [CaptainsLog](https://github.com/balderdashy/captains-log) logger instance.


##### Expose `sails.log` function
Publicly expose `sails.log()` function (see http://sailsjs.com/documentation/concepts/logging)


##### Add `sails.log.ship()` method
Add an extra method to the logger which teaches it how to draw a ship in ASCII.





## Implicit Defaults
This hook sets the following implicit default configuration on `sails.config`:


| Property                                       | Type          | Default         |
|------------------------------------------------|:-------------:|-----------------|
| `sails.config.log.level`                       | ((string))    | `'info'`        |





## Events

##### `hook:logger:loaded`

Emitted when this hook has been automatically loaded by Sails core, and triggered the callback in its `initialize` function.




## FAQ

+ Why is this a hook and not part of core?
  + Originally, it was as a way of separating concerns.  But realistically, this particular hook _could_ be merged into core (under `app`) in a future release.  But realistically since the core configuration process does everything this hook does anyways, this hook _might as well_ be merged into core (under `app`).  Look for this to happen in a future release.

> If you have a question that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/hooks/moduleloader/README.md`)

# `moduleloader` (Core Hook)

This hook exposes `sails.modules`, a set of functions which other core hooks call to load modules from an app's configured directories in `sails.config.paths`.

The moduleloader hook is always the first core hook to load; even before `userconfig`.  Consequently, in order to customize `sails.config.paths`, you need to inject configuration into the load process using env variables, the .sailsrc file, or by passing in an option to the programmatic call to sails.lift (i.e. in app.js). Otherwise, by the time your user configuration files in config/* have loaded, it is too late (this hook has already run using the default paths).

---

### Overview (`lib/hooks/policies/README.md`)

# Policies (Core Hook)

## Status

> ##### Stability: [2](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Stable


## Purpose

This hook's responsibilities are:

1. Use `sails.modules` to read policies from the user's app into `self.middleware`.
2. Normalize the policy mapping config (`sails.config.policies`)
3. Listen for `route:typeUnknown` and bind a policy if the route requests it.
4. Listen for `router:before` and when it fires, transform loaded middleware that match the policy mapping config (i.e. controller actions) to arrays of functions, where the original middleware is "protected" by one or more relevant policy middleware.



## FAQ

> No frequently asked questions yet...
>
> If you have a question, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/hooks/pubsub/README.md`)

# Pubsub (core hook)

See http://sailsjs.com/documentation/reference/web-sockets/resourceful-pub-sub for more info.

---

### Overview (`lib/hooks/request/README.md`)

# request (Core Hook)

> In future releases, the various responsibilities of this hook will likely be farmed out to other hooks and/or pulled into core.

## Purpose

This hook's responsibilities are:

##### Add properties to `req`
+ req.params.all()
+ req.wantsJSON()
+ req.explicitlyAcceptsHTML()
+ req.baseUrl
+ req.port
+ req._sails (access to the app's `sails` object in case it's not global)

##### Set default view locals (i.e. `app.locals`)
+ `_` (lodash)
+ `session`
+ `req`
+ `res`
+ `sails`

> Note that this will likely move into the `views` hook in the future.



## FAQ

> If you have a question that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/hooks/responses/README.md`)

# responses (Core Hook)

## Status

> ##### Stability: [2](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Stable


## Dependencies

In order for this hook to load, the following other hooks must have already finished loading:

- moduleloader



## Dependents

If this hook is disabled, in order for Sails to load, the following other core hooks must also be disabled:

- blueprints



## Purpose

This hook's responsibilities are:


##### Support `response` route target syntax

This hook listens for the `route:typeUnknown` event, and if the unknown route target syntax contains a `response` key, it binds the route address to a middleware function that does nothing except send that response.

For example:

```
'post /foo': {
  response: 'ok'
}
```

...would run `res.ok()` whenever a POST request to `/foo` is received.


##### Load custom responses

When Sails loads, this hook loads custom response files from the app's responses folder and merges them with built-in defaults, storing them in-memory as "outlet functions".  Conventionally this is `api/responses/*.js`, but it can be configured in `sails.config.paths`.


##### Bind shadow route that exposes response functions as `res.*`

This hook binds a shadow route that intercepts all incoming requests and attaches a method to `res` for each of the outlet functions (representing custom responses) that were prepared when the hook was initialized.



## Implicit Defaults

This hook sets the following implicit default configuration on `sails.config`:

_N/A_



## Events

##### `hook:responses:loaded`

Emitted when this hook has been automatically loaded by Sails core, and triggered the callback in its `initialize` function.



## Methods


#### sails.hooks.responses.loadModules()

Load custom responses modules from the responses directory in the current app (conventionally this is `api/responses/`).

```javascript
sails.hooks.responses.loadModules(cb);
```


###### Usage


|     |          Argument           | Type                | Details
| --- | --------------------------- | ------------------- | ----------------------------------------------------------------------------------
| 1   |        **cb**               | ((function))        | Fires when the custom response modules have been loaded or if an error occurs.


> ##### API: Private
> - Please do not use this method in userland (i.e. in your app or even in a custom hook or other type of Sails plugin).
> - Because it is a private API of a core hook, if you use this method in your code it may stop working or change without warning, at any time.
> - If you would like to see a version of this method made public and its API stabilized, please open a [proposal](https://github.com/balderdashy/sails/blob/master/CONTRIBUTING.md#v-proposing-features-and-enhancements).
>
> _(internally in core, note that this is called by the `moduleloader` hook)_



## FAQ

> If you have a question about this hook that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer, a core maintainer will merge your PR and add an answer as soon as possible)

---

### Overview (`lib/hooks/security/README.md`)

# security (Core Hook)


## Status

> ##### Stability: [2](https://github.com/balderdashy/sails-docs/blob/master/contributing/stability-index.md) - Stable



## Dependencies

In order for this hook to load, the following other hooks must have already finished loading:

- moduleloader
- userconfig


## Dependents

If this hook is disabled, in order for Sails to load, the following other core hooks must also be disabled:

_N/A_


## Purpose

This hook's responsibilities are:


##### Bind shadow routes to set appropriate CORS headers

When Sails loads, this hook binds a `router:before` listener so that it can bind routes before the router binds explicit routes.  Then it binds shadow routes for the appropriate endpoints based on `sails.config.cors` (also mixing in its implicit defaults).

##### Sets up CRSF action

It generates `security/grant-csrf-token` action 

## Implicit Defaults

This hook sets the following implicit default configuration on `sails.config.security`:


| Property                                      | Type          | Default         |
|-----------------------------------------------|:-------------:|-----------------|
| `sails.config.security.cors.allowOrigins`                    | ((string))    | `'*'`
| `sails.config.security.cors.allRoutes`                 | ((boolean))   | `false`
| `sails.config.security.cors.allowCredentials`               | ((boolean))   | `false`
| `sails.config.security.cors.allowRequestMethods`                   | ((string))    | `'GET, HEAD, PUT, PATCH, POST, DELETE'`
| `sails.config.security.cors.allowRequestHeaders`                   | ((string))    | `'content-type'`
| `sails.config.security.cors.allowResponseHeaders`             | ((string))    | `''` _(empty string)_
| `sails.config.security.cors.allowAnyOriginWithCredentialsUnsafe`             | ((boolean))    | `false`
| `sails.config.security.csrf`             | ((boolean))    | `false`




## Events

##### `hook:security:loaded`

Emitted when this hook has been automatically loaded by Sails core, and triggered the callback in its `initialize` function.




## FAQ

> If you have a question that isn't covered here, please feel free to send a PR adding it to this section (even if you don't have the answer!)

---

### Overview (`lib/hooks/session/README.md`)

## Session Hook

At configuration-time, this hook loads verifies valid configuration of the connect session store (configurable in `sails.config.session`),
At lift-time, it instantiates the session store and makes it accesible via `sails.session`.

It includes methods for:
  + attaching a connect session to a socket.io connection
  + generating new sessions
  + getting and setting the session



##### Contributing to this hook
It would be great to see a generic connect session adapter with support for the existing 'connections' in sails (ie. waterline adapters).  See [connect-waterline](https://www.npmjs.com/package/connect-waterline).

---

### Overview (`lib/hooks/userconfig/README.md`)

## Userconfig Hook

This hook loads app-level user configuration using the moduleloader hook (from the config directory located at `sails.config.paths.config`) It is always loaded first.

##### Contributing to this hook
Not a good place to jump in right now.  Please tweet @mikermcneil before working on this part!

---

### Overview (`lib/hooks/userhooks/README.md`)

## Userhooks Hook

This hook loads hooks from the user hooks directory, configurable in `sails.config.paths.hooks` (defaults to `api/hooks`) of a sails app.  If the directory doesn't exist, this hook is a no-op.

##### Contributing to this hook
Not a good place to jump in right now.  Please tweet @mikermcneil before working on this part!

---

### Overview (`lib/app/private/controller/README.md`)

# Actions in Sails

In Sails, an _action_ is a named request handler that is intended to be bound directly to a route in an app's `config/routes.js` file.  Actions may be loaded from disk (typically from the `api/controllers` project folder and subfolders), from runtime configuration (in `sails.config.controllers.moduleDefinitions`) or added by hooks (using `sails.registerAction`).

##### Benefits of actions

By using actions to represent the majority of the code that is executed at runtime in user apps, we get the following benefits:

* An easy way to reference all of the available request handlers -- calling `sails.getActions()` returns a list of all actions registered by the user _and_ by hooks like the blueprints hook.
* Simplified user routing -- instead of hooks adding routes whose address must be configured separately (e.g. the `/csrfToken` route) or referenced using a separate syntax (e.g. the `{response: 'notFound'}` route target syntax), hooks simply provide an action for the app developer to route to in `config/routes.js` using a single, streamlined syntax.
* Ability to easily add middleware that applies only to app-level code, and not to all routes.  Instead of binding to `/*` in a hook and then excluding assets (or forgetting to), `registerActionMiddleware` can be used to add handlers _only_ to actions.

##### Should my hook register an action, bind a route, or both?

If you are creating a hook that adds request handlers to a Sails app, and you want the app developer to be able to bind their own routes to those request handlers, then you should register the handler as an action (the core "blueprints", "responses" and "views" hooks are good examples of this).  This doesn't mean you can't also bind routes directly within the hook (this is how blueprint RESTful routes are created, for example), especially if the user may override your hook's action with their own (as may happen with blueprint or response actions).

On the other hand, if your hook creates a request handler that is not intended to be bound directly by the app developer, and/or it is not intended to be overridden, you may not want to register that handler as an action.  Handlers that _modify_ requests and then call `next()` (for example the `addLocalizationMethod` handler in the core `i18n` hook) generally fall into this category.

Somewhere in the middle lie hooks that create a request handler that you may want the app developer to be able to bind directly, but which should _not_ be overridable.  A good example of this is the core `CSRF` hook; besides adding CSRF protection to an app's routes, it also provides an action which returns the current CSRF token.  It is desirable to allow this action to be bound to a route in the `config/routes.js` file (so that the app developer can choose the address to bind it to), but it is _not_ desirable for the user to override the action with their own code.  In this case, a hook can register the action as "not overridable" by beginning namespacing it under `_.` (e.g. `sails.registerAction(myAction, '_.csrf.return-token')`).

> Alternate idea: have hooks register actions under UPPERCASED version of their name, e.g. `CSRF.return-token`

##### Action middleware

Action middleware are functions that are intended to _modify_ actions (or more accurately, the requests that the actions handle).  You may register middleware that affects a single action, a subset of actions, or all actions.  Note that action middleware _only_ affects actions; if you need to modify _all_ requests (particularly, if you need to modify requests that return assets), you should still bind a route directly to `/*` in your hook.



## Action-related methods in Sails

### Public methods

##### `sails.registerAction(action, identity)`

Registers an action in Sails.  It is very similar in function to the private `registerAction` method, with the notable exception that there is no `force` argument: if a call to `registerAction` results in an attempt to overwrite an existing key in the actions dictionary, the call will trigger an error with code `E_CONFLICT`.

##### `sails.getActions()`

Returns a shallow clone of the internal Sails actions dictionary.  This is a flat (i.e. one-level) dictionary where the keys are the kebab-cased, dash-delimited action identities, and the values are the action functions (all actions in the dictionary will have been converted to `req, res` functions at this point).

##### `sails.registerActionMiddleware(middleware, includeActions, excludeActions)`

Registers middleware that will run before the specified actions.  Middleware should be `req, res, next` functions.  The `includeActions` and `excludeActions` arguments are strings or arrays of strings describing the actions that the middleware should (or should not) be attached to, using `*` as a wildcard to cover multiple actions at once.

Examples:

**Register middleware that affects all actions**:
```
sails.registerActionMiddleware(mustBeLoggedIn, '*')
````

**Register middleware that affects all `user` actions**:
```
sails.registerActionMiddleware(mustBeLoggedIn, 'user.*')
````

**Register middleware that affects all `user` and `pet` actions**:
```
sails.registerActionMiddleware(mustBeLoggedIn, ['user.*', 'pet.*'])
````

**Register middleware that affects all `user` and `pet` actions _except_ user.hello**:
```
sails.registerActionMiddleware(mustBeLoggedIn, ['user.*', 'pet.*'], 'user.hello')
````

**Register middleware that affects all `user` and `pet` actions _except_ ones namespaced under "public"**:
```
sails.registerActionMiddleware(mustBeLoggedIn, ['user.*', 'pet.*'], ['user.public.*', 'pet.public.*'])
````



### Private utilities

> _Please do not use these in a hook (even a core hook) or in any userland code!  They may change at any time, without warning!_

##### `loadActionModules()`

When Sails loads, this method loads all of the files underneath the controllers directory (`api/controllers` by default) and attempts to parse them into actions that can be bound to routes.  File in the controllers directory can either be pascal-cased and ending in "Controller" (e.g. MyController.js), in which case they are expected to be _dictionaries_ of actions, or else kebab-cased and lowercased (e.g. my-action.js) in which case they are expected to contain a single action.  An action may be a function which accepts `req` and `res` as arguments, or a [node-machine](http://node-machine.org) definition which will be parsed by [machine-as-action](https://github.com/treelinehq/machine-as-action).

After actions are loaded from disk, any actions specified under the `sails.config.controllers.moduleDefinitions` config key are merged on top of those actions.  This allows Sails apps to be constructed dynamically at runtime.

Note that this method is called internally by Sails _after_ hooks have loaded (or in the case of a `Sails.reloadModules` call, after they have _reloaded_).  This ensures that user actions always take precedence over those added by hooks.

##### `helpRegisterAction(action, identity, [force])`

This method takes an _action_ (in the form of a function or a machine definition, which is transformed into a function via `machine-as-action`) and adds it to the internal `Sails._actions` dictionary under the key specified by `identity`.  Keys in the internal dictionary can be overridden by setting the `force` argument to `true`; otherwise any conflict will result in an error being thrown.

---

### Contributing Stability Index (`docs/contributing/stability-index.md`)

# Stability index

Throughout the documentation and in README files in Sails, you will see indications of a section's stability. The Sails framework is still somewhat changing, and as it matures, certain parts are more reliable than others. Some are so proven, and so relied upon, that they are unlikely to ever change at all. Others are brand new and experimental, or known to be hazardous and in the process of being redesigned.

Stability indices are used to describe individual methods, events, and configuration settings _as well_ as sub-modules of Sails core such as core hooks.  The latter affordance is a soft science-- the core team labels hooks with stability indices in order to provide a better experience for developers building plugins for Sails and/or contributing to Sails core.

When a stability index refers to a module like a core hook, note that that index refers to the **features of that hook which are _explicitly public_**.  For example, if the documentation for a hook mentions that it "exposes" a property called `foo` on the `sails` app object, then you can _only rely on that property_ to respect the hook's the stability level if it is also clearly marked as "public" elsewhere in the hook documentation.  If in doubt, submit a pull request to the relevant hook's README file in the [GitHub repository for Sails core](https://github.com/balderdashy/sails) and add a question to the FAQ section.

The stability indices are as follows:

##### Stability: 0 - Deprecated
This feature is known to be problematic, and changes are planned.  Do not rely on it in new code, and be sure to change existing code before upgrading.  Use of the feature may cause warnings.  Backwards compatibility should not be expected.

##### Stability: 1 - Experimental
This feature is subject to change or removal in future major releases of Sails.

##### Stability: 2 - Stable
This feature has proven satisfactory. Compatibility with existing Sails apps and the plugin ecosystem is a high priority, and so stable hooks/features/etc. will not be broken or removed in future major releases unless absolutely necessary.

##### Stability: 3 - Locked
This hook/feature/etc. will not undergo any future API changes, except as demanded by critical fixes related to security or performance.  Please do not propose usage/philosophical changes for features/hooks/etc. at this stability index; they will be refused.



### Notes
> - Sails' stability index, and much of the verbiage of this file, is based on [the Stability Index used by Node.js core](https://nodejs.org/api/documentation.html#documentation_stability_index).

<docmeta name="notShownOnWebsite" value="true">

---

### PAGE NEEDED (`docs/PAGE_NEEDED.md`)

# Page Needed

If you&rsquo;re seeing this page, it means you've clicked on a link to a Sails doc that has yet to be written.  Help make Sails better by contributing to the docs!

Please send a pull request to master with corrections/additions and they'll be double-checked and merged as soon as possible.

Secondly, we are open to suggestions about the process we're using to manage our documentation, and to work with the community in general. Please post to the Google Group with your ideas, or if you're interested in helping directly, contact @fancydoilies, @aaaaanxiety, or @mikermcneil on Twitter.

Love,

The Sails Team

---

### Anatomy .Editorconfig (`docs/anatomy/.editorconfig.md`)

# .editorconfig

This file exists to help maintain consistent formatting throughout the files in your Sails app.

For more information, see [editorconfig.org](http://editorconfig.org/).


<docmeta name="displayName" value=".editorconfig">

---

### Anatomy .Eslintignore (`docs/anatomy/.eslintignore.md`)

# .eslintignore

This file exists to signify to [ESLint](https://eslint.org/) that certain files and/or directories should be ignored for the purposes of linting.

<docmeta name="displayName" value=".eslintignore">

---

### Anatomy .Eslintrc (`docs/anatomy/.eslintrc.md`)

# .eslintrc

This file defines a set of basic code conventions designed to encourage quality and consistency across your Sails app's code base.

For more information, see [eslint.org](https://eslint.org/).

<docmeta name="displayName" value=".eslintrc">

---

### Anatomy .Htmlhintrc (`docs/anatomy/.htmlhintrc.md`)

# .htmlhintrc

This file defines the rules for your app's [HTMLHint](http://htmlhint.com/), to encourage quality and consistency in your views and templates.

<docmeta name="displayName" value=".htmlhintrc">

---

### Anatomy Gruntfile.Js (`docs/anatomy/Gruntfile.js.md`)

# Gruntfile.js


Sails uses [Grunt](http://gruntjs.com) for asset management. This file contains the entry point for the default asset pipeline in Sails; that is, the code that does stuff like compiling LESS stylesheets, minifying scripts for production, and precompiling and injecting client-side templates.

Sails' integration with Grunt is fully customizable, but for most use cases, this file (`Gruntfile.js`) should remain unchanged.  Instead, you can install Grunt plugins or add your own custom logic as new files in the [`tasks/`](./tasks) folder.

> + To learn more about working with static assets in Sails, check out the [conceptual documentation on assets](https://sailsjs.com/documentation/concepts/assets).
> + For a broader introduction to Grunt tasks in general, see [Grunt's docs on configuring tasks](http://gruntjs.com/configuring-tasks).


<docmeta name="displayName" value="Gruntfile.js">

---

### Anatomy README.Md (`docs/anatomy/README.md.md`)

# README.md

This is a generic README that you can edit to describe your app.


<docmeta name="displayName" value="README.md">

---

### Anatomy Anatomy (`docs/anatomy/anatomy.md`)

# Anatomy of a Sails app

An interactive guide to the structure of the Sails app generated by default with `sails new`.

Choose from any of the files or folders in the list to learn more about its purpose.

<docmeta name="displayName" value="Anatomy of a Sails app">
<docmeta name="isOverviewPage" value="true">

---

### Anatomy App.Js (`docs/anatomy/app.js.md`)

# app.js

This file is the conventional entry point for a _production_ Sails/Node.js app.

When developing on your local computer, and you run `sails lift`, the code in `app.js` is not executed.  Instead, this file exists to provide an easy, out-of-the-box way to run your app _without_ typing `sails lift`.  This is most likely how you'll start your app in production (i.e. `node app`, or `npm start`).

For example, when you deploy to most PaaS vendors like [Heroku](http://heroku.com), they will automatically detect that you're running a Sails/Node.js app and execute this file with the `NODE_ENV` environment variable set to production.

> Whatever stage of the development lifecycle you're at, you can safely ignore `app.js`.  It's good to go out of the box for most apps.  But the code in `app.js` also serves as an easy-to-reference example of how to use Sails programmatically.  So you might want to take a look at it if you plan on writing automated tests, scheduled jobs, manual database migrations, or administration scripts.


<docmeta name="displayName" value="app.js">

---

### Anatomy Gitignore (`docs/anatomy/gitignore.md`)

# .gitignore

This file is only relevant if you are using git.

It informs `git` of any files that you don't want `pushed` to the remote server.

Files which match the splat patterns seen in the code below will be ignored by git.  This keeps random crap and and sensitive credentials from being uploaded to  your repository.  It allows you to configure your app for your machine without accidentally committing settings which will smash the local settings of other developers on your team.

Some reasonable defaults are included, but, of course, you should modify/extend/prune to fit your needs!

[Read more about .gitignore](https://help.github.com/articles/ignoring-files)



<docmeta name="displayName" value=".gitignore">

---

### Anatomy Package.Json (`docs/anatomy/package.json.md`)

# package.json

This is a standard configuration file for [npm](https://npmjs.org/doc/json.html). Among other things, this file contains the name and version of all of the Node Modules that your app depends on to run.  You can change this manually but be careful to adhere to their rules or things might break.

<docmeta name="displayName" value="package.json">

---

### Anatomy Sailsrc (`docs/anatomy/sailsrc.md`)

# .sailsrc

This file is useful for setting configuration that you want to generate programmatically.  You can also use it to extend the functionality of the Sails CLI tool, for example to add a generator.

You can learn more about using sailsrc files [here](https://sailsjs.com/documentation/concepts/configuration/using-sailsrc-files).


<docmeta name="displayName" value=".sailsrc">

---

### Concepts Concepts (`docs/concepts/concepts.md`)

# Sails.js Documentation > Core Concepts

> The contents of this file are overridden automatically during compilation (please do not edit manually!)

<docmeta name="displayName" value="Core Concepts: Table of Contents">
<docmeta name="isTableOfContents" value="true">

---

### Contributing Adapter Specification (`docs/contributing/adapter-specification.md`)

# Adapter interface reference

> The adapter interface specification is currently under active development and may change.


## Semantic (interface)
> e.g. `RestAPI` or `MySQL`

> ##### Stability: [3](http://nodejs.org/api/documentation.html#documentation_stability_index) - Stable

Implementing the basic semantic interface (CRUD) is really a step towards a complete implementation of the Queryable interface, but with some services/datasources, about as far as you'll be able to get using native methods.

By supporting the Semantic interface, you also get the following:
+ if you write a `find()` function, developers can also use all of its synonyms, including dynamic finders and `findOne()`.  When they're called, they'll automatically be converted into the appropriate criteria object for the basic `find()` definition in your adapter.
+ as long as you implement basic `where` functionality (see `Queryable` below), Waterline can derive a simplistic version of associations support for you.  To optimize the default assumptions with native methods, override the appropriate methods in your adapter.




> All officially supported Sails.js database adapters implement the `Semantic` interface.

###### Class methods
+ `Model.create()`
+ `Model.find()`
+ `Model.update()`
+ `Model.destroy()`
+ Optimizations:
  + `findOrCreate()`
  + `createEach()`
  + Not yet available:
    + `destroyEach()`
    + `updateEach()`
    + `findOrCreateEach()`
    + `findAndUpdateOrCreate()`
    + `findAndUpdateOrCreateEach()`




## Queryable (interface)

> ##### Stability: [3](http://nodejs.org/api/documentation.html#documentation_stability_index) - Stable

Query building features are common in traditional ORMs, but not at all a guarantee when working with Waterline.  Since Waterline adapters can support services as varied as Twitter, SMTP, and Skype, traditional assumptions around structured data don't always apply.

If query modifiers are enabled, the adapter must support `Model.find()`, as well as the **complete** query interface, or, where it is impossible to do so, at least provide good error messages.  If coverage of the interface is unfinished, it's still not a bad idea to make the adapter available, but it's important to clearly state the unifinished parts, and consequent limitations, up front.  This helps prevent the creation of off-topic issues in Sails/Waterline core, protects developers from unexpected consequences, and perhaps most importantly, helps focus contributors on high-value tasks.

> All officially supported Sails.js database adapters implement this interface.

###### Query modifiers
Query modifiers include normalized syntax:
+ `where`
+ `limit`
+ `skip`
+ `sort`
+ `select`

And WHERE supports:

Boolean logic:
+ `and`
+ `or`
+ `not`


`IN` queries:
Adapters which implement `where` should recognize a list of values (e.g. `name: ['Gandalf', 'Merlin']`) as an `IN` query.  In other words, if `name` is either of those values, a match occured.

Sub-attribute modifiers:
You are also responsible for sub-attribute modifiers, (e.g. `{ age: { '>=' : 65 } }`) with the notable exception of `contains`, `startsWith`, and `endsWith`, since support for those modifiers can be derived programatically by leveraging your definition of  `like`.
+ `like`    (SQL-style, with % wildcards)
+ `'>' `    (you can also opt to use the more verbose `.greaterThan()`, etc.)
+ `'<' `
+ `'>='`
+ `'<='`


## Migratable (interface)

> ##### Stability: [1](http://nodejs.org/api/documentation.html#documentation_stability_index) - Experimental

Adapters which implement the Migratable interface are usually interacting with SQL databases.  This interface enables the `migrate` configuration option on a per-model or adapter-global basis, as well as access to the prototypal/class-level CRUD operations for working with tables.

###### Adapter methods

> This is not how it actually works, but how it could work soon:

+ `Adapter.define()`
+ `Adapter.describe()`
+ `Adapter.drop()`
+ `Adapter.alter()` (change table name, other table metadata)
+ `Adapter.addAttribute()` (add column)
+ `Adapter.removeAttribute()` (remove column)
+ `Adapter.alterAttribute()` (rename column, add or remove uniquness constraint to column)
+ `Adapter.addIndex()`
+ `Adapter.removeIndex()`


###### Auto-migration strategies
+ `"safe"` (default in production env)
  + do nothing
+ `"drop"` (default in development env)
  + drop all tables and recreate them each time the server starts-- useful for development
+ `"alter"`
  + experimental automigrations
+ `"create"`
  + create all missing tables/columns without modifying existing data



## SQL (interface)

> ##### Stability: [1](http://nodejs.org/api/documentation.html#documentation_stability_index) - Experimental

Adapters which implement the SQL interface interact with databases supporting the SQL language. This interface exposes the method `.query()` allowing the user to run *raw* SQL queries against the database.

###### Adapter methods

+ `Adapter.query(query,[ data,] cb)`







<docmeta name="notShownOnWebsite" value="true">

---

### Contributing Code Of Conduct (`docs/contributing/code-of-conduct.md`)

# Code of conduct

> The Code of Conduct explains the *bare minimum* behavior expectations the Sails project requires of its contributors.  This Code of Conduct is adapted from the version used by the [Node.js core team](https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md).  Their version was originally borrowed from [Rust lang's excellent CoC](http://www.rust-lang.org/conduct.html).

- We are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, disability, ethnicity, religion, or similar personal characteristic.
- Please avoid using overtly sexual, racial, or political nicknames, or any other nicknames that might detract from a friendly, safe and welcoming environment for all.
- Please be kind and courteous. There's no need to be mean or rude.
- Avoid the use of personal pronouns in any code comments or documentation where such use could be perceived in a negative light. There is no need to address persons when explaining code (e.g. "When the developer").
- Respect that some individuals and cultures consider the casual use of profanity offensive and off-putting.
- Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
- Please keep unstructured critique to a minimum. If you have ideas you want to experiment with, make a fork and see how it works.
- We will exclude you from interaction if you insult, demean or harass
  anyone. That is not welcome behavior. We interpret the term
  "harassment" as including the definition in the [Citizen Code of
  Conduct](http://citizencodeofconduct.org/); if you have any lack of
  clarity about what might be included in that concept, please read
  their definition, or ask one of the project maintainers first.
  In particular, we don't tolerate defamatory remarks or behavior that
  excludes people in socially marginalized groups, or for whom English
  is not a native language.
- Private harassment is also unacceptable. No matter who you are, if
  you feel you have been or are being harassed or made uncomfortable
  by a community member, please contact one of the core maintainers immediately
  via private message on Twitter or by emailing [inquiries@sailsjs.com](inquiries@sailsjs.com).
  In either case, include a capture (screenshot, log, photo, email) of
  the harassment if possible. Whether you're a regular contributor or
  a newcomer, we care about making this community a safe, comfortable
  place for you and we've got your back.
- Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome,
  and will result in your exclusion.


<docmeta name="displayName" value="Code of conduct">

---

### Contributing Contributing To The Documentation (`docs/contributing/contributing-to-the-documentation.md`)

# Contributing to the documentation
The official documentation on the Sails website is compiled from markdown files in the [sails](https://github.com/balderdashy/sails/sails-docs) repo. Please send a pull request to the **master** branch with amendments and they'll be double-checked and merged as soon as possible.

We are open to suggestions about the process we're using to manage our documentation, and to working with the community in general.  Please post to the [Gitter](https://gitter.im/balderdashy/sails) with your ideas; or, if you're interested in helping directly, contact @fancydoilies or @mikermcneil on Twitter.

#### What branch should I edit?

That depends on what kind of edit you are making.  Most often, you'll be making an edit that is relevant for the latest stable version of Sails (i.e. the version on [NPM](npmjs.org/package/sails)) and so you'll want to edit the `master` branch of _this_ repo (what you see in the sails repo by default).  The docs team merges master into the appropriate branch for the latest stable release of Sails, and then deploys that to sailsjs.com about once per week.

On the other hand, if you are making an edit related to an unreleased feature in an upcoming version&mdash;usually as an accompaniment a feature proposal or open pull request to Sails or a related project&mdash;then you will want to edit the branch for the next, unreleased version of Sails (sometimes called "edge").


| Branch (in `sails` or `sails-docs`)                    | Documentation for Sails Version...                                   | Preview At...      |
|-------------------------------------------------------------------------------------|------------------------|:-------------------|
| [`master`](https://github.com/balderdashy/sails/tree/master/docs) | [](http://badge.fury.io/js/sails) | [preview.sailsjs.com](http://preview.sailsjs.com)
| [`0.12`](https://github.com/balderdashy/sails-docs/tree/0.12) | Sails v0.12.x | [sailsjs.com](https://sailsjs.com)
| [`0.11`](https://github.com/balderdashy/sails-docs/tree/0.11) | Sails v0.11.x           | [0.11.sailsjs.com](http://0.11.sailsjs.com)


#### How are these docs compiled and pushed to the website?

We use a module called `doc-templater` to convert the .md files to the HTML for the website. You can learn more about how it works in [the doc-templater repo](https://github.com/uncletammy/doc-templater).

Each .md file has its own page on the website (e.g. all reference, concepts, and anatomy files), and should include a special `<docmeta name="displayName">` tag with a `value` property specifying the title for the page.  This will impact how the doc page appears in search engine results, and it will also be used as its display name in the navigation menu on sailsjs.com.  For example:

```markdown
<docmeta name="displayName" value="Building Custom Homemade Puddings">
```

#### When will my change appear on the Sails website?

Documentation changes go live when they are merged onto a special branch corresponding with the current stable version of Sails (e.g. 0.12). We cannot merge pull requests sent directly to this branch&mdash;its sole purpose is to reflect the content currently hosted on sailsjs.com, and content is only merged just before redeploying the Sails website.

If you want to see how documentation changes will appear on sailsjs.com, you can visit [preview.sailsjs.com](http://preview.sailsjs.com). The preview site updates itself automatically as changes are merged into the master branch of sails.


#### How can I help translate the documentation?

A great way to help the Sails project, especially if you're a native speaker of a language other than English, is to volunteer to translate the Sails documentation.

If you are interested in beginning a translation project, follow these steps:

+ Bring the documentation folder from the [sails repo](https://github.com/balderdashy/sails/tree/master/docs) (`balderdashy/sails/docs`) into a new repo named `sails-docs-{{IETF}}` where {{IETF}} is the [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) for your language.
+ Edit [the documentation README](https://github.com/balderdashy/sails/tree/master/docs) to summarize your progress so far, provide any other information you think would be helpful for others reading your translation, and let interested contributors know how to contact you.
+ When you are satisfied with the first complete version of your translation, open an issue and someone from our docs team will be happy to help you preview it in the context of the Sails website, get it live on a domain (yours, or a subdomain of sailsjs.com, whichever makes the most sense), and share it with the rest of the Sails community.


<docmeta name="displayName" value="Contributing to the docs">

---

### Contributing Contributors Pledge (`docs/contributing/contributors-pledge.md`)

# Contributor's pledge

By making a contribution to this project, I certify that:

* (a) The contribution was created in whole or in part by me and I
  have the right to submit it under the MIT license; or
* (b) The contribution is based upon previous work that, to the best
  of my knowledge, is covered under an appropriate open source license
  and I have the right under that license to submit that work with
  modifications, whether created in whole or in part by me, under the
  same open source license (unless I am permitted to submit under a
  different license), as indicated in the file; or
* (c) The contribution was provided directly to me by some other
  person who certified (a), (b) or (c) and I have not modified it.

> The certificate of origin above is based on the "[Developer's Certificate of Origin 1.0](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#developers-certificate-of-origin-10)" used by Node.js core.

<docmeta name="displayName" value="Contributor's pledge">

---

### Contributing Core Maintainers (`docs/contributing/core-maintainers.md`)

# Core maintainers

The Sails.js core maintainers constitute a small team of individuals located in Austin, TX who are passionate about making it easier for everyone to develop scalable, secure, custom web applications.  We fell in love with Node.js at first sight and are firm believers in the continued, unprecedented dominance of JavaScript as a unifying force for good.  We see Node.js as the logical continuation of the web standards movement into the world of server-side development.

The Sails core team maintains the framework and its related sub-projects, including the Waterline ORM, the Node-Machine project, the Skipper body parser, and all officially-supported generators, adapters, and hooks.  We rely heavily on the help of a network of contributors and users all over the world, but we make all final decisions about our releases and roadmap.


#### History

Sails.js was originally developed by [Mike McNeil](http://twitter.com/mikermcneil) with the help of his company [Balderdash](http://www.bizjournals.com/sanantonio/blog/socialmadness/2013/03/sxsw-2013-Balderdash-startup-web-app.html), a small development and design studio in Austin, TX.  The first stable version of Sails was released as open source in 2012.  Today, it is still actively maintained by the same [core team members](https://sailsjs.com/about), along with the help of many amazing [contributors](https://github.com/balderdashy/sails/network/members).


#### Financial Support

Today, Sails.js is financially supported by [The Sails Company](https://sailsjs.com/about) ([YC W15](http://techcrunch.com/2015/03/11/treeline-wants-to-take-the-coding-out-of-building-a-backend/)).  Please feel free to [contact us directly](https://sailsjs.com/contact) with questions about the company, our [team](https://sailsjs.com/about), or our mission.

<docmeta name="displayName" value="Core maintainers">

---

### Contributing Intro To Custom Adapters (`docs/contributing/intro-to-custom-adapters.md`)

# Introduction to custom adapters for Sails/Waterline

> ##### Stability: Varies

## Reference

Please see the [adapter interface specification](https://github.com/balderdashy/sails/blob/master/docs/contributing/adapter-specification.md).



### What is an adapter?

 Adapters expose **interfaces**, which imply a conract to implemnt certain functionality.  This allows us to guarantee conventional usage patterns across multiple models, developers, apps, and even companies, making app code more maintainable, efficient, and reliable.  Adapters are useful for integrating with databases, open APIs, internal/proprietary web services, or even hardware.


### What kind of things can I do in an adapter?

Adapters are mainly focused on providing model-contextualized CRUD methods.  CRUD stands for create, read, update, and delete.  In Sails/Waterline, we call these methods `create()`, `find()`, `update()`, and `destroy()`.

For example, a `MySQLAdapter` implements a `create()` method which, internally, calls out to a MySQL database using the specified table name and connection information and runs an `INSERT ...` SQL query.

In practice, your adapter can really do anything it likes-- any method you write will be exposed on the raw datastore objects and any models which use them.




## Why would I need a custom adapter?

When building a Sails app, the sending or receiving of any asynchronous communication with another piece of hardware can be normalized into an adapter.  (viz. API integrations)

> **From Wikipedia:**
> *http://en.wikipedia.org/wiki/Create,_read,_update_and_delete*

> Although a relational database provides a common persistence layer in software applications, numerous other persistence layers exist. CRUD functionality can be implemented with an object database, an XML database, flat text files, custom file formats, tape, or card, for example.

In other words, Waterline is not just an ORM for your database.  It is a purpose-agnostic, open standard and toolset for integrating with all kinds of RESTful services, datasources, and devices, whether it's LDAP, Neo4J, or [a lamp](https://www.youtube.com/watch?v=OmcQZD_LIAE).
I know, I know... Not everything fits perfectly into a RESTful/CRUD mold!  Sometimes the service you're integrating with has more of an RPC-style interface, with one-off method names.  That's ok-- you can define any adapter methods you like! You still get all of the trickle-down config and connection-management goodness of Waterline core.



## Why should I build a custom adapter?

To recap, writing your API integrations as adapters is **easier**, takes **less time**, and **absorbs a considerable amount of risk**, since you get the advantage of a **standardized set of conventions**, a **documented API**, and a **built-in community** of other developers who have gone through the same process.  Best of all, you (and your team) can **reuse the adapter** in other projects, **speeding up development** and **saving time and money**.

Finally, if you choose to release your adapter as open-source, you provide a tremendous boon to our little framework and our budding Sails.js ecosystem.  Even if it's not via Sails, I encourage you to give back to the OSS community, even if you've never forked a repo before-- don't be intimidated, it's not that bad!

The more high-quality adapters we collectively release as open-source, the less repetitive work we all have to do when we integrate with various databases and services.  My vision is to make building server-side apps more fun and less repetitive for everyone, and that happens one community adapter at a time.

I tip my hat to you in advance :)




## What is an Adapter Interface?

The functionality of adapters is as varied as the services they connect.  That said, there is a standard library of methods, and a support matrix you should be aware of.  Adapters may implement some, all, or none of the interfaces below, but rest assured that **if an adapter implements one method in an interface, it should implement *all* of them**.  This is not always the case due to limitations and/or incomplete implementations, but at the very least, a descriptive error message should be used to keep developers informed of what's supported and what's not.


##### Class methods
Below, `class methods` refer to the static, or collection-oriented, functions available on the model itself, e.g. `User.create()` or `Menu.update()`.  To add custom class methods to your model (beyond what is provided in the adapters it implements), define them as top-level key/function pairs in the model object.

##### Instance methods
`instance methods` on the other hand, (also known as object, or model, methods) refer to methods available on the individual result models themselves, e.g. `User.findOne(7).done(function (err, user) { user.someInstanceMethod(); });`.  To add custom instance methods to your model (beyond what is provided in the adapters it implements), define them as key/function pairs in the `attributes` object of the model's definition.

##### DDL and auto-migrations
`DDL` stands for data-definition language, and is a common fixture of schema-oriented databases.  In Sails, auto-migrations are supported out of the box.  Since adapters for the most common SQL databases support `alter()`, they also support automatic schema migration!  In your own adapter, if you write the `alter()` method, the same behavior will take effect.  The feature is configurable using the `migrate` property, which can be set to `safe` (don't touch the schema, period), `drop` (recreate the tables every time the app starts), or `alter` (the default-- merge the schema in the apps' models with what is currently in the database).






## Offcially supported adapters

Cody, Mike, and the team behind Sails.js at Balderdash support a handful of commonly used adapters.

### Disk


Write to your computer's hard disk, or a mounted network drive.  Not suitable for at-scale production deployments, but great for a small project, and essential for developing in environments where you may not always have a database set up. This adapter is bundled with Sails and works out of the box with zero configuration.

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Streaming


### Memory

Pretty much like Disk, but doesn't actually write to disk, so it's not persistent.  Not suitable for at-scale production deployments, but useful when developing on systems with little or no disk space.

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Streaming


### MySQL

MySQL is the world's most popular relational database.
http://en.wikipedia.org/wiki/MySQL

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Streaming
+ Migratable


### PostgreSQL

[PostgreSQL](http://en.wikipedia.org/wiki/PostgreSQL) is another popular relational database.

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Streaming
+ Migratable


### MongoDB

[MongoDB](http://en.wikipedia.org/wiki/MongoDB) is the leading NoSQL database.

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Streaming

### Redis

[Redis](http://redis.io/) is an open source, BSD licensed, advanced key-value store.

###### Interfaces implemented:
+ Semantic
+ Queryable



> Under active development:
>
> + sails-s3
> + sails-local-fs






## Notable Community Adapters

> ##### Stability: Varies
> in various states of completion


Community adapters are crucial to the success and central to the philosophy of an open ecosystem for API integrations.  The more high-quality adapters you release as open-source, the less repetitive work we all have to do when we integrate with various databases and services.  My vision is to make building server-side apps more fun and less repetitive for everyone, and that happens one community adapter at a time.  We welcome your support!


### [Mandrill (email-sending service by MailChimp)](https://github.com/mikermcneil/sails-mandrill)
+ One-Way

### Heroku
> Not currently available as open-source.

### Git
> Not currently available.

### [CouchDB](https://github.com/craveprogramminginc/sails-couchdb)
+ Semantic

### [Riak](https://npmjs.org/package/sails-riak)
+ Semantic

### [REST](https://github.com/zohararad/sails-rest)
+ Semantic

### [IRC](https://github.com/balderdashy/sails-irc)
+ Pubsub

### [Twitter](https://github.com/balderdashy/sails-twitter)

### [ElasticSearch](https://github.com/UsabilityDynamics/waterline-elasticsearch)
+ Semantic

### [JSDom](https://github.com/mikermcneil/sails-jsdom)

### [Yelp](https://github.com/balderdashy/sails-adapter-boilerplate/pull/2)

### [OrientDB](https://github.com/appscot/sails-orientdb)

[OrientDB](http://en.wikipedia.org/wiki/OrientDB) is an Open Source NoSQL DBMS with the features of both Document and Graph DBMSs.

###### Interfaces implemented:
+ Semantic
+ Queryable
+ Associations
+ Migratable


> Search google and NPM for more-- there are new adapters being written all the time.



> Check out the docs to learn how to write your own custom adapter (whether it's a private, internal project for a proprietary API or something you can share as open-source)


> Want to see your adapter listed here?  Send a pull request with a link and we'll merge it!
<docmeta name="notShownOnWebsite" value="true">

---

### Contributing Issue Contributions (`docs/contributing/issue-contributions.md`)

# Issue contributions

When opening new issues or commenting on existing issues in any of the repositories in this GitHub organization, please make sure discussions are related to concrete technical issues of the Sails.js software.  Feature requests and ideas are always welcome, but they should not be submitted as GitHub issues.  See [Requesting Features](https://sailsjs.com/documentation/contributing/proposing-features-enhancements) below for submission guidelines.

For general help using Sails, please refer to the [official Sails documentation](https://sailsjs.com/documentation).  For additional help, ask a question on [StackOverflow](http://stackoverflow.com/questions/ask) or refer to any of the [other recommended avenues of support](https://sailsjs.com/support).

If you have found a security vulnerability in Sails or any of its dependencies, _do not report it in a public issue_.  Instead, alert the core maintainers immediately using the instructions detailed in the [Sails Security Policy](https://sailsjs.com/security).  Please observe this request _even for  external dependencies not directly maintained by the core Sails.js team_ (e.g. Socket.io, Express, Node.js, or openssl).  Whether or not you believe the core team can do anything to fix an issue, please follow the instructions in our security policy to privately disclose the vulnerability as quickly as possible.

Finally, discussion of a non-technical nature, including subjects like team membership, trademark, code of conduct, and high-level questions or concerns about the project should be sent directly to the core maintainers by emailing [inquiries@sailsjs.com](inquiries@sailsjs.com).

#### Opening an issue

> Sails is composed of a number of different sub-projects, many of which have their [own dedicated repository](https://sailsjs.com/architecture).  Even so, the best place to submit a suspected issue with a module maintained by the Sails core team is in the main Sails repo.  This helps us stay on top of issues and keep organized.

Before submitting an issue, please follow these simple instructions:

<a name="issue-instructions"></a>

First, search for issues similar to yours in [GitHub search](https://github.com/balderdashy/sails/search?type=Issues) within the main Sails repo.
  - If your original bug report is covered by an existing open issue, then add a comment to that issue instead of opening a new one.
  - If all clearly related issues are closed, then open a new issue and paste links to the URLs of the already closed issue(s) at the bottom.
  - If you cannot find any related issues, try using different search keywords, if appropriate (in case this affects how you search, at the time of this writing, GitHub uses ElasticSearch, which is based on Lucene, to index content).  If you still cannot find any relevant existing issues, then create a new one.
  - Please consider the importance of backlinks.  A contributor responding to your issue will almost always need to search for similar existing issues theirself, so having the URLs all in one place is a huge time-saver.  Also keep in mind that backlinking from new issues causes GitHub to insert a link to the URL of the new issue in referenced original issues automatically.  This is very helpful, since many visitors to our GitHub issues arrive from search engines.

Once you've determined that a new issue should be created,
+ Make sure your new issue does not report multiple unrelated problems.
  - If you are experiencing more than one problem&mdash;and the problems are clearly distinct&mdash;create a separate issue for each one, but start with the most urgent.
  - If you are experiencing multiple related problems (problems that you have only been able to reproduce in tandem), then please create only a single issue. Be sure to describe both problems thoroughly, though, as well as the steps necessary to cause them both to appear.

+ Check that your issue has a concise, on-topic title that uses polite, neutral language to explain the problem as best you can in the available space. The ideal title for your issue is one that communicates the problem at a glance.
  - For example, _"jst.js being removed from layout.ejs on lift"_ is a **very helpful** title for an issue.
  - Here are some **non-examples**&mdash;that is, examples of issue titles which are **not helpful**:
    - _"templates dont work"_ : This title is too vague. Even if more information cannot be gleaned, wording like _"unexpected behavior with templates"_ is a little more specific and would likely generate a quicker response.
    - _"app broken cannot access templates on filesystem because it is broken in the asset pipeline please help"_ : This title is repetative and contains unnecessary content ("_please help_"). Remember that a useful title is both desciptive and concise.
    - _"jst.js is being REMOVED!!!!!!!!!"_: This title contains unnecessary capitalization and punctuation, which is distracting at best, and may be perceived as impolite. In either case, it's unlikely to speed the response to your issue.
    - _"How does this dumb, useless framework remove jst.js from my app?"_: This title contains unnecessary negativity, which doesn't encourage participant review. Try keeping titles as objective as possible for the best possible issue resolution experience.
    - _"Thousands of files being corrupted in our currently deployed production app every time the server crashes."_: Language like this might be perceived as hyperbolic and could lessen the credibility of your claim. In this instance, it may even confuse the issue (e.g. "Is this only happening when NODE_ENV===production?").

+ Before putting together steps to reproduce your issue, normalize as many of the variables on your personal development environment as possible:
  - Make sure you have the right app lifted.
  - Make sure you've killed the Sails server with CTRL+C and started it again.
  - Make sure you do not have any open browser tabs pointed at localhost.
  - Make sure you do not have any other Sails apps running in other terminal windows.
  - Make sure the app you are using to reproduce the issue has a clean `node_modules/` directory, meaning:
    - no dependencies are linked (e.g. you haven't run `npm link foo`)
    - you haven't made any inline changes to files in the `node_modules/` folder
    - you don't have any weird global dependency loops
    The easiest way to double-check any of the above, if you aren't sure, is to run: `rm -rf node_modules && npm cache clear && npm install`.

+ Remember to provide the version of Sails that your app is using (`sails -v`).
  - Note that this could be different than the version of Sails you have globally installed.

+ Provide your currently-installed version of Node.js (`node -v`), your version of NPM (`npm -v`), and the operating system that you are running (OS X, Windows, Ubuntu, etc.)
  - If you are using `nvm` or another Node version manager like `n`, please be sure to mention that in the issue.

+ Provide detailed steps to reproduce the problem from a clean Sails app (i.e. an app created with `sails new` on a computer with no special environment variables or `.sailsrc` files)

+ Finally, take a moment to think about what you are about to post and how it will be interpreted by the rest of the Sails userbase.  Make sure it is aligned with our Code of Conduct, and make sure you are not endangering other Sails users by posting a [security vulnerability](https://sailsjs.com/security) publicly.

Issues which do not meet these guidelines will usually be closed without being read, with a response asking that the submitter review this contribution guide.  If this happens to you, _realize that it's nothing personal_, and that it may even happen again.  Please understand that Sails is a large project that receives hundreds of new issue submissions every month, and that we truly appreciate the time you donate to post detailed issues.  The more familiar you become with the conventions and ground rules laid out in this contribution guide, the more helpful your future contributions will be for the community.  You will also earn the respect of core team members and set a good example for future contributors.

> You might think of these rules as guardrails on a beautiful mountain road: they may not always be pretty, and if you run into them you may get banged up a little bit, but, collectively, they keep us all from sliding off a turn and into the abyss.

<docmeta name="displayName" value="Issue contributions">

---

### Contributing Preface (`docs/contributing/preface.md`)

# Contributing to Sails

This guide is designed to help you get off the ground quickly contributing to Sails.  Reading it thoroughly will help you write useful issues, make eloquent proposals, and submit top-notch code that can be merged quickly.  Respecting the guidelines laid out here helps make the core maintainers of Sails more productive, and makes the experience of working with Sails positive and enjoyable for the community at large.

If you are working on a pull request, **please carefully read the this guide in its entirety**. In case of doubt, [open an issue on GitHub](https://github.com/balderdashy/sails/issues/new) or contact someone from our [core team](https://sailsjs.com/about) on Twitter. Especially do so if you plan to work on something big. Nothing is more frustrating than seeing your hard work go to waste because your vision does not align with planned or ongoing development efforts of the project's maintainers.

> Note that unless otherwise specified, the content in this section is either straight from the hearts of the Sails.js core team, or based on the [Node.js contribution guide](https://github.com/joyent/node/blob/master/CONTRIBUTING.md#contributing).

<docmeta name="displayName" value="Contributing to Sails">
<docmeta name="isOverviewPage" value="true">

---

### Faq Faq (`docs/faq/faq.md`)

# Frequently Asked Questions

### Table of Contents
1. [I'm having trouble installing Sails. What should I do?](https://sailsjs.com/faq#?im-having-trouble-installing-sails-what-should-i-do)
2. [What are the dependencies of Sails?](https://sailsjs.com/faq#?what-are-the-dependencies-of-sails)
3. [Who else is using Sails.js?](https://sailsjs.com/faq#?who-else-is-using-sailsjs)
4. [Are there professional support options?](https://sailsjs.com/faq#?are-there-professional-support-options)
5. [Where do I get help?](https://sailsjs.com/faq#?where-do-i-get-help)
6. [What are some good community tutorials?](https://sailsjs.com/faq#?what-are-some-good-community-tutorials)
7. [How can I convince the other girls/guys on my team?](https://sailsjs.com/faq#?how-can-i-convince-the-other-girls-guys-on-my-team)
8. [Where do I submit ideas?  Report bugs?](https://sailsjs.com/faq#?where-do-i-submit-ideas-report-bugs)
9. [What version of Sails should I use?](https://sailsjs.com/faq#?what-version-of-sails-should-i-use)
10. [How do I get involved?](https://sailsjs.com/faq#?how-do-i-get-involved)
11. [How does the documentation end up on the Sails website?](https://sailsjs.com/faq#?how-does-the-documentation-end-up-on-the-sails-website)
12. [Where is the documentation for the different releases of Sails?](https://sailsjs.com/faq#?where-is-the-documentation-for-the-different-releases-of-sails)

### I'm having trouble installing Sails. What should I do?

Start with NPM's helpful [troubleshooting guide](https://github.com/npm/npm/wiki/Troubleshooting).  If you continue to have problems, and you've tried Google searching but you're still stumped, please carefully review the updated Sails [contribution guide](https://sailsjs.com/documentation/contributing) and then create a GitHub issue in the Sails repo.


### What are the dependencies of Sails?

[](https://david-dm.org/balderdashy/sails)

We have learned again and again over the years to take versioning of dependencies very seriously.  We lock Sails's dependency versions and only bump those versions if the associated updates fix a security issue or present other substantive advantages to Sails users (improved compatibility, performance, etc.)  In addition, the core maintainers of Sails are committed to fixing any major security, performance, or stability bugs that arise in any of our core dependencies-- regardless of whether those modules are [officially maintained by another entity or not](https://github.com/balderdashy/sails/pull/3235#issuecomment-170417122).

Sails is tested with [node](http://nodejs.org/) versions 0.10.x and up, though, we recommend using The latest LTS version of Node.  The framework is built on the rock-solid foundations of [Express](https://github.com/expressjs/) and [Socket.io](http://socket.io/).  Out of the box, it also depends on other great modules, like `grunt`, `waterline`, and `fs-extra`.  Click the badge above for the full list of dependencies in the latest stable release of Sails core.

> **Sails Flagship users:** We manually verify every dependency of Sails and other officially-maintained modules by hand, every single week.  This includes core hooks, adapters, generators, client SDKs, and Flagship packages.   We regularly send security/compatibility reports about dependencies to the primary email address associated with your account.  If you'd like additional people on your team to receive these reports, no problem!  Just [let us know](https://flagship.sailsjs.com/ask) their email addresses and we'll get them set up.  _(These email addresses will also receive communications about patches, shrinkwrap updates, and compatibility notices.)_

If you have questions or concerns about our dependencies, [talk to a core team member](https://sailsjs.com/contact).  _Please do not submit a pull request changing the version of a dependency without first (1) checking that dependency's changelog, (2) verifying compatibility, and (3) [submitting an accompanying PR to update **roadstead**](https://github.com/treelinehq/roadstead/edit/master/constants/verified-releases.type.js), our dependency wallah._


### Who else is using Sails.js?

Sails is used in production by individuals and companies, non-profits, and government entities all over the world, for all sorts of projects (greenfield and mature).  You can see some examples [here](https://sailsjs.com/#?using-sails) of companies that have used Sails for their projects. (This small list is definitely not authoritative, so if you're using Sails in your app/product/service, [we'd love to hear about it](https://sailsjs.com/contact)!

### Are there professional support options?

[The Sails Company](https://sailsjs.com/about) offers custom development, services, training, enterprise-class products, and support for teams building applications on Sails.

##### Partner with us
Our studio provides development services for startups, SMBs, and the Fortune 500. As you might expect, the Sails core team has done a lot of custom Sails/Node.js development, but we also have experience across the full stack, including: advanced interaction design, practical/scalable JavaScript development practices for huge applications, and building rich user experiences across many different devices and screen resolutions.

We can build your app and API from scratch, modernize your legacy web platform, or catalyze the development efforts of your established team.  If you're interested in working with us on your next project, [drop us a line](https://sailsjs.com/studio#?contact).

##### Sails Flagship for Enterprise
Sails Flagship is a platform on top of Sails which provides a suite of additional services, production-quality accoutrements, and support for enterprise use cases.  This includes early access to new features and enhancements, a license for our internal tools, as well as exclusive reports and best-practice guides created by core maintainers.  To learn more, [set up a call](https://sailsjs.com/contact) _(or [purchase online now](https://sailsjs.com/flagship/plans))_.

> We are actively expanding this product offering with new additions and official re-releases of some formerly-experimental modules.  If you have specific suggestions/requests for new Flagship packages, please [let us know](http://flagship.sailsjs.com/contact).

##### Professional support / SLAs
The Sails Company also provides a lifeline for organizations using Sails to build their products. If you need guaranteed support in the event of a critical production issue, or just want an extra pair of eyes looking out for your code base during development, take a look at our [basic subscriptions](https://sailsjs.com/flagship/plans), or [contact us](https://flagship.sailsjs.com/contact) and we'll give you a call.



### Where do I get help?

Aside from the [official documentation](https://sailsjs.com/documentation), be sure and check out the [recommended support options on the Sails website](https://sailsjs.com/support), and pop in to our [Gitter chat room](https://gitter.im/balderdashy/sails).  If you're stumped, make sure and [ask a question on StackOverflow](http://stackoverflow.com/questions/ask), where there's an [active Sails community](http://stackoverflow.com/questions/tagged/sailsjs?sort=newest&days=30).  Members of our core team recently taught a [free video course](https://courses.platzi.com/courses/develop-apps-sails-js/) on [Platzi](http://platzi.com) and wrote [a book](https://www.manning.com/books/sails-js-in-action).

> If you're using [Sails Flagship](https://sailsjs.com/faq#?are-there-professional-support-options), you can contact the core team [here](http://flagship.sailsjs.com/ask).



### What are some good community tutorials?

> If you are the author of a tutorial or guide about Sails, please send us a pull request [here](https://github.com/balderdashy/sails/edit/master/docs/faq/faq.md) and we'll check it out. (Be sure to add your tutorial to the top of the applicable list, as we try to order these from newest to oldest.)



##### Multi-part guides:
+ [The busy JavaScript developer's guide to Sails.js](https://www.ibm.com/developerworks/library/wa-build-deploy-web-app-sailsjs-1-bluemix/index.html) -- 4-part series from IBM developerWorks. (Also available in [Chinese](http://www.ibm.com/developerworks/cn/web/wa-build-deploy-web-app-sailsjs-1-bluemix/) and [Japanese](http://www.ibm.com/developerworks/jp/web/library/wa-build-deploy-web-app-sailsjs-1-bluemix/).)

+ [SailsCasts](http://irlnathan.github.io/sailscasts/) - Short screencasts that take you through the basics of building traditional websites, single-page/mobile apps, and APIs using Sails.  Perfect for both novice and tenured developers, but does assume some background on MVC.

+ [Sails.js Development channel on Medium](https://medium.com/sails-js-development/)

+ [Sails.js Course on Pluralsight](https://www.pluralsight.com/courses/two-tier-enterprise-app-api-development-angular-sails)

+ Sails API Development
  + [Datalayer -models, connections, waterline](http://www.codeproject.com/Articles/898221/Sails-API-development-Datalayer-models-connections)
  + [Custom methods, overriding default actions, and related](http://www.codeproject.com/Articles/985730/Sails-API-development-2-2-Custom-methods-overriding-default)

+ Desarrollar Webapps Realtime:
  + [Creación](http://jorgecasar.github.io/blog/desarrollar-webapps-realtime-creacion/)
  + [Usuarios](http://jorgecasar.github.io/blog/desarrollar-webapps-realtime-usuarios/)
  + [Auth](http://jorgecasar.github.io/blog/desarrollar-webapps-realtime-auth/)
  + [Auth con Passport](http://jorgecasar.github.io/blog/desarrollar-webapps-realtime-auth-con-passport/)



##### Articles & blog posts:
+ [Nanobox Blog: Getting Started - A Simple Sails.js App](https://content.nanobox.io/a-simple-sails-js-example-app/)

+ [Twitter Dev Blog: Guest Post: Twitter Sign-In with Sails.js](https://blog.twitter.com/2015/guest-post-twitter-sign-in-with-treelineio)

+ [Guest Post on Segment.io Blog: Webhooks with Slack, Segment, and Sails.js/Treeline](https://segment.com/blog/segment-webhooks-slack/)

+ [Postman Blog: Manage your Sails.js server bootstrap code](http://blog.getpostman.com/2015/08/28/manage-your-sailsjs-server-bootstrap-code/)

+ [Sails.js on Heroku](https://vort3x.me/sailsjs-heroku/)

+ [Angular + Sails.js (0.10.0-rc5) with angular-sails socket.io](https://github.com/maartendb/angular-sails-scrum-tutorial/blob/master/README.md)

+ [Angular + Sails!  Help!](https://github.com/xdissent/spinnaker) - Sails Resources Service for AngularJS

+ [How to Create a Node.js App using Sails.js on an Ubuntu VPS](https://www.digitalocean.com/community/articles/how-to-create-an-node-js-app-using-sails-js-on-an-ubuntu-vps)

+ [Working With Data in Sails.js](http://net.tutsplus.com/tutorials/javascript-ajax/working-with-data-in-sails-js/) tutorial on NetTuts


##### Video tutorials:
+ [Develop Web Apps in Node.js and Sails.js](https://courses.platzi.com/courses/sails-js/)
+ [Jorge Casar: Introduccion a Sails.js](https://www.youtube.com/watch?v=7_zUNTtXtcg)

+ [Sails.js - How to render node views via Ajax, single page application, SPA](http://www.youtube.com/watch?v=Di50_eHqI7I&feature=youtu.be)

+ [Intro to Sails.js](https://www.youtube.com/watch?v=GK-tFvpIR7c) [@mikermcneil](https://github.com/mikermcneil)'s original screencast



### How can I convince the other girls/guys on my team?

##### Articles / interviews / press releases / whitepapers / talks

> + If you are the author of an article about Sails, please send us a pull request [here](https://github.com/balderdashy/sails/edit/master/docs/faq/faq.md).  We'll check it out!
> + If you are a company interested in doing a press release about Sails, please contact [@mikermcneil](https://twitter.com/mikermcneil) on Twitter.  We'll do what we can to help.

+ [InfoWorld: Why Node.js beats Java and .Net for web, mobile, and IoT apps](http://www.infoworld.com/article/2975233/javascript/why-node-js-beats-java-net-for-web-mobile-iot-apps.html) _(Speed, scalability, productivity, and developer politics all played a role in [AnyPresence](http://anypresence.com)’s selection of Sails.js/Node.js for its enterprise development platform)_
+ [TechRepublic: Build Robust Applications with the Node.js MVC framework](http://www.techrepublic.com/article/build-robust-node-applications-with-the-sails-js-mvc-framework/)
+ [Microsoft Case Study: Deploying Sails.js to Azure Web Apps](https://blogs.msdn.microsoft.com/partnercatalystteam/2015/07/16/y-combinator-collaboration-deploying-sailsjs-to-azure-web-apps/)
+ [Mike's interview w/ @freddier and @cvander from Platzi](https://www.youtube.com/watch?v=WN0YgPdPbRE)
+ [Smashing Magazine: Sailing with Sails.js](https://www.smashingmagazine.com/2015/11/sailing-sails-js-mvc-style-framework-node-js/)
+ [Presentation at Smart City Conference & Expo 2015](http://www.goodxense.com/blog/post/our-presentation-at-smart-city-conference-expo-2015/) (George Lu & YJ Yang)
+ [Radio interview with Mike McNeil w/ ComputerAmerica's Craig Crossman](https://www.youtube.com/watch?v=ERIvf2iUj5U&feature=youtu.be)
+ Sails.js, Treeline and the future of programming  ([Article](https://courses.platzi.com/blog/sails-js-creator-mike-mcneil-on-treeline-and-frameworks/) | [Video](https://www.youtube.com/watch?v=nZKG7hLhbRs) | [Deck](https://speakerdeck.com/mikermcneil/what-even-is-software))
+ [UI-First API Design & Development: Apigee's I &hearts; APIs, San Francisco, 2015](https://speakerdeck.com/mikermcneil/i-love-apis)
+ [Choosing the right framework for Node.js development](https://jaxenter.com/choosing-the-right-framework-for-node-js-development-126432.html)
+ [TechCrunch: Our 10 Favorite Companies From Y Combinator Demo Day](https://techcrunch.com/gallery/our-10-favorite-companies-from-y-combinator-demo-day-day-1/slide/11/)
+ [Sails.js used on the website for the city of Paris](https://twitter.com/parisnumerique/status/617999231182176256)
+ [18f Open Source Hack Series: Midas](https://18f.gsa.gov/2014/10/01/open-source-hack-series-midas/)
+ [From Rags to Open Source](https://speakerdeck.com/mikermcneil/all-things-open) (All Things Open, Raleigh, 2014)
+ SxSW Conference, Austin, TX: ([2014](https://speakerdeck.com/mikermcneil/2014-intro-to-sails-v0-dot-10-dot-x) | [2015](https://speakerdeck.com/mikermcneil/sxsw-2015))
+ [More talks by Mike and the Sails.js core team](http://lanyrd.com/profile/mikermcneil/)
+ [Dessarolo Web: Interview w/ Mike McNeil](https://www.youtube.com/watch?v=XMpf44oV2Og) (Spanish & English--English starts at 1:30)
+ [CapitalOne blog: Contrasting Enterprise Node.js Frameworks](http://www.capitalone.io/blog/contrasting-enterprise-nodejs-frameworks/) (by [Azat Mardan](https://www.linkedin.com/in/azatm), author of the book "Pro Express.js")
+ [Alternatives to MongoDB (Chinese article)](http://www.infoq.com/cn/news/2015/07/never-ever-mongodb)
+ [Introducción a Sails.js, un framework para crear aplicaciones realtime](https://abalozz.es/introduccion-a-sails-js-un-framework-para-crear-aplicaciones-realtime/)
+ [Austin startup finds success in responsive design](http://www.bizjournals.com/sanantonio/blog/socialmadness/2013/03/sxsw-2013-Balderdash-startup-web-app.html?ana=twt)
+ [Interact ATX](http://www.siliconhillsnews.com/2013/03/10/flying-high-with-interact-atx-adventures-in-austin-part-3-2-1/)
+ [Intro to Sails.js :: Node.js Conf: Italy, 2014](http://2014.nodejsconf.it/)
+ [Startup America](http://www.prlog.org/12038372-engine-pitches-startup-america-board-of-directors.html)
+ [Recent tweets about Sails.js](https://twitter.com/search?q=treelinehq%20OR%20%40treelinehq%20OR%20%23treelinehq%20OR%20%40waterlineorm%20OR%20treeline.io%20OR%20sailsjs.com%20OR%20github.com%2Fbalderdashy%2Fsails%20OR%20sailsjs%20OR%20sails.js%20OR%20%23sailsjs%20OR%20%40sailsjs&src=typd)
+ [How to use more open source](https://18f.gsa.gov/2014/11/26/how-to-use-more-open-source/) _(18F is an office inside the U.s. General Services Administration that helps other federal agencies build, buy, and share efficient and easy-to-use digital services.)_
+ [Express Web Server Advances in Node.js Ecosystem](https://adtmag.com/articles/2016/02/11/express-joins-node.aspx) ([auch auf Deutsch](http://www.heise.de/developer/meldung/IBM-uebergibt-JavaScript-Webframework-Express-an-Node-js-Foundation-3099223.html))
+ Interview w/ Tim Heckel [on InfoQ](http://www.infoq.com/news/2013/04/Sails-0.8.9-Released)
+ [Sails.js - Une Architecture MVC pour applications real-time Node.js](http://www.lafermeduweb.net/billet/sails-js-une-architecture-mvc-pour-applications-real-time-node-js-1528.html)
+ [Hacker News](https://news.ycombinator.com/item?id=5373342)
+ [Pulling the Plug: dotJS (Paris, 2014)](http://www.thedotpost.com/2014/11/mike-mcneil-pulling-the-plug)
+ [Intro to Sails.js :: Node PDX, Portland, 2013 (Slides)](http://www.slideshare.net/michaelrmcneil/node-pdx))
+ [Sail.js : un framework MVC pour Node.js](http://javascript.developpez.com/actu/52729/Sail-js-un-framework-MVC-pour-Node-js/)
+ [Build Custom & Enterprise Node.js Apps with Sails.js](http://www.webappers.com/2013/03/29/build-custom-enterprise-node-js-apps-with-sails-js/)
+ [New tools for web design and development: March 2013](http://www.creativebloq.com/design-tools/new-tools-web-design-and-development-march-2013-4132972)
+ [Sails 0.8.9: A Rails-Inspired Real-Time Node MVC Framework](http://www.infoq.com/news/2013/04/Sails-0.8.9-Released)
+ [Node.js の MVCフレームワーク Sails.js が良さげなので少し試してみた](http://nantokaworks.com/?p=1101)
+ [InfoWorld: 13 fabulous frameworks for Node.js](http://www.infoworld.com/article/3064653/application-development/13-fabulous-frameworks-for-nodejs.html#slide9)
+ [New web design tools that you need to check out](http://www.designyourway.net/blog/resources/new-web-design-tools-that-you-need-to-check-out/)
+ [Live code Sails.js avec Mike McNeil](http://www.weezevent.com/live-code-sailsjs-avec-mike-mcneil)
+ [#hack4good adds cities and welcomes Sails.js creator to speak and hack in Paris!](http://us2.campaign-archive1.com/?u=cf9af451f2674767755b02b35&id=fb98713f48&e=b2d87b15fe)
+ [TechCrunch: Sails.js Funded by Y-Combinator](http://techcrunch.com/2015/03/11/treeline-wants-to-take-the-coding-out-of-building-a-backend/)


### Where do I submit ideas?  Report bugs?

The Sails project tracks bug reports in GitHub issues and uses pull requests for feature proposals.  Please read the [contribution guide](https://sailsjs.com/documentation/contributing) before you create an issue, submit a proposal, or begin working on pull request.


### What version of Sails should I use?

[](http://badge.fury.io/js/sails)

Unless you are a contributor running a pre-release version of the framework in order to do some testing or work on core, you should use the latest stable version of Sails from NPM (click the badge above).  Installing is easy- just follow [these instructions](https://sailsjs.com/get-started).

> Note: to install/upgrade to the latest version of Sails locally in an existing project, run `npm install sails@latest --save`.  If you are having trouble and are looking for a bazooka, you might also want to run `rm -rf node_modules && npm cache clear && npm install sails@latest --force --save && npm install`.

If you are looking to install a pre-release version of Sails, you can install from the `beta` tag on npm (i.e. `npm install sails@beta`). This is a great way to try out a coming release ahead of time and start upgrading before the release becomes official.  The beta npm release candidate corresponds with the `beta` branch in the Sails repo.  (Just be sure to also use the right version of your favorite adapters and other plugins.  If in doubt, [feel free to ask](https://sailsjs.com/support).)

Finally, if you like living on the edge, or you're working on adding a feature or fixing a bug in Sails, install the edge version from the `master` branch on github.  The edge version is not published on the registry since it's constantly under development, but you can _still use npm to install it_ (e.g. `npm install sails@git://github.com/balderdashy/sails.git`)

For more instructions on installing the beta and edge versions of Sails, check out the [contribution guide](https://sailsjs.com/documentation/contributing).


### How do I get involved?

There are many different ways to contribute to Sails; for example you could help us improve the [official documentation](https://github.com/balderdashy/sails/tree/master/docs), write a [plugin](https://sailsjs.com/documentation/concepts/extending-sails), answer [StackOverflow questions](http://stackoverflow.com/questions/tagged/sails.js), start a Sails meetup, help troubleshoot GitHub issues, write some tests, or submit a patch to Sails core or one of its dependencies.  Please look through the [contribution guide](https://sailsjs.com/documentation/contributing) before you get started. It's a short read that covers guidelines and best practices that ensure your hard work will have the maximum impact.

### How does the documentation end up on the Sails website?

The documentation is compiled from the markdown files in the [`sails` repo on github](https://github.com/balderdashy/sails/tree/master/docs). A number of Sails users have expressed interest in emulating the process we use to generate the pages on the Sails website.  Good news is it's pretty simple:  The compilation process for the Sails docs involves generating HTML from Markdown files in the sails repo, then performing some additional transformations such as adding data type bubbles, tagging permalinks for individual sections of pages, building JSON data to power the side navigation menu and setting HTML `<title>` attributes for better search engine discoverability of individual doc pages.  See the [doc-templater](https://github.com/uncletammy/doc-templater) module for more information.


### Where is the documentation for the different releases of Sails?
The [documentation on the main website](https://sailsjs.com/documentation) is for the latest stable npm release of Sails, and is mirrored by the docs in the [master branch of the `sails` repo on github](https://github.com/balderdashy/sails/tree/master/docs) (Master is sometimes a few commits ahead, but any critical documentation updates make it onto the website within a day or two.)

For older releases of Sails that are still widely used, the documentation is compiled from the relevant `sails-docs` branches and hosted on the following subdomains:
+ [0.12.sailsjs.com](http://0.12.sailsjs.com/)
+ [0.11.sailsjs.com](http://0.11.sailsjs.com/)

---

### Irc Irc (`docs/irc/irc.md`)

## Grab An IRC Client
Below you'll find some of the more popular IRC Clients.

### Linux
 - [xChat](http://xchat.org)
 - [irssi](http://irssi.org)
 - [weeChat](http://www.weechat.org)

#### Using apt package manager for Ubuntu/Debian
```
sudo apt-get install weechat

```

### OSX
- [irssi](http://irssi.org)

```
sudo steveJobsPM --prettyPlease install -m 'is this okay?' irssi

```
### Windows
 - [xChat](http://xchat.org)
 - [hydra IRC](http://www.hydrairc.com/content/downloads)
 

## Setting Up Your Client
### Registering On Freenode
Our chat room is on the Freenode network.  Freenode does not require that you register your `nick` name.  You do have the option to though.  If you want to do this, read about how to do it [on the freenode website](https://freenode.net/faq.shtml#registering)

### Getting on Freenode

Each IRC Client is a little different to configure.  All of the ones we have recommended have very straight forward configuration process.  If your client provides a list of available servers, look for the one called Freenode.

Make sure to put in a `nick` to go by.

Upon connecting to the Freenode network, join us by typing `/join #sailsjs`.

If you registered a nick, you can identify yourself with `/msg nickserv identify <password>`


## Getting help on IRC

### `#sailsjs` on irc.freenode.net
If you are looking for a quick answer and you can't find what you're looking for in the docs, come ask in our IRC chat room.  While there is typically somebody there who can answer your question, please remember that #sailsjs is 100% community maintained. That means that help is given at the discretion of the community.  For best results, be polite and to the point.

If you've never been on IRC, now is the perfect time.  Getting started is easy.


## Sails Troll
Sails Troll is our resident IRC Bot.  His job is to write down what people say in case someone wants to find it later.

He also informs the room whenever someone pushes up a change to any of the repos in the Sails.js ecosystem.


<docmeta name="displayName" value="#sailsjs on IRC">

---

### Reference Reference (`docs/reference/reference.md`)

# Sails.js Documentation > API Reference

> The contents of this file are overridden automatically during compilation (please do not edit manually!)

<docmeta name="displayName" value="API Reference: Table of Contents">
<docmeta name="isTableOfContents" value="true">

---

### Security SAILS SECURITY POLICY (`docs/security/SAILS-SECURITY-POLICY.md`)

# Security policy

Sails is committed to providing a secure framework, and quickly responding to any suspected security vulnerabilities.  Contributors work carefully to ensure best practices, but we also rely heavily on the community when it comes to discovering, reporting, and remediating security issues.

### Reporting a security issue in Sails

If you believe you've found a security vulnerability in Sails, Waterline, or one of the other modules maintained by the Sails core team, please send an email to **critical at sailsjs dot com**.  In the spirit of [responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure), we ask that you privately report any security vulnerability at that email address, and give us time to patch the issue before publishing the details</em>.

### What is a security vulnerability?

A security vulnerability is any major bug or unintended consequence that could compromise a Sails.js app in production.

For example, an issue where Sails crashes in a development environment when using non-standard Grunt tasks is _not a security vulnerability_.  On the other hand, if it was possible to perform a trivial DoS attack on a Sails cluster running in a production environment and using documented best-practices (a la the [Express/Connect body parser issue](http://expressjs-book.com/index.html%3Fp=140.html)), that _is a security vulnerability_ and we want to know about it.

> Note that this definition includes any such vulnerability that exists due to one of our dependencies.  In this case, an upgrade to a different version of the dependency is not always necessary: for example, when Express 3 deprecated multipart upload support in core, Sails.js dealt with the feature mismatch by implementing a wrapper around the `multiparty` module called [Skipper](https://github.com/balderdashy/skipper#history).

### What should be included in the email?

- The name and NPM version string of the module where you found the security vulnerability (e.g. Sails, Waterline, other core module).
- A summary of the vulnerability
- The code you used when you discovered the vulnerability or a code example of the vulnerability (whichever is shorter).
- Whether you want us to make your involvement public.  If you want such a reference the name and link you wish to be referred (e.g. Jane Doe's link to her GitHub account)

> Please respect the core team's privacy and do not send bugs resulting from undocumented usage, questions, or feature requests to this email address.

### The process
When you report a vulnerability, one of the project members will respond to you within a maximum of 72 hours.  This response will most likely be an acknowledgement that we've received the report and will be investigating it immediately.  Our target patching timeframe for most security vulnerabilities is 14 days.

Based upon the nature of the vulnerability, and the amount of time it would take to fix, we'll either send out a patch that disables the broken feature, provide an estimate of the time it will take to fix, and/or document best practices to follow to avoid production issues.

You can expect follow-up emails outlining the progression of a solution to the vulnerability along with any other questions we may have regarding your experience.

##### When a solution is achieved we do the following:

- notify you
- release a patch on NPM
- coordinate with [Node Security](http://nodesecurity.io) to issue an [advisory](https://nodesecurity.io/advisories?search=sails), crediting you (unless you expressly asked not to be identified)
- publicize the release via our [newsgroup](https://groups.google.com/forum/#!forum/sailsjs)

### Is this an SLA?

No. The Sails framework is available under the [MIT license](https://sailsjs.com/license), which does not include a service level agreement.  However, the core team and contributors care deeply about Sails, and all of us have websites and APIs running on Sails in production.  We will _always_ publish a fix for any serious security vulnerability as soon as possible-- not just out of the kindness of our hearts, but because it could affect our apps (and our customer's apps) too.

> For more support options, see https://sailsjs.com/support.

---

### Tutorials CoffeeScript (`docs/tutorials/coffeeScript.md`)

# Using CoffeeScript in a Sails app

**The recommended language for building Node.js+Sails apps is JavaScript.**

But Sails also supports using CoffeeScript to write your custom app code (like [actions](http://www.sailsjs.com/documentation/concepts/actions-and-controllers) and [models](http://www.sailsjs.com/documentation/concepts/core-concepts-table-of-contents/models-and-orm)).  You can enable this support in three steps:

1. Run `npm install coffee-script --save` in your app folder.
2. Add the following line at the top of your app's `app.js` file:
```javascript
require('coffee-script/register');
```
3. Start your app with `node app.js` instead of `sails lift`.

### Using CoffeeScript generators

If you want to use CoffeeScript to write your controllers, models or config files, just follow these steps:
 1. Install the generators for CoffeeScript (optional): <br/>`npm install --save-dev sails-generate-controller-coffee sails-generate-model-coffee`
 2. To generate scaffold code, add `--coffee` when using one of the supported generators from the command-line:
```bash
sails generate api <foo> --coffee
# Generate api/models/Foo.coffee and api/controllers/FooController.coffee
sails generate model <foo> --coffee
# Generate api/models/Foo.coffee
sails generate controller <foo> --coffee
# Generate api/controllers/FooController.coffee
```

<docmeta name="displayName" value="Using CoffeeScript">

---

### Tutorials Full Stack Javascript (`docs/tutorials/full-stack-javascript.md`)

# Full-stack JavaScript with Sails

This video tutorial is an in-depth guide to building your first Node.js/Sails.js app, taught by [the creator of the framework](https://twitter.com/mikermcneil), and following the best practices and conventions our team uses for all our projects. We walk you through setting up your development environment and building our demo app, [Ration](https://ration.io).


#### Links
+ [Take the course](https://platzi.com/cursos/sails-js/)
+ [Try out the demo app (Ration)](https://ration.io)
+ [Download the source code](https://github.com/mikermcneil/ration) for the demo app

<docmeta name="displayName" value="Full-stack JavaScript with Sails">

---

### Tutorials Low Level Mysql Access (`docs/tutorials/low-level-mysql-access.md`)

# Low-level MySQL usage (advanced)

This tutorial steps through how to access the raw MySQL connection instance from the [`mysql` package](https://www.npmjs.com/package/mysql).  This is useful for getting access to low level APIs available only in the raw client itself. 

> Note: Many Node.js / Sails apps using MySQL will never need the kind of low-level usage described here.  If you find yourself running up against the limitations of the ORM, there is usually a workaround that does not involve writing code for the underlying database.  Even then, if you're just looking to use custom native SQL queries, read no further-- instead, check out [`sendNativeQuery()`](/documentation/reference/waterline-orm/datastores/send-native-query) instead.
>
> Also, before we proceed, make sure you have a datastore configured to use a functional MySQL database.

### Get access to an active MySQL connection

To obtain an active connection from the MySQL package you can call the [`.leaseConnection()`](/documentation/reference/waterline-orm/datastores/lease-connection) method of a registered datastore object (RDI).

1. Get the registered datastore instance for the connection:

```javascript
// Get the named datastore
var rdi = sails.getDatastore('default');

// Get the datastore configured for a specific model
var rdi = Product.getDatastore();
```

2. Call the `leaseConnection()` method to obtain an active connection:

```javascript
rdi.leaseConnection(function(connection, proceed) {
  db.query('SELECT * from `user`;', function(err, results, fields) {
    if (err) {
      return proceed(err);
    }

    proceed(undefined, results);
  });
}, function(err, results) {
  // Handle results here after the connection has been closed
})
```

### Get access to the low-level driver

To get access to the low-level driver and MySQL package in a Sails app, you can grab them from the registered datastore object (RDI).

1. Get the registered datastore instance for the connection:

```javascript
// Get the named datastore
var rdi = sails.getDatastore('default');

// Get the datastore configured for a specific model
var rdi = Product.getDatastore();
```

2. Get the driver from the datastore instance which contains the MySQL module:

```javascript
var mysql = rdi.driver.mysql;
```

3. You can now use the module to make native requests and call other function native to the MySQL module:

```javascript
// Get the named datastore
var rdi = sails.getDatastore('default');

// Grab the MySQL module from the datastore instance
var mysql = rdi.driver.mysql;

// Create a new connection
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : 'password',
  database: 'example_database'
});

// Make a query and pipe the results
connection.query('SELECT * FROM posts')
  .stream({highWaterMark: 5})
  .pipe(...);
```

<docmeta name="displayName" value="Low-level MySQL usage (advanced)">

---

### Tutorials Mongo (`docs/tutorials/mongo.md`)

# Using MongoDB with Node.js/Sails.js

Sails supports the popular [MongoDB database](https://www.mongodb.com/) via the [sails-mongo adapter](https://www.npmjs.com/package/sails-mongo).

> First, make sure you have access to a running MongoDB server, either on your development machine or in the cloud.  Below, 'mongodb://root@localhost/foo' refers to a locally-installed MongoDB using "foo" as the database name.  Be sure to replace that [connection URL](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores#?the-connection-url) with the appropriate string for your database.

### Developing locally with MongoDB

To use MongoDB in your Node.js/Sails app during development:

1. Run `npm install sails-mongo` in your app folder.
2. In your `config/datastores.js` file, edit the `default` datastore configuration:

    ```js
    default: {
      adapter: 'sails-mongo',
      url: 'mongodb://root@localhost/foo'
    }
    ```
3. In your `config/models.js` file, edit the default `id` attribute to have the appropriate `type` and `columnName` for MongoDB's primary keys:

    ```js
    attributes: {
      id: { type: 'string', columnName: '_id' },
      //…
    }
    ```

That's it!  Lift your app again and you should be good to go.

#### Case-sensitivity

After configuring your project to use MongoDB, you may notice that your Waterline [queries](https://sailsjs.com/documentation/reference/waterline-orm/queries) are now case-sensitive by default. To do case-insensitive queries, you can use [`.meta({makeLikeModifierCaseInsensitive: true})`](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).

### Deploying your app with MongoDB

To use MongoDB in production, edit your adapter setting in `config/env/production.js`:

```js
adapter: 'sails-mongo',
```

You may also configure your [connection URL](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores#?the-connection-url) -- but many developers prefer not to check sensitive credentials into version control.  Another option is to use an environment variable:

```
sails_datastores__default__url=mongodb://heroku_12345678:random_password@ds029017.mLab.com:29017/heroku_12345678
```

> To use MongoDB in your staging environment, edit `config/env/staging.js`.  Depending on your application, it may be acceptable to check in your staging database credentials to version control, since they are less of a security risk.


### Low-level MongoDB usage (advanced)

As with all of the [Sails database adapters](https://sailsjs.com/documentation/concepts/extending-sails/adapters/available-adapters), you can use any of the [Waterline model methods](https://sailsjs.com/documentation/reference/waterline-orm/models) to interact with your models when using `sails-mongo`.

For many apps, that's all you'll need-- from "hello world" to production.  Even if you run into limitations, they can usually be worked around without writing Mongo-specific code.  However, for situations when there is no alternative, it is possible to use the Mongo driver directly in your Sails app.

To access the lower-level &ldquo;native&rdquo; MongoDB client directly, use the [`.manager`](https://sailsjs.com/documentation/reference/waterline-orm/datastores/manager) property of the [datastore instance](https://sailsjs.com/documentation/reference/application/sails-get-datastore).

As of `sails-mongo` v2.0.0 and above, you can access the [`MongoClient`](https://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html) object via `manager.client`. This gives you access to the latest MongoDB improvements, like [`ClientSession`](https://mongodb.github.io/node-mongodb-native/3.5/api/ClientSession.html),
and with it, transactions, [change streams](https://mongodb.github.io/node-mongodb-native/3.5/api/ChangeStream.html), and other new features.

```js
var mongoClient = Pet.getDatastore().manager.client;

var results = await mongoClient.db('test')
.collection('pet')
.find({}, { name: 1 })
.toArray();

console.log(results);
```

For a full list of methods available in the native MongoDB client, see the [Node.js MongoDB Driver API reference](https://mongodb.github.io/node-mongodb-native/3.5/api/Collection.html).


<docmeta name="displayName" value="Using MongoDB">

---

### Tutorials Tutorials (`docs/tutorials/tutorials.md`)

# Tutorials

Here you can find step-by-step guides for dealing with a few specific Sails use cases. There's a wealth of great information and tutorials about Sails across the web; these are just a few that have been personally vetted by members of the core team.  Currently, the objective of this section of the docs is to cover some less common scenarios that users have asked about, but that would add unnecessary complexity to the reference & conceptual documentation if they were included there. In the future, we hope to also address some common _"How do I ...?"_ questions that we hear from newcomers to the framework.

If you have a use case you would like to see addressed here, and/or are interested in writing a tutorial yourself, we appreciate your input! Just take a look at our [contribution guide](https://sailsjs.com/documentation/contributing) if you haven't already, then open an issue in the [`sails`](https://github.com/balderdashy/sails/issues/new) repo with a proposal for the tutorial you'd like to see/write.

<docmeta name="displayName" value="Tutorials">
<docmeta name="isOverviewPage" value="true">

---

### Tutorials TypeScript (`docs/tutorials/typeScript.md`)

# Using TypeScript in a Sails app

**The recommended language for building Node.js+Sails apps is JavaScript.**

But Sails also supports using TypeScript to write your custom app code (like [actions](http://www.sailsjs.com/documentation/concepts/actions-and-controllers) and [models](https://sailsjs.com/documentation/concepts/models-and-orm)).  You can enable this support in just a few steps:

1. Run `npm install typescript ts-node --save` in your app folder.
2. Install the necessary typings for your app.  At the very least you'll probably want to:
   ```
   npm install @types/node --save
   npm install @types/express --save
   ```
3. Add the following line at the top of your app's `app.js` file:
```javascript
require('ts-node/register');
```
4. Start your app with `node app.js` instead of `sails lift`.

To get you started, here's an example of a traditional Sails [controller](https://sailsjs.com/documentation/concepts/actions-and-controllers) written in Typescript, courtesy of [@oshatrk](https://github.com/oshatrk):

```typescript
// api/controllers/SomeController.ts
declare var sails: any;

export function hello(req:any, res:any, next: Function):any {
  res.status(200).send('Hello from Typescript!');
}
```

To try that example out, configure a route so that its target points at `SomeController.hello`, relift, and then visit the route in your browser or with a tool like Postman.

<docmeta name="displayName" value="Using TypeScript">

---

### Upgrading To0.10 (`docs/upgrading/To0.10.md`)

# Upgrading to Sails v0.10

For the most part, running sails lift in an existing v0.9 project should just work. The core contributors have taken a number of steps to make the upgrade as easy as possible, and if you follow the deprecation messages in the console, you should do just fine.

Sails v0.10 comes with some big changes. The sections below provide a high level overview of what's changed, major bug fixes, enhancements and new features, as well as a basic tutorial on how to upgrade your v0.9.x Sails app to v0.10.

## File uploads

The Connect multipart middleware [will soon be officially deprecated](http://www.senchalabs.org/connect/multipart.html). But since this module was used as the built-in HTTP body parser in Sails v0.9 and Express v3, this is a breaking change for v0.9 Sails projects relying on `req.files`.

By default in v0.10, Sails includes [skipper](https://github.com/balderdashy/skipper), a body parser which allows for streaming file uploads without buffering tmp files to disk. For run-of-the-mill file upload use cases, Skipper comes with bundled support for uploads to local disk (via skipper-disk), but streaming uploads can be plugged in to any of its supported adapters.

For examples/documentation, please see the Skipper repository as well as the Sails documentation on `req.file()`.

### Why?

A body parser's job is to parse the "body" of incoming multipart HTTP requests. Sometimes, that "body" includes text parameters, but sometimes, it includes file uploads.

Connect multipart is great code, and it supports both file uploads AND text parameters in multipart requests. But like most modules of its kind, it accomplishes this by buffering file uploads to disk. This can quickly overwhelm a server's available disk space, and in many cases exposes a serious DoS attack vulnerability.

Skipper is unique in that it supports **streaming** file uploads, but also maintains support for metadata in the request body (i.e. JSON/XML/urlencoded request body parameters). It uses a handful of heuristics to make sure only the files you're expecting get plugged in and received by the blob adapter, and other (potentially malicous) file fields are ignored.

> #### ** Important!**
> For Skipper to work, you _must include all text parameters BEFORE file parameters_ in file upload requests to the server. Once Skipper sees the first file field, it stops waiting for text parameters (this is to avoid unnecessary/unsafe buffering of file data).

### Configuring a different body parser

As with most things in Sails, you can use any Connect/Express/Sails-compatible bodyparser you like. To switch back to **connect-multipart**, or any other body parser (like **formidable** or **busboy**), change your app's http configuration.

## Blueprints

A new blueprint action (`findOne`) has been added. For instance, if you have a `FooController` and `Foo` model, then send a request to `/foo/5`, the `findOne` action in your `FooController` will run. If you don't have a `findOne` action, the `findOne` blueprint action will be used in its stead. Requests sent to `/foo` will still run the find controller/blueprint action.

## Policies

Policies work exactly as they did in v0.9- however there is a new consideration you should take into account: Due to the introduction of the more specific `findOne()` blueprint action mentioned above, you will want to make sure you're handling it explicitly in your policy mapping configuration.

For example, let's say you have a v0.9 app whose `policies.js` configuration prevents access to the `find` action in your `DoveController`:

```
module.exports.policies = {
  '*': true,
  DoveController: {
    find: false
  }
};
```

Assuming rest blueprint routes are enabled, this would prevent access to requests like both `/dove` and `/dove/14`. But now in v0.10, since `/dove/14` will actually run the `findOne` action, we must handle it explicitly:

```
module.exports.policies = {
  '*': true,
  DoveController: {
    find: false,
    findOne: false
  }
};
```

## Pubsub

### Summary
+ `message` socket (i.e. "comment") event on client is now `modelIdentity` (where "modelIdentity" is different depending on the model that the `publish*()` method was called from.
+ Clients are no longer subscribed to model-creation events by the blueprint routes. To listen for creation events, use `Model.watch()`.
+ The events that were formerly `create`, `update`, and `destroy` are now `created`, `updated`, and `destroyed`.

### Details
The biggest change to pubsub is that Socket.io events are emitted under the name of the model emitting them. Previously, your client listened for the `message` event and then had to determine which model it came from based on the included data:

```
socket.on('message', function(cometEvent) {
   if (cometEvent.model == 'user') {
     // Handle inbound messages related to a user record
   }
   else if (cometEvent.model === 'product') {
     // Handle inbound messages related to a product record
   }
   // ...
}
```
Now, you subscribe to the identity of the model:
```
socket.on('user', function(cometEvent) {
  // Handle inbound messages related to a user record
});

socket.on('product', function (cometEvent) {
  // Handle inbound messages related to a product record
});
```
This helps to structure your front end code.

The way you subscribe clients to models has also changed. Previously, you specified whether you were subscribing to the model class (class room) or one or more model instances based on the parameters that you passed to `Model.subscribe`. It was effectively one method to do two very different things.

Now, you use `Model.subscribe()` to subscribe only to model instances (records). You can also specify event "contexts", or types, that you'd like to hear about. For example, if you only wanted to get messages about updates to an instance, you would call `User.subscribe(req, myUser, 'update')`. If no context is given in a call to `.subscribe()`, then all contexts specified by the model class's autosubscribe property will be used.

To subscribe to model creation events, you can now use `Model.watch()`. Upon subscription, your clients will receive messages every time a new record is created on that model using the blueprint routes, and will automatically be subscribed to the new instance as well.

Remember, when working with blueprints, clients are no longer auto subscribed to the class room. This must be done manually.

Finally, if you want to see all pubsub messages from all models, you can access the `firehose`, a development-only tool that broadcasts messages about _everything_ that happens to your models. You can subscribe to the firehose using `sails.sockets.subscribeToFirehose(socket)`, or on the front end by making a socket request to `/firehose`. The firehose will broadcast a `firehose` event whenever a model is created, updated, destroyed, added to, removed from or messaged. This effectively replaces the `message` event used in previous Sails versions.

To see examples of the new pubsub methods in action, see [SailsChat](https://github.com/balderdashy/sailschat).

## Arguments to lifecycle callbacks are now typecasted

Previously, with `schema: true`, if you sent an attribute value to a `.create()` or `.update()` that did not match the expected type declared in the model's attributes, the value you passed in would still be accessible in your model's lifecycle callbacks.

In Sails/Waterline v0.10, this is no longer the case. Values passed to `.create()` and `.update()` are type-casted before your lifecycle callbacks run. Affected lifecycle callbacks include `beforeUpdate()`, `beforeCreate()`, and `beforeValidate()`.

## beforeValidation() is now beforeValidate()

If you were using the `beforeValidation` or `afterValidation` model lifecycle callbacks in any of your models, you should change them to `beforeValidate` or `afterValidate`. This change was made in Waterline to match the style of the other lifecycle callbacks (e.g. `beforeCreate`, `afterUpdate`, etc.).

## .done() vs. .exec()

** The old (/confusing?) meaning of `.done()` has been deprecated.**

In Sails <= v0.8, the syntax for executing an ORM query was `Model. [ … ] .done( cb )`. In v0.9, when promise support was added, the `Model. [ … ] .exec( cb )` became the recommended replacement, since `.done()` has a special meaning in the promise spec. However, the original usage of `.done()` was left untouched to make upgrading from v0.8 to v0.9 easier.

But as of Sails/Waterline v0.10, the original meaning of `.done()` has been officially deprecated to allow for a more robust promise implementation going forward, and pluggable promise library support (e.g. choose `Q` or `Bluebird` etc.).

## Associations

Sails v0.10 introduces associations between data models. Since the work we've done on associations is largely additive, your existing models should still just work. That said, this is a powerful new feature that allows you to write less code and makes your app more maintainable, so we suggest taking advantage of it! To learn about how to use associations in Sails, check out the docs.

Associations (or "relations") are really just special attributes. Instead of string or integer values, you can specify an instance of a model or a collection of model instances. You can think about this kind of like an object (`{...}`) or an array (`[{...}, {...}]`) you might store as JSON in a NoSQL database. The difference is, in Sails, this works with any of the supported databases, and even allows you to populate (i.e. join) across different databases and types of databases.

## Generators

Sails has had support for generating code for a while now (e.g. `sails generate controller foo`) but in v0.10, we wanted to make this feature more extensible, open, and accessible to everybody in the Sails community. With that in mind, v0.10 comes with a complete rewrite of the command-line tool, and pluggable generators. Want to be able to run `sails generate blog foo` to make a new blog built on Sails? Create a `blog` generator (run sails `generate generator blog`), add your templates, and configure the generator to copy the new templates over. Then you can release it to the community by publishing an npm module called `sails-generate-blog`. Compatibility with Yeoman generators is also in our roadmap.

## Command-line tool

The big change here is how you create a new api. In the past you called `sails generate new_api`. This would generate a new controller and model called `new_api` in the appropriate places. This is now done using `sails generate api new_api`.

You can still generate models and controllers seperately using the same CLI Commands.

Also, `--linker` switch is no longer available. In previous version, if `--linker` switch was provided, it created a `myApp/assets/linker folder`, with `js`, `styles` and `templates` folders inside. In this new version, the `myApp/assets/linker` folder is not created. Compiling CoffeeScript and Less is the default behavior now, right from the `myApp/assets/js` and `myApp/assets/scripts` folders.

## Custom server responses

In v0.10, you can now generate your own custom server responses.

Like before, there are a few that we automatically create for you. Instead of generating `myApp/config/500.js` and other `.js` responses in the config directory, they are now generated in `myApp/api/responses/`.

To migrate, you will need to create a new v0.10 project and copy the `myApp/api/responses` directory into your existing app. You will then modify the appropriate .js file to reflect any customization you made in your response logic files (500.js,etc).

## Legacy data stored in the temporary sails-disk database

`sails-disk`, used by default in new Sails projects, now stores data a bit differently. If you have some temporary data stored in a 0.9.x project, you'll want to wipe it out and start fresh. To do this:

From your project's root directory:

```
$ rm .tmp/disk.db
```

## Adapter/Database Configuration

`config.adapters` (in `myApp/config/adapters.js`) is now config.connections (in new projects, this is generated in `myApp/config/connections.js`). Also, `config.model` is now `config.models`.

Your app's default `connection` (i.e. database) should now be configured as a string `config.models.connection` used by default for model. New projects are generated with a `/config/models.js` file that includes the default connection.

To configure a model to use specific adapters, you must now specify them in the `connection` key instead of `adapters`.

For example:
```
module.exports = {

    connection: ['someMongoDatabase'],

    attributes: {
        name:{
            type     : 'string',
            required : true
        }
    }
};
```

## Blueprints/Controller configuration

The object literal describing controller configuration overrides for controller blueprints should change from:
```
...
_config: {
  blueprints: {
    rest: true,
    ...
  }
}
```
to:
```
...
_config: {
    rest: true,
    ...
}
```

## Layout paths:
In Sails v0.9, you could use the following syntax to specify `auth/someLayout.ejs` as a custom layout when rendering a view:
```
return res.view('auth/login',{
  layout: 'someLayout'
});
```
However in Sails v0.10, all layout paths are relative to your app's views path. In other words, the relative path of the layout is no longer resolved from the view's own path-- it is now always resolved from the views path. This makes it easier to understand which file is being used, particularly when layout files have similar names:
```
return res.view('auth/login', {
  layout: 'auth/someLayout'
});
```


<docmeta name="displayName" value="To v.0.10">
<docmeta name="version" value="0.10.0">

---

### Upgrading To0.11 (`docs/upgrading/To0.11.md`)

# Upgrading to Sails v0.11


**tldr;**

v0.11 comes with many minor improvements, as well as some internal cleanup in core.  The biggest change is that Sails core is now using Socket.io v1.

Almost none of this should affect the existing code in project, but there are a few important differences and new features to be aware of.  We've listed them below.


## Differences

#### Upgrade the Socket.io / Sails.io browser client

Old v0.9 socket.io client will no longer work, so consequently you'll need to upgrade your sails.io.js client from v0.9 or v0.10 to v0.11.

To do this, just remove your sails.io.js client and install the new one.  We've bundled a new generator that will do this for you, assuming your sails.io.js client is in the conventional location at `assets/js/dependencies/sails.io.js` (i.e. if you haven't moved or renamed it):

```sh
sails generate sails.io.js --force
```


####  `onConnect` lifecycle callback

> **tldr;**
>
> Remove your `onConnect` function from `config/sockets.js`.

The `onConnect` lifecycle callback has been deprecated.  Instead, if you need to do something when a new socket is connected, send a request from the newly-connected client to do so.  The purpose of `onConnect` was always for optimizing performance (eliminating the need to do this initial extra round-trip with the server), yet its use can lead to confusion and race conditions. If you desperately need to eliminate the server roundtrip, you can bind a handler directly on `sails.io.on('connect', function (newlyConnectedSocket){})` in your bootstrap function (`config/bootstrap.js`). However, note that this is discouraged.  Unless you're facing _true_ production performance issues, you should use the strategy mentioned above for your "on connection" logic (i.e. send an initial request from the client after the socket connects).  Socket requests are lightweight, so this doesn't add any tangible overhead to your application, and it will help make your code more predictable.



####  `onDisconnect` lifecycle callback

The `onDisconnect` lifecycle callback has been deprecated in favor of `afterDisconnect`.

If you were using `onDisconnect` previously, you might have had to change the `session`, then call `session.save()` manually.  In v0.11, this works in almost exactly the same way, except that `afterDisconnect` receives an additional 3rd argument: a callback function.  This way, you can just call the provided callback when your `afterDisconnect` logic has finished, so that Sails can persist any changes you've made to the session automatically.  Finally, as you might expect, you won't need to call `session.save()` manually anymore- it is now taken care of for you (just like `req.session` in a normal route, action, or policy.)


> **tldr;**
> Rename your `onDisconnect` function in `config/sockets.js` with the following:
>
```
afterDisconnect: function (session, socket, cb) {
 // Be sure to call the callback
 return cb();
}
```




####  Other configuration in `config/sockets.js`

Many of the configuration options in Socket.io v1 have changed, so you'll want to update your `config/sockets.js` file accordingly.

+ if you haven&rsquo;t customized any of the options in `config/sockets.js` for your app, you can safely remove or comment out the entire file and let the Sails defaults do their magic.  Otherwise, refer to the new [Sails sockets  documentation](https://sailsjs.com/documentation/reference/configuration/sails-config-sockets) to ensure that your configuration is still valid and avoid unwanted hair loss.
+ if you are scaling to multiple servers in an environment that does *not support sticky sessions* (this includes Heroku), you'll need to set your `transports` to `['websocket']` in both `config/socket.js` and your client--see [our Scaling doc](https://sailsjs.com/documentation/concepts/deployment/scaling#?preparing-your-app-for-a-clustered-deployment) for more info.
+ if you were using a custom `authorization` function to restrict socket connections, you'll now want to use `beforeConnect`.  `authorization` was deprecated by Socket.io v1, but `beforeConnect` (which maps to the `allowRequest` option from Engine.io) works just the same way.
+ if you were using other low-level socket configuration that was passed directly to socket.io v1, be sure and check out the [reference page on sailsjs.com](https://sailsjs.com/documentation/reference/configuration/sails-config-sockets) where all of the new configuration options are covered in detail.


#### The "firehose"

The "firehose" feature for testing with sockets has been deprecated.  If you don't know what that means, you have nothing to worry about. The basic usage will continue to work for a while, but it will soon be removed from core and should not be relied upon in your app.  This also applies to the following methods:
  + sails.sockets.subscribeToFirehose()
  + sails.sockets.unsubscribeFromFirehose()
  + sails.sockets.drink()
  + sails.sockets.spit()
  + sails.sockets.squirt()

> If you want the "firehose" back, let [Mike know on twitter](http://twitter.com/mikermcneil) (it can be brought back as a separate hook).

#### Config files in subfolders

It has always been the intention that files in the Sails `config` folder have no precedence over each other, and that the filenames and subfolders (with the exception of `local.js` and the `env` and `locale` subfolders) be used merely for organization.  However, in previous Sails versions, saving config files in subfolders would have the effect that the filename would be added as a key in `sails.config`, so that if you saved some config in `config/foo/bar.js`, then that config would be namespaced under `sails.config.bar`.  This was unintentional and potentially confusing as 1) the directory name is ignored, and 2) moving the file would change the config key.  This has been fixed in v0.11.x: config files in subfolders will be treated the same as those in the root `config` folder.  If you are for some reason relying on the old behavior, you may set `dontFlattenConfig` to `true` in your `.sailsrc` file, but we would strongly recommend that you instead just namespace the config yourself by setting the desired key on `module.exports`; for example `module.exports.foo = {...}`.  See [issue #2544](https://github.com/balderdashy/sails/issues/2544) for more details.

#### Waterline now uses Bluebird

As of v0.11, Waterline now supports Bluebird (instead of q) for promises.  If you are using `.exec()` you won't be affected-- only if you are using `.then()`.  See https://github.com/balderdashy/sails/issues/1186 for more information.


## New features

Sails v0.11 also comes with some new stuff that we thought you'd like to know about:


#### User-level hooks

Hooks can now be installed directly from NPM.

This means you can now install hooks with a single command in your terminal.  For instance, consider the [`autoreload` hook](https://github.com/sgress454/sails-hook-autoreload) by [@sgress454](https://twitter.com/sgress454), which watches for changes to your backend code so you don't need to kill and re-lift the server every time you change your controllers, routes, models, etc.

To install the `autoreload` hook, run:

```sh
npm install sails-hook-autoreload
```

This is just one example of what's possible.  As you might already know, hooks are the lowest-level pluggable abstraction in Sails.  They allow authors to tap into the lift process, listen for events, inject custom "shadow" routes, and, in general, take advantage of raw access to the `sails` runtime.
Most of the features you're familiar with in Sails have actually already been implemented as "core" hooks for over a year, including:

+ `blueprints` _(which provides the blueprint API)_
+ `sockets`    _(which provides socket.io integration)_
+ `grunt`      _(which provides Grunt integration)_
+ `orm`        _(which provides integration with the Waterline ORM, and imports your projects adapters, models, etc.)_
+ `http`       _(which provides an HTTP server)_
+ and 16 others.

You can read more about how to write your own hooks in the [new and improved "Extending Sails" documentation](https://sailsjs.com/documentation/concepts/extending-sails) on https://sailsjs.com.


#### Socket.io v1.x

The upgrade to Socket.io v1.0 shouldn't actually affect your app-level code, provided you are using the layer of abstraction provided by Sails itself; everything from the `sails.sockets.*` wrapper methods and "up" (resourceful pubsub, blueprints)
If you are using underlying socket.io methods in your apps, or are just curious about what changed in Socket.io v1.0, be sure and check out the [complete Socket.io 1.0 migration guide](http://socket.io/docs/migrating-from-0-9/) from Guillermo and the socket.io team.

#### Ever-increasing modularity

As part of the upgrade to Socket.io v1.0, we pulled out the core `sockets` hook into a separate repository.  This allowed us to write some modular, hook-specific tests for the socket.io interpreter, which will make things easier to maintain, customize, and override.
This also allows the hook to grow at its own pace, and puts related issues in one place.

Consider this a test of the pros and cons of pulling other hooks out of the sails core repo over the next few months.  This will make Sails core lighter, faster, and more extensible, with fewer core dependencies, shorter "lift" time for most apps, and faster `npm install`s.


#### Testing, the "virtual" request interpreter, and the `sails.request()` method

In the process of pulling the `sockets` hook _out_ of core, the logic which interprets requests has been normalized and is now located _in_ Sails core.  As a result, the `sails.request()` method is much more powerful.

This method allows you to communicate directly with the request interpreter in Sails without lifting your server onto a port.  It's the same mechanism that Sails uses to map incoming messages from Socket.io to "virtual requests" that have the familiar `req` and `res` streams.

The primary use case for `sails.request()` is in writing faster-running unit and integration tests, but it's also handy for proxying to mounted apps (or "sub-apps").

For instance, here is an example (using mocha) of how you might test one of your app's routes:

```js
var assert = require('assert');
var Sails = require('sails').Sails;

before(function beforeRunningAnyTests (done){

  // Load the app (no need to "lift" to a port)
  sails.load({
    log: {
      level: 'warn'
    },
    hooks: {
      grunt: false
    }
  }, function whenAppIsReady(err){
    if (err) return done(err);

    // At this point, the `sails` global is exposed, although we
    // could have disabled it above with our config overrides to
    // `sails.load()`. In fact, you can actually use this technique
    // to set any configuration setting you like.
    return done();
  });
});

after(function afterTestsFinish (done) {
  sails.lower(done);
});

describe('GET /hotpockets', function (){

  it('should respond with a 200 status code', function (done){

    sails.request({
      method: 'get',
      url: '/hotpockets',
      params: {
        limit: 10,
        sort: 'price ASC'
      }
    }, function (err, clientRes, body) {
      if (err) return done(err);

      assert.equal(clientRes.statusCode, 200);
      return done();
    });

  });
});
```


#### `config/env/` subfolders

In v0.10.x, we added the `config/env` folder (thanks to [@clarkorz](https://github.com/clarkorz)), where you can add config files that will be loaded only in the appropriate environment (e.g. `config/env/production.js` for production environment, `config/env/development` for development, etc.).  In v0.11.x we've added the ability to specify whole subfolders per-environment.  For example, *all* config files saved to the `config/env/production` will be loaded and merged on top of other configuration when the environment is set to `production`.  Note that if both a `config/env/production` folder and a `config/env/production.js` file are present, the `config/env/production.js` settings will take precedence.  And, as always, `local.js` is merged on top of all other files, and `.sailsrc` rules them all.


## Questions?

As always, if you run into issues upgrading, or if any of the notes above don't make sense, let us know and we'll do what we can to clarify.

Finally, to those of you that have contributed to the project since the v0.10 release in August: we can't stress enough how much we value your continued support and encouragement.  There is a pretty massive stream of issues, pull requests, documentation tweaks, and questions, but it always helps to know that we're in this together :)

Thanks.

-[@mikermcneil](https://github.com/mikermcneil/), [@sgress454](https://github.com/sgress454/) and [@particlebanana](https://github.com/particlebanana/)


<docmeta name="displayName" value="To v0.11">
<docmeta name="version" value="0.11.0">

---

### Upgrading To0.12 (`docs/upgrading/To0.12.md`)

# Upgrading to Sails v0.12

Sails v0.12 comes with an upgrade to Socket.io and Express, as well as many bug fixes and performance enhancements. While you should find that this version is mostly backwards compatible with Sails v0.11, there are some major changes to `sails.sockets.*` methods which may affect your app. Those changes are addressed in the migration guide below, so if you are upgrading an existing app from v0.11 and are using `sails.sockets` methods, please be sure and carefully read the information below. Aside from those changes, running `sails lift` in an existing project should just work.

The sections below provide a high-level overview of what's changed, major bug fixes, enhancements and new features, as well as a basic tutorial on how to upgrade your v0.11.x Sails app to v0.12.

## Installing the update

Run the following command from the root of your Sails app:

```bash
npm install sails@~0.12.0 --force --save
```

The `--force` flag will override the existing Sails dependency installed in your `node_modules/` folder with the latest patch release of Sails v0.12, and the `--save` flag will update your package.json file so that future npm installs will also use the new version.


## Things to do immediately after upgrading

 + If your app uses the `socket.io-redis` adapter, upgrade to at least version 1.0.0 (`npm install --save socket.io-redis@^1.0.0`).
 + If your app is using the Sails socket client (e.g. `assets/js/dependencies/sails.io.js`) on the front end, also install the newest version (`sails generate sails.io.js --force`).


## Overview of changes in v0.12

> For a full list of changes, see the changelog file for [Sails](https://github.com/balderdashy/sails/blob/master/CHANGELOG.md), as well as those for [Waterline](https://github.com/balderdashy/waterline/blob/master/CHANGELOG.md), [sails-hook-sockets](https://github.com/balderdashy/sails-hook-sockets/blob/master/CHANGELOG.md) and [sails.io.js](https://github.com/balderdashy/sails.io.js/blob/master/CHANGELOG.md).

+ Security enhancements: updated several dependencies with potential vulnerabilities.
+ Reverse routing functionality is now built into Sails core via the new [`sails.getRouteFor()`](https://sailsjs.com/documentation/reference/application/sails-get-route-for) and [`sails.getUrlFor()`](https://sailsjs.com/documentation/reference/application/sails-get-url-for) methods.
+ Generally improved multi-node support (and therefore scalability) of low-level `sails.socket.*` methods, and made additional adjustments and improvements related to the latest socket.io upgrade.  Added a much tighter Redis integration that sits on top of `socket.io-redis`, using a Redis client to implement cross-server communication rather than an additional socket client.
+ Cleaned up the API for `sails.socket.*` methods, normalizing overloaded functions and deprecating methods which cause problems in multiserver deployments (more on that below).
+ Added a few brand new sails.sockets methods: `.leaveAll()`, `.addRoomMembersToRooms()`, and `.removeRoomMembersFromRooms()`.
+ `sails.sockets.id()` is now `sails.sockets.getId()` (backwards compatible with deprecation message).
+ New Sails apps are now generated with the updated version of `sails.io.js` (the JavaScript Sails socket client).  This upgrade bundles the latest version of `socket.io-client`, as well as some more advanced functionality (including the ability to specify common headers for all virtual socket requests).
+ Upgraded to latest trusted versions of `grunt-contrib-*` dependencies (eliminates many NPM deprecation warnings and provides better error messages from NPM).
+ If you are using NPM v3, running `sails new` will now run `npm install` instead of symlinking your new app's initial dependencies.  This is slower than you may be used to, but it is a necessary change due to changes in the way NPM handles nested dependencies.  The core maintainers are [working on](https://github.com/npm/npm/issues/10013#issuecomment-178238596) a better long-term solution, but in the meantime if you frequently run `sails new` and the slowdown is bugging you, consider temporarily downgrading to an earlier version of NPM (v2.x).  If the installed version of NPM is prior to version 3, Sails will continue to take advantage of the classic symlinking strategy.


## Socket Methods

Without question, the biggest change in Sails v0.12 is to the API of the low-level `sails.sockets` methods exposed by the `sockets` hook.  In order to ensure that Sails apps perform flawlessly in a [multi-server (aka "multi-node" or "clustered") environment](https://sailsjs.com/documentation/concepts/realtime/multi-server-environments), several [low-level methods](https://sailsjs.com/documentation/reference/web-sockets/sails-sockets) have been deprecated and some new ones have been added.

The following `sails.sockets` methods have been deprecated:

 + [`.emit()`](https://0.12.sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-emit)
 + [`.id()`](https://0.12.sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-id) (renamed to [`.getId()`](https://sailsjs.com/documentation/reference/web-sockets/sails-sockets/get-id))
 + [`.socketRooms()`](https://0.12.sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-socket-rooms)
 + [`.rooms()`](https://0.12.sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-rooms)
 + [`.subscribers()`](https://0.12.sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-subscribers)

If you are using any of those methods in your app, they will still work in v0.12 but _you should replace them as soon as possible_ as they may be removed from Sails in the next version.  See the individual doc pages for each method for more information.

## Resourceful PubSub Methods

The [`.subscribers()`](https://sailsjs.com/documentation/reference/web-sockets/resourceful-pub-sub/subscribers) resourceful PubSub method has been deprecated for the same reasons as [`sails.sockets.subscribers()`](https://sailsjs.com/documentation/reference/web-sockets/sails-sockets/sails-sockets-subscribers).  Follow the guidelines in the docs for replacing this method if you are using it in your code.


## Waterline (ORM) Updates

Sails v0.12 comes with the latest version of the Waterline ORM (v0.11.0).  There are two API changes to be aware of:

##### `.save()` no longer provides a second argument to its callback

The callback to the `.save()` instance method no longer receives a second argument.  While requiring the second argument was convenient, it made `.save()` less performant, especially for apps working with millions of records.  This change resolves those issues by eliminating the need to build redundant queries, and preventing your database from having to process them.

If there are places in your app where you have code like this:
```javascript
sierra.save(function (err, modifiedSierra){
  if (err) { /* ... */  return; }

  // ...
});
```

You should replace it with:
```javascript
sierra.save(function (err){
  if (err) { /* ... */  return; }

  // ...
});
```



##### Custom column/field names for built-in timestamps

You can now configure a custom column name (i.e. field name, for Mongo/Redis folks) for the built-in `createdAt` and `updatedAt` attributes.  In the past, the top-level `autoCreatedAt` and `autoUpdatedAt` model settings could be specified as `false` to disable the automatic injection of `createdAt` and `updatedAt` altogether.  That _still works as it always has_, but now you can also specify string values for one or both of these settings instead.  If a string is specified, it will be understood as the custom column (/field) name to use for the automatic timestamp.

```javascript
{
  attributes: {},
  autoCreatedAt: 'my_cool_created_when_timestamp',
  autoUpdatedAt: 'my_cool_updated_at_timestamp'
}
```

If you were using the [workaround suggested by @sgress454 here](http://stackoverflow.com/a/24562385/486547), you may want to take advantage of this simpler approach instead.



## SQL Adapter Performance

[Sails-PostgreSQL](https://github.com/balderdashy/sails-postgresql) and [Sails-MySQL](https://github.com/balderdashy/sails-mysql) recieved patch updates that significantly improved performance when populating associations. Thanks to [@jianpingw](https://github.com/jianpingw) for digging into the source and finding a bug that was processing database records too many times. If you are using either of these adapters, upgrading to `sails-postgresql@0.11.1` or `sails-mysql@0.11.3` will give you a significant performance boost.


## Contributing

While not technically part of the release, Sails v0.12 is accompanied by some major improvements to the tools and resources available to contributors.  More core hooks are now fully documented ([controllers](https://github.com/balderdashy/sails/tree/master/lib/hooks/controllers)|[grunt](https://github.com/balderdashy/sails/tree/master/lib/hooks/grunt)|[logger](https://github.com/balderdashy/sails/tree/master/lib/hooks/logger)|[cors](https://github.com/balderdashy/sails/tree/master/lib/hooks/cors)|[responses](https://github.com/balderdashy/sails/tree/master/lib/hooks/responses)|[orm](https://github.com/balderdashy/sails/tree/master/lib/hooks/orm)), and the team has put together a [Code of Conduct](https://github.com/balderdashy/sails/blob/master/CODE-OF-CONDUCT.md) for contributing to the Sails project.

The biggest change for contributors is the [updated contribution guide](https://github.com/balderdashy/sails/blob/master/CONTRIBUTING.md), which contains the new, streamlined process for feature/enhancement proposals and for merging features, enhancements, and patches into core.  As the Sails framework has grown (both the code base and the user base), it's become necessary to establish clearer processes for how issue contributions, code contributions, and contributions to the documentation are reviewed and merged.


## Documentation

This release also comes with a deep clean of the official reference documentation, and some minor usability improvements to the online docs at [https://sailsjs.com/documentation](https://sailsjs.com/documentation). The entire Sails website is now available in [Japanese](http://sailsjs.jp/), and four other [translation projects](https://github.com/balderdashy/sails/tree/master/docs#in-other-languages) are underway for Korean, Brazillian Portugese, Taiwanese Mandarin, and Spanish.

In addition, the Sails.js project (finally) has an [official blog](http://blog.sailsjs.com).  The Sails.js blog is the new source for all longform updates and announcements about Sails, as well as for our related projects like Waterline, Skipper, and the machine specification.



## Need Help?

If you run into an unexpected issue upgrading your Sails app to v0.12.0, please review our contribution guide and [submit an issue in the Sails GitHub repo](https://github.com/balderdashy/sails/blob/master/CONTRIBUTING.md).



<docmeta name="displayName" value="To v0.12">
<docmeta name="version" value="0.12.0">

---

### Upgrading To1.0 (`docs/upgrading/To1.0.md`)

# Upgrading to Sails v1.0

Sails v1.0 is here!  Keep reading for a high-level overview of what's changed in this release, and to learn about some new features you might want to take advantage of in your app.


### A note about breaking changes
While working on this version of Sails, a lot of the decisions we made favored a better developer experience over backwards compatibility. Because of this, the upgrade to Sails 1.0 will involve dealing with more breaking changes than previous versions. But when you're finished, there'll be a much better chance that the features you're using in Sails are things that its author and maintainers understand thoroughly and use almost every day.

For more about the philosophy behind many of the breaking changes in 1.0, you can read Mike McNeil's in-depth explanation [here](https://gitter.im/balderdashy/sails?at=5a1d8fcd3a80a84b5b907099).


### Upgrading an existing app using the automated tool

Ready to upgrade your existing v0.12.x Sails app to version 1.0?  To get started, we recommend using the Sails 1.0 upgrade tool, which will help with some of the most common migration tasks.  To use the tool, first install Sails 1.0 globally with `npm install sails@^1.0.0` and then run `sails upgrade`.  After the tool runs, it will create a report for you with a list of remaining items that need to be manually upgraded.

### Upgrading an existing app manually

The checklist below covers the changes most likely to affect the majority of apps.

If your app still has errors or warnings on startup after following this checklist, or if you're seeing something unexpected, head back to this document and take a look further down the page.  (One of the guides for covering various app components will probably be applicable.)

> We've done a lot of work to make the upgrade process as seamless as possible, particularly when it comes to the errors and warnings you'll see on the console.  But if you're stumped or have lingering questions about any of the changes below, feel free to [drop by the Sails community Gitter channel](https://sailsjs.com/support).  (If your company is using Sails Flagship, you can also chat directly with the Sails core team [here](https://flagship.sailsjs.com/ask).)

### tl;dr checklist: things you simply _must_ do when upgrading to version 1.0

The upgrade tool does its best to help with some of these items, but it won&rsquo;t change your app-specific code for you!

+ **Step 0**: Check your Node version
+ **Step 1**: Install hooks & update dependencies
+ **Step 2**: Update configuration
+ **Step 3**: Modify client-side code for the new blueprint API
+ **Step 4**: Adopt the new release of Waterline ORM

##### Step 0: Check your Node version!

If your app needs to support Node versions earlier than v4, you will not be able to upgrade to Sails 1.0, as Sails 1.0 no longer supports Node v0.x. The earliest version of Node supported by Sails 1.0 is Node 4.x.

##### Step 1: Install hooks & update dependencies
Sails v1 introduces [custom builds](https://github.com/balderdashy/sails/pull/3504).  This means that certain core hooks are now installed as direct dependencies of your app, giving you more control over your dependencies and making `npm install sails` run _considerably_ faster.  So, the first thing you'll need to do is install the core hooks you're using.  (And while you're at it, be sure to update the other dependencies mentioned in the list below.)

* **Install the `sails-hook-orm` package** into your app with `npm install --save sails-hook-orm`, unless your app has the ORM hook disabled.
* **Install the `sails-hook-sockets` package** into your app with `npm install --save sails-hook-sockets`, unless your app has the sockets hook disabled.
* **Install the `sails-hook-grunt` package** into your app with `npm install --save sails-hook-grunt`, unless your app has the Grunt hook disabled.
* **Install the latest version of your database adapter**.  For example, if you're using `sails-mysql`, do `npm install --save sails-mysql@latest`.
* **Upgrade your `sails.io.js` websocket client** with `sails generate sails.io.js`.  See the ["Websockets" section below](https://sailsjs.com/documentation/upgrading/to-v-1-0/#?websockets) for more details.


##### Step 2: Update configuration
Sails v1 comes with several improvements in app configuration. For example, automatic install of lodash and async can now be customized to any version, and view engine configuration syntax is now consistent with that of Express v4+. The most significant change to configuration, however, is related to one of the most exciting new features in Sails v1: [datastores](https://sailsjs.com/documentation/reference/waterline-orm/datastores).  To make sure you correctly upgrade the configuration for your database(s) and other settings, be sure to carefully read through the steps below and apply the necessary changes.

* **Update your `config/globals.js` file** (unless your app has `sails.config.globals` set to `false`)
  + Set `models` and `sails` to have boolean values (`true` or `false`).
  + Set `async` and `lodash` to either have `require('async')` and `require('lodash')` respectively, or else `false`. You may need to `npm install --save lodash` and `npm install --save async`, as well.
* **Comment out any database configuration your aren&rsquo;t using** in `config/connections.js`.  Unlike previous versions, Sails 1.0 will load _all_ database adapters that are referenced in config files, regardless of whether they are actually used by a model.  See the [migration guide section on database configuration](https://sailsjs.com/documentation/upgrading/to-v-1-0/#?changes-to-database-configuration) for more info.
* **The `/csrfToken` route** is no longer provided to all apps by default when using CSRF.  If you're utilizing this route in your app, you'll need to manually add it to `config/routes.js` as `'GET /csrfToken': { action: 'security/grant-csrf-token' }`.
* **If your app relies on [action shadow routes](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes#?action-routes)** (where every custom controller action is automatically mapped to a route), you&rsquo;ll need to update your `config/blueprints.js` file and set `actions` to `true`.  This setting is now `false` by default.
* **If your app uses CoffeeScript or TypeScript** see the [CoffeeScript](https://sailsjs.com/documentation/tutorials/using-coffee-script) and [TypeScript](https://sailsjs.com/documentation/tutorials/using-type-script) tutorials for update information.
* **If your app uses a view engine other than EJS**, you&rsquo;ll need to configure it yourself in the `config/views.js` file, and you'll likely need to run `npm install --save consolidate` for your project.  See the "Views" section below for more details.
* **If your `api` or `config` folders and subfolders contain any non-source files**, they&rsquo;ll need to be moved.  The exception is for Markdown (.md) and text (.txt) files, which will continue to be ignored.  Sails will attempt to read all other files in those folders as code, allowing for more flexibility in choosing between Javascript dialects (see the notes about CoffeeScript and TypeScript above).

##### Step 3: Modify client-side code for the new blueprint API
As well as having been expanded to include a new endpoint, there also are a couple of minor&mdash;but breaking&mdash;changes to the blueprint API that may require you to make changes to your client-side code.

* **If your app uses blueprint routes**, be aware that a couple of implicit "shadow" routes have had their HTTP method (aka verb) changed:
  + the RESTful blueprint route address for [**add**](https://sailsjs.com/documentation/reference/blueprint-api/add-to) has changed from `POST` to `PUT`.
  + the RESTful blueprint route address for [**update**](https://sailsjs.com/documentation/reference/blueprint-api/update) has changed from `PUT` to `PATCH`.
* **If your app relies on the default socket notifications from blueprint actions**, be aware that there have been some performance-related upgrades that change the structure of these messages somewhat:
  + Sails no longer publishes separate `addedTo` notifications, one for each new member of a collection. Those individual notifications are now rolled up into a single notification, and the new message contains an array of ids (`addedIds`) instead of just one.
  + Sails no longer publishes separate `removedFrom` notifications, one for each former member of a collection. Sails now rolls those up into a single notification, and the new message now contains an array of ids (`removedIds`) instead of just one.


##### Step 4: Adopt the new release of Waterline ORM
The new release of Waterline ORM (v0.13) introduces full support for SQL transactions, the ability to include or omit attributes in result sets (aka "projections"), dynamic database connections, and more extensive granular control over query behavior.  It also includes a major stability and performance overhaul, which comes with a few breaking changes to usage.  The bullet points below cover the most common issues you're likely to run into with the Waterline upgrade.

* **If your app relies on getting records back from `.create()`, `.createEach()`, `.update()`, or `.destroy()` calls**, you&rsquo;ll need to update your model settings to indicate that you want those methods to fetch records (or chain a `.fetch()` to individual calls).  See the [migration guide section on `create()`, `.createEach()`, `.update()`, and `.destroy()` results](https://sailsjs.com/documentation/upgrading/to-v-1-0/#?changes-to-create-createeach-update-and-destroy-results) for more info.
* **If your app relies on using the `.add()`, `.remove()`, and `.save()` methods to modify collections**, you will need to update them to use the new [.addToCollection](https://sailsjs.com/documentation/reference/waterline-orm/models/add-to-collection), [.removeFromCollection](https://sailsjs.com/documentation/reference/waterline-orm/models/remove-from-collection), and [.replaceCollection](https://sailsjs.com/documentation/reference/waterline-orm/models/replace-collection) model methods.
* **Waterline queries will now rely on the database for case sensitivity.** This means that in most adapters your queries will now be case-sensitive, whereas before they were not. This may have unexpected consequences if you are used to having case-insensitive queries. For more information on how to manage this for databases such as MySQL, see the [case sensitivity docs](https://sailsjs.com/documentation/concepts/models-and-orm/models#?case-sensitivity).
* **Waterline no longer supports nested creates or updates**, and this change extends to the related blueprints.  If your app relies on these features, see the [migration guide section on nested creates and updates](https://sailsjs.com/documentation/upgrading/to-v-1-0/#?nested-creates-and-updates) for more info.
* **If your app sets a model attribute to `null`** using `.create()`, `.findOrCreate()` or `.update()`, you&rsquo;ll need to change the type of that attribute to `json`, or use the base value for the existing attribute type, instead of `null` (e.g. `0` for numbers).  See [the validations docs](https://sailsjs.com/documentation/concepts/models-and-orm/validations#?null-and-empty-string) for more info.
* **The `create` blueprint response is now fully populated**, just like responses from `find`, `findOne`, `update` and `destroy`.  To suppress population of records, add a `parseBlueprintOptions` to your blueprints config or to a specific route.  See the [blueprints configuration reference](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints#?using-parseblueprintoptions) for more information.
* **If you're using `createEach`** to insert large numbers of rows into a database, keep in mind that the Sails 1.0-compatible versions of most adapters now optimize the `createEach` method to use a single query, instead of using one query per row.  Depending on your database, per-request data size limits may apply.  See the [notes at the bottom of the `.createEach()` reference page](https://sailsjs.com/documentation/reference/waterline-orm/models/create-each#?notes) for more information.
* **The `size` property for attributes** is no longer supported.  Instead, you may indicate column size using [the `columnType` property](https://sailsjs.com/documentation/concepts/models-and-orm/attributes#?columntype).
* **The `defaultsTo` property for attributes may no longer be defined as a function.** Instead, you will either need to hard-code a default value, or remove the `defaultsTo` entirely and update your code to determine the appropriate value for the attribute before creating new records. (This can either be handled before calls to `.create()`/`.createEach()` in your actions, or in the model's [`beforeCreate`](https://sailsjs.com/documentation/concepts/models-and-orm/lifecycle-callbacks#?lifecycle-callbacks-on-create)).



### Other breaking changes

The upgrade guide above provides for the most common upgrade issues that Sails contributors have encountered when upgrading various apps between version 0.12 and version 1.0. Every app is different, though, so we recommend reading through the points below, as well.  Not all of the changes discussed will necessarily apply to your app, but some might.

* **Several properties and methods on `req` now work a little differently:**
  * `req.accepted` has been replaced with [`req.accepts()`](https://sailsjs.com/documentation/reference/request-req/req-accepts)
  * `req.acceptedLanguages` and `req.acceptsLanguage()` have been replaced with [`req.acceptsLanguages()`](https://sailsjs.com/documentation/reference/request-req/req-accepts-languages)
  * `req.acceptedCharsets` and `req.acceptsCharset()` have been replaced with [`req.acceptsCharsets()`](https://sailsjs.com/documentation/reference/request-req/req-accepts-charsets)
* **Several `req.options` properties related to blueprints are no longer supported.**  Instead, the new `parseBlueprintOptions` method can be used to give you complete control over blueprint behavior.  See the [blueprints configuration reference](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints#?using-parseblueprintoptions) for more information.
* **The `defaultLimit` and `populate` blueprint configuration options are no longer supported.** Instead, the new `parseBlueprintOptions` method can be used to give you complete control over blueprint behavior.  See the [blueprints configuration reference](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints#?using-parseblueprintoptions) for more information.
* **The `.findOne()` query method no longer supports `sort` and `limit` modifiers, and will throw an error if the given criteria match more than one record**.  If you want to find a single record using anything besides a `unique` attribute (like the primary key) as criteria, use `.find(<criteria>).limit(1)` instead (keeping in mind that this will return an array of one item).
* **`autoPk`, `autoCreatedAt` and `autoUpdatedAt`** are no longer supported as top-level model properties.  See the [migration guide section on model config changes](https://sailsjs.com/documentation/upgrading/to-v-1-0/#?changes-to-model-configuration) for more information.
* **Dynamic finders** (such as `User.findById()`) are no longer added to your models automatically.  You can implement these yourself as [custom model methods](https://sailsjs.com/documentation/concepts/models-and-orm/models#?custom-model-methods).
* **Model Instance Methods** are no longer supported. This allows records returned from find queries to be plain JavaScript objects instead of model record instances.
* **Custom `.toJSON()`** instance methods are no longer supported.  Instead, add a [`customToJSON` method](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?customtojson) to the model class (outside of the `attributes` dictionary).  See the [model settings documentation](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings) for more information.
* **The `.toObject()` instance method** is no longer added to every record.  When implementing [`customToJSON`](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?customtojson) for a model, be sure to clone the record using `_.omit()`, `_.pick()` or `_.clone()`.
* **`autoUpdatedAt` timestamps can now be manually updated** in calls to `.update()` (previously, the passed-in attribute value would be ignored).  The previous behavior faciliated the use of `.save()`, which is no longer supported.  Now, you can update the `updatedAt` if you need to (but generally you should let Sails do this for you!)
* **`beforeValidate` and `afterValidate` lifecycle callbacks no longer exist**. Use one of the [many other lifecycle callbacks](https://sailsjs.com/documentation/concepts/models-and-orm/lifecycle-callbacks) to tap into the query.
* **`afterDestroy` lifecycle callback now receives a single record**. It has been normalized to work the same way as the `afterUpdate` callback and call the function once for each record that has been destroyed rather than once with all the destroyed records.
* **Many resourceful PubSub methods have changed** (see the PubSub section below for the full list).  If your app only uses the automatic RPS functionality provided by blueprints (and doesn&rsquo;t call RPS methods directly), no updates are required.
* **The `.find()` model method no longer automatically coerces constraints that are provided for unrecognized attributes**.  For example, if you execute `Purchase.find({ amount: '12' })`, e.g. via blueprints (http://localhost:1337/purchase?amount=12), and there is no such "amount" attribute, then even if the database contains a record with the numeric equivalent (`12`), it will not be matched.  (This is only relevant when using MongoDB and sails-disk.)  If you are running into problems because of this, either define the attribute as a number or (if you're using blueprints) use an explicit `where` clause instead (e.g. `http://localhost.com:1337/purchase?where={"amount":12}`).
* **Custom blueprints and the associated blueprint route syntax have been removed**.  This functionality can be replicated using custom actions, helpers, and routes.  See the "Replacing custom blueprints" section below for more information.
* **Blueprint action shadow routes no longer include `/:id?`** at the end -- that is, if you have a `UserController.js` with a `tickle` action, you will no longer get a `/user/tickle/:id?` route (instead, it will be just `/user/tickle`).  Apps relying on those routes should add them manually to their `config/routes.js` file.
* **`sails.getBaseUrl`**, deprecated in v0.12.x, has been removed.  See the [v0.12 docs for `getBaseUrl`](http://0.12.sailsjs.com/documentation/reference/application/sails-get-base-url) for more information on why it was removed and how you should replace it.
* **`req.params.all()`**, deprecated in v0.12.x, has been removed.  Use `req.allParams()` instead.
* **`sails.config.dontFlattenConfig`**, deprecated in v0.12.x, has been removed.  See the [original notes about `dontFlattenConfig`](https://sailsjs.com/documentation/upgrading/to-v-0-11#?config-files-in-subfolders) for details.
* **The order of precedence for `req.param()` and `req.allParams()` has changed.**  It is now consistently path > body > query (that is, url path params override request body params, which override query string params).
* **`req.validate()`** has been removed.  Use [`actions2`](https://sailsjs.com/documentation/concepts/actions-and-controllers#?actions-2) instead.
* **The default `res.created()` response has been removed.**  If you&rsquo;re calling `res.created()` directly in your app, and you don't have an `api/responses/created.js` file, you&rsquo;ll need to create one.
 + On a related note, the [Blueprint create action](https://sailsjs.com/documentation/reference/blueprint-api/create) will now return a 200 status code upon success, instead of 201.
* **The default `notFound` and `serverError` responses no longer accept a `pathToView` argument.** They will only attempt to serve a `404` or `500` view.  If you need to be able to call these responses with different views, you can customize the responses by adding `api/responses/notFound.js` or `api/responses/serverError.js` files to your app.
* **The default `badRequest` or `forbidden` responses no longer display views**.  If you don&rsquo;t already have the `api/responses/badRequest.js` and `api/responses/forbidden.js` files, you&rsquo;ll need add them yourself and write custom code if you want them to display view files.
* **The <a href="https://www.npmjs.com/package/connect-flash" target="_blank">`connect-flash`</a> middleware has been removed** (so `req.flash()` will no longer be available by default).  If you wish to continue using `req.flash()`, run `npm install --save connect-flash` in your app folder and [add the middleware manually](https://sailsjs.com/documentation/concepts/middleware).
* **The `POST /:model/:id` blueprint RESTful route has been removed.**  If your app is relying on this route, you&rsquo;ll need to add it manually to `config/routes.js` and bind it to a custom action.
* **The `handleBodyParserError` middleware has been removed**; in its place, the <a href="https://www.npmjs.com/package/skipper" target="_blank">Skipper body parser</a> now has its own `onBodyParserError` method.
  + If you have customized the [middleware order](https://sailsjs.com/documentation/concepts/middleware#?adding-or-overriding-http-middleware), you&rsquo;ll need to remove `handleBodyParserError` from the array.
  + If you've overridden `handleBodyParserError`, you&rsquo;ll need to instead override `bodyParser` with your own customized version of Skipper, including your error-handling logic in the `onBodyParserError` option.
* **The `methodOverride` middleware has been removed.** If your app utilizes this middleware:
  + `npm install --save method-override`
  + Make sure your `sails.config.http.middleware.order` array (in `config/http.js`) includes `methodOverride` somewhere before `router`
  + Add `methodOverride: require('method-override')()` to `sails.config.http.middleware`.
* **The `router` middleware is no longer overrideable.**  Instead, the Express 4 router is used for routing both external and internal (aka &ldquo;virtual&rdquo;) requests.  It&rsquo;s still important to have a `router` entry in `sails.config.http.middleware.order` to delimit which middleware should be added before and after the router.
* **The query modifiers `lessThan`, `lessThanOrEqual`, `greaterThan`, and `greaterThanOrEqual` have been removed**. Use the shorthand versions instead (`<`, `<=`, `>`, `>=`).
* **The [`find one`](https://sailsjs.com/documentation/reference/blueprint-api/find-one) and [`find`](https://sailsjs.com/documentation/reference/blueprint-api/find-where) blueprint actions** now accept a `populate=false` rather than `populate=` to specify that no attributes should be populated.
* **The [`add`](https://sailsjs.com/documentation/reference/blueprint-api/add-to) and [`remove`](https://sailsjs.com/documentation/reference/blueprint-api/remove-from) blueprint actions** now require that the primary key of the child record to add or remove be supplied as part of the URL, rather than allowing it to be passed on the query string or in the body.
* **The [`destroy`](https://sailsjs.com/documentation/reference/blueprint-api/destroy) blueprint action** now requires that the primary key of the record to destroy be supplied as part of the URL, rather than allowing it to be passed on the query string or in the body.
* **The `sails.config.session.routesDisabled` setting has changed** to `sails.config.session.isSessionDisabled()`, a function.  See the [`config/session.js` docs](https://sailsjs.com/documentation/reference/configuration/sails-config-session) for more information on configuring `isSessionDisabled()`.
* **The experimental &ldquo;switchback-style&rdquo; usage for Waterline methods is no longer supported**.  Only function callbacks may be used with Waterline model methods.
* **The experimental `create` auto-migration scheme is no longer supported**.  It is highly recommended that you use a migration tool such as [Knex](http://knexjs.org/#Migrations) to handle migrations of your production database.
* **The experimental `forceLoadAdapter` datastore setting is no longer supported**.  Instead, all adapters referenced in `config/datastores.js` (formerly `config/connections.js`) are automatically loaded whenever Sails lifts.
* **The experimental `usage` route option has been removed.**  It is recommended that you perform any route parameter validation in your controller code.
* **The experimental &ldquo;associated-item&rdquo; blueprint shadow routes have been removed.** These were routes like `GET /user/1/pets/2`, whose functionality can be replicated by simply using the much-clearer route `GET /pets/2`.
* **The experimental `.validate()` method in model classes** (e.g. `User.validate()`) is now fully supported, but its usage has changed.  See the [`.validate()` docs](https://sailsjs.com/documentation/reference/waterline-orm/models/validate) for more information.
* **The ordering of attributes** in the internal representation of model classes has changed (association attributes are now sorted at the bottom).  This has the effect of causing tables created using `migrate: 'alter'` to have their columns in a different order than in previous versions of Waterline, so be aware of this if column ordering is important in your application.  As a reminder, auto-migrations are intended to help you design your schema as you build your app.  They are not guaranteed to be consistent regarding any details of your physical database columns besides setting the column name, type (including character set / encoding if specified) and uniqueness.
* **Using `_config` to link a controller to a model** will no longer work.  This was never a supported feature, but it was used in some projects to change the URLs that were mapped to the blueprint actions for a model.  Please use [`restPrefix`](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints#?properties) instead.
* **The `find()`, `destroy()`, and `update()` methods**  ignore `undefined` attributes. These methods will strip undefined attributes from their search criteria, e.g. `User.update({id: undefined}).with({ firstName: 'Finn'})` would update **every** user record. Read more about this in [this Github issue](https://github.com/balderdashy/sails/issues/4639#issuecomment-320369193)

### Changes to database configuration

* The `sails.config.connections` setting has been deprecated in favor of `sails.config.datastores`.  If you lift an app that still has `sails.config.connections` configured, you&rsquo;ll get a warning which you can avoid by simply changing `module.exports.connections` in `config/connections.js` to `module.exports.datastores`.  For your own sanity, it&rsquo;s recommended that you also change the filename to `config/datastores.js`.
* The `sails.config.models.connection` setting has been deprecated in favor of `sails.config.models.datastore`.  As above, changing the name of the property in `config/models.js` should be sufficient to turn off any warnings.
* Every app now has a default datastore (appropriately named `default`) that is configured to use a built-in version of the [`sails-disk` adapter](https://github.com/balderdashy/sails-disk).  In Sails 1.0, the default value of `sails.config.models.datastore` is `default` (rather than `localDiskDb`). The recommended approach to setting the default datastore for your models is to simply to add the desired configuration under the `default` key in `config/datastores.js`, and leave the `datastore` key in `config/models.js` undefined, rather than the previous approach of setting `datastore` to (for example) `myPostgresqlDb` and then adding a `myPostgresqlDb` key to `config/datastores.js`.  This makes it a lot easier to change the datastore used by different environments (for instance, by changing the configuration of the `default` datastore in `config/env/production.js`).
* _All_ datastores that are configured in an app will be loaded at runtime (rather than only loading datastores that were being used by at least one model).  This has the benefit of allowing the use of a datastore outside the context of an individual model, but it does mean that if you don&rsquo;t want to connect to a certain database when Sails lifts, you should comment out that datastore connection config!

### Nested creates and updates

* The [`.create()`](https://sailsjs.com/documentation/reference/waterline-orm/models/create), [`.update()`](https://sailsjs.com/documentation/reference/waterline-orm/models/update) and [`.add()`](https://sailsjs.com/documentation/reference/waterline-orm/models/find) model methods no longer support creating a new &ldquo;child&rdquo; record to link immediately to a new or existing parent.  For example, given a `User` model with a singular association to an `Animal` model through an attribute called `pet`, it is not possible to set `pet` to a dictionary representing values for a brand new `Animal` (aka a &ldquo;nested create&rdquo;).  Instead, create the new `Animal` first and use its primary key to set `pet` when creating the new `User`.
* Similarly, the [create](https://sailsjs.com/documentation/reference/blueprint-api/create), [update](https://sailsjs.com/documentation/reference/blueprint-api/update) and [add](https://sailsjs.com/documentation/reference/blueprint-api/add-to) blueprint actions no longer support nested creates.
* The [`.update()`](https://sailsjs.com/documentation/reference/waterline-orm/models/update) model method and its associated [blueprint action](https://sailsjs.com/documentation/reference/blueprint-api/update) no longer support replacing an entire plural association.  If a record is linked to one or more other records via a [&ldquo;one-to-many&rdquo;](https://sailsjs.com/documentation/concepts/models-and-orm/associations/one-to-many) or [&ldquo;many-to-many&rdquo;](https://sailsjs.com/documentation/concepts/models-and-orm/associations/many-to-many) association and you wish to link it to an entirely different set of records, use the [`.replaceCollection()` model method](https://sailsjs.com/documentation/reference/waterline-orm/models/replace-collection) or the [replace blueprint action](https://sailsjs.com/documentation/reference/blueprint-api/replace).

### Changes to model configuration

##### tl;dr

Remove any `autoPK`, `autoCreatedAt` and `autoUpdatedAt` properties from your models, and add the following to your `config/models.js` file:

```javascript
  attributes: {
    createdAt: { type: 'number', autoCreatedAt: true, },
    updatedAt: { type: 'number', autoUpdatedAt: true, },
    id: { type: 'number', autoIncrement: true}, // <-- for SQL databases
    id: { type: 'string', columnName: '_id'}, // <-- for MongoDB
  }
```

##### The `autoPK` top-level property is no longer supported

This property was formerly used to indicate whether or not Waterline should create an `id` attribute as the primary key for a model.  Starting with Sails v1.0 / Waterline 0.13, Waterline will no longer create any attributes in the background.  Instead, the `id` attribute must be defined explicitly.  There is also a new top-level model property called `primaryKey`, which can be set to the name of the attribute that should be used as the model's primary key.  This value defaults to `id` for every model, so in general you won't have to set it yourself.

##### The `autoUpdatedAt` and `autoCreatedAt` model settings are now attribute-level properties

These properties were formerly used to indicate whether or not Waterline should create `createdAt` and `updatedAt` timestamps for a model.  Starting with Sails v1.0 / Waterline 0.13, Waterline will no longer create these attributes in the background.  Instead, the `createdAt` and `updatedAt` attributes must be defined explicitly if you want to use them.  By adding `autoCreatedAt: true` or `autoUpdatedAt: true` to an attribute definition, you can instruct Waterline to set that attribute to the current timestamp whenever a record is created or updated. Depending on the type of these attributes, the timestamps will be generated in one of two formats:
  + For `type: 'string'`, these timestamps are stored in the same way as they were in Sails 0.12: as timezone-agnostic ISO 8601 JSON timestamp strings (e.g. `'2017-12-30T12:51:10Z'`).  So if any of your front-end code is relying on the timestamps as strings it's important to set this to `string`.
  + For `type: 'number'`, these timestamps are stored as JS timestamps (the number of milliseconds since Jan 1, 1970 at midnight UTC).

Furthermore, for any attribute, if you pass `new Date()` as a constraint within a Waterline criteria's `where` clause, or as a new record, or within the values to set in a `.update()` query, then these same rules are applied based on the type of the attribute. If the attribute is `type: 'json'`, it uses the latter approach.



### Changes to `.create()`, `.createEach()`, `.update()`, and `.destroy()` results

As of Sails v1.0 / Waterline 0.13, the default result from `.create()`, `.createEach()`, `.update()`, and `.destroy()` has changed.

To encourage better performance and easier scalability, `.create()` no longer sends back the created record. Similarly, `.createEach() ` no longer sends back an array of created records, `.update()` no longer sends back an array of _updated_ records, and `.destroy()` no longer sends back _destroyed_ records.  Instead, the second argument to the .exec() callback is now `undefined` (or the first argument to `.then()`, if you're using promises).

This makes your app more efficient by removing unnecessary `find` queries, and it makes it possible to use `.update()` and `.destroy()` to modify many different records in large datasets, rather than falling back to lower-level native queries.

You can still instruct the adapter to send back created or modified records for a single query by using the `fetch` method.  For example:

```js
Article.update({
  category: 'health-and-wellness',
  status: 'draft'
})
.set({
  status: 'live'
})
.fetch()
.exec(function(err, updatedRecords){
  //...
});
```


> If the prospect of changing all of your app's queries seems daunting, there is a temporary convenience you might want to take advantage of.
> To ease the process of upgrading an existing app, you can tell Sails/Waterline to fetch created/updated/destroyed records for ALL of your app's `.create()`/`.createEach()`/`.update()`/`.destroy()` queries.  Just edit your app-wide model settings in `config/models.js`:
>
> ```js
> fetchRecordsOnUpdate: true,
> fetchRecordsOnDestroy: true,
> fetchRecordsOnCreate: true,
> fetchRecordsOnCreateEach: true,
> ```
>
> That's it!  Still, to improve performance and future-proof your app, you should go through all of your `.create()`, `.createEach()`, `.update()`, and `.destroy()` calls and add `.fetch()` when you can.  Support for these model settings will eventually be removed in Sails v2.

### Changes to Waterline criteria usage
* For performance reasons, as of Sails v1.0 / Waterline 0.13, criteria passed into Waterline's model methods will now be mutated in-place in most situations (whereas in Sails/Waterline v0.12, this was not necessarily the case).
* Aggregation clauses (`sum`, `average`, `min`, `max`, and `groupBy`) are no longer supported in criteria.  Instead, see new model methods [.sum()](https://sailsjs.com/documentation/reference/waterline-orm/models/sum) and [.avg()](https://sailsjs.com/documentation/reference/waterline-orm/models/avg).
* Changes to limit and skip:
  + `limit: 0` **no longer does the same thing as `limit: undefined`**.  Instead of matching ∞ results, it now matches 0 results.
  + Avoid specifying a limit of < 0.  It is still ignored, and acts like `limit: undefined`, but it now logs a deprecation warning to the console.
  + `skip: -20` **no longer does the same thing as `skip: undefined`**.  Instead of skipping zero results, it now refuses to run with an error.
  + Limit must be < Number.MAX_SAFE_INTEGER (...with one exception: for compatibility/convenience, `Infinity` is tolerated and normalized to `Number.MAX_SAFE_INTEGER` automatically.)
  + Skip must be < Number.MAX_SAFE_INTEGER


##### Change in support for mixed `where` clauses
Criteria dictionaries with a mixed `where` clause are no longer supported. For example, instead of:
```javascript
{
  username: 'santaclaus',
  limit: 4,
  select: ['beardLength', 'lat', 'long']
}
```
you should use:
```javascript
{
  where: { username: 'santaclaus' },
  limit: 4,
  select: ['beardLength', 'lat', 'long']
}
```
> Note that you can still do `{ username: 'santaclaus' }` as shorthand for `{ where: { username: 'santaclaus' } }`, you just can't mix other top-level criteria clauses (like `limit`) alongside constraints (e.g. `username`).
>
> For places where you're using Waterline's chainable deferred object to build criteria, don't worry about this&mdash;it's already taken care of for you.

### Security

New apps created with Sails 1.0 will contain a **config/security.js** file instead of individual **config/cors.js** and **config/csrf.js** files. Apps migrating from earlier versions can keep their existing files, as long as they perform the following upgrades:

* Change `module.exports.cors` to `module.exports.security.cors` in `config/cors.js`
* Change CORS config settings names to match the newly documented names in [Reference > Configuration > sails.config.security](https://sailsjs.com/documentation/reference/configuration/sails-config-security#?sailsconfigsecuritycors)
* Change `module.exports.csrf` to `module.exports.security.csrf` in `config/csrf.js`.  This value is now simply `true` or `false`; no other CSRF options are supported (see below).
* `sails.config.csrf.routesDisabled` is no longer supported. Instead, add `csrf: false` to any route in `config/routes.js` that you wish to be unprotected by CSRF, for example:

```js
'POST /some-thing': { action: 'do-a-thing', csrf: false },
```

* `sails.config.csrf.origin` is no longer supported. Instead, you can add any custom CORS settings directly to your CSRF token route configuration, for example:

```js
'GET /csrfToken': {
  action: 'security/grant-csrf-token',
  cors: {
    allowOrigins: ['http://foobar.com', 'https://owlhoot.com']
  }
}
```

* `sails.config.csrf.grantTokenViaAjax` is no longer supported.  This setting was used to turn the CSRF token-granting route on or off.  In Sails 1.0, you add that route manually in your `config/routes.js` file (see above). If you don&rsquo;t want to grant CSRF tokens via AJAX, just leave that route out of `config/routes.js`.

### Views

For maximum flexibility, Consolidate is no longer bundled with Sails.  If you are using a view engine besides EJS, you'll probably want to install Consolidate as a direct dependency of your app.  You can then configure the view engine in `config/views.js`, like so:

```javascript
extension: 'swig',
getRenderFn: function() {
  // Import `consolidate`.
  var cons = require('consolidate');
  // Return the rendering function for Swig.
  return cons.swig;
}
```

Adding custom configuration to your view engine is a lot easier in Sails 1.0:

```javascript
extension: 'swig',
getRenderFn: function() {
  // Import `consolidate`.
  var cons = require('consolidate');
  // Import `swig`.
  var swig = require('swig');
  // Configure `swig`.
  swig.setDefaults({tagControls: ['{?', '?}']});
  // Set the module that Consolidate uses for Swig.
  cons.requires.swig = swig;
  // Return the rendering function for Swig.
  return cons.swig;
}
```

Note that the [built-in support for layouts](https://sailsjs.com/documentation/concepts/views/layouts) still works for the default EJS views, but layout support for other view engines (e.g. Handlebars or Ractive) is not bundled with Sails 1.0.

### Resourceful PubSub

* Removed deprecated `backwardsCompatibilityFor0.9SocketClients` setting.
* Removed deprecated `.subscribers()` method.
* Removed deprecated "firehose" functionality.
* Removed support for 0.9.x socket client API.
* The following resourceful pubsub methods have also been removed:
  * `.publishAdd()`
  * `.publishCreate()`
  * `.publishDestroy()`
  * `.publishRemove()`
  * `.publishUpdate()`
  * `.watch()`
  * `.unwatch()`
  * `.message()`

In place of the removed methods, you should use the new `.publish()` method, or the low-level [sails.sockets](https://sailsjs.com/documentation/reference/web-sockets/sails-sockets) methods.  Keep in mind that unlike `.message()`, `.publish()` does _not_ wrap your data in an envelope containing the record ID, so&mdash;if it's important&mdash;you'll need to include the ID yourself as part of the data.  For example, in Sails v0.12.x, `User.message(123, {owl: 'hoot'})` would have resulted in the following notification being broadcasted to clients:

```
{
  verb: 'messaged',
  id: 123,
  data: {
    owl: 'hoot'
  }
}
```

By contrast, in Sails v1.0, `User.publish(123, {owl: 'hoot'})` will simply broadcast:
```
{
  owl: 'hoot'
}
```



### Replacing custom blueprints

Out of the box, it is no longer possible to add a file to `api/blueprints/` that will automatically be used as a blueprint action for all models.  However, this behavior can easily be replicated by installing [`sails-hook-custom-blueprints`](https://www.npmjs.com/package/sails-hook-custom-blueprints).



### Express 4

Sails 1.0 comes with an update to the internal Express server from version 3 to version 4 (thanks to some great work by [@josebaseba](http://github.com/josebaseba)).  This change is mainly about maintainability for the Sails framework and should be transparent to your app.  However, there are a couple of differences worth noting:

* The `404`, `500` and `startRequestTimer` middleware are now built-in to every Sails app, and have been removed from the `sails.config.http.middleware.order` array.  If your app has an overridden `404` or `500` handler, you should instead override `api/responses/notFound.js` and `api/responses/serverError.js` respectively.
* Session middleware that was designed specifically for Express 3 (e.g. very old versions of `connect-redis` or `connect-mongo`) will no longer work, so you&rsquo;ll need to upgrade to more recent versions.
* The `sails.config.http.customMiddleware` feature is deprecated in Sails 1.0.  It will still work for now, but may be removed in a later release.  Instead of using `customMiddleware` to modify the Express app directly, use regular (`req`, `res`, `next`) middleware instead.  For instance, you can replace something like:

```
customMiddleware: function(app) {
  var passport = require('passport');
  app.use(passport.initialize());
  app.use(passport.session());
}
```

with something like:
```
var passport = require('passport');
middleware: {
  passportInit: passport.initialize(),
  passportSession: passport.session()
},
```
being sure to insert `passportInit` and `passportSession` into your `middleware.order` array in `config/http.js`.

### Response methods
 * `.jsonx()` is deprecated. If you have files in `api/responses` that you haven't customized at all, you can just delete them and let the Sails default responses work their magic.  If you have files in `api/responses` that you&rsquo;d like to keep, replace any occurences of `res.jsonx()` in those files with `res.json()`.
 * `res.negotiate()` is deprecated. Use `res.serverError()`, `res.badRequest()`, or a [custom response](https://sailsjs.com/documentation/concepts/extending-sails/custom-responses) instead.


### i18n

Sails 1.0 switches from using the [i18n](http://npmjs.org/package/i18n) to the lighter-weight [i18n-2](http://npmjs.org/package/i18n-2) module.  The overwhelming majority of users should see no difference in their apps.  However, if you&rsquo;re using the `sails.config.i18n.updateFiles` option, be aware that this is no longer supported; instead, locale files will _always_ be updated in development mode, and _never_ in production mode.  If this is a problem or you&rsquo;re missing some other feature from the i18n module, you can install [sails-hook-i18n](http://npmjs.org/package/sails-hook-i18n) to revert to pre-Sails-1.0 functionality.

> If your 0.12 application is running into issues during upgrade due to its use of i18n features, see [#4343](https://github.com/balderdashy/sails/issues/4343) for more troubleshooting tips.

### WebSockets

All Sails 1.0 projects that use websockets must install the latest `sails-hook-sockets` dependency (`npm install --save sails-hook-sockets`).  This version of `sails-hook-sockets` differs from previous ones in a couple of ways:

* The default `transports` setting is simply `['websocket']`.  In the majority of production deployments, restricting your app to the `websocket` transport (rather than using `['polling', 'websocket']`) avoids problems with sessions (see the pre-1.0 [scaling guide notes](https://github.com/balderdashy/sails-docs/blob/1038b38cb34fd945086480ee45325a1ac95a0950/concepts/Deployment/Scaling.md#notes) for details).  If you&rsquo;re using the `sails.io.js` websocket client, the easiest way to make your app compatible with the new websocket settings is to install the new `sails.io.js` version with `sails generate sails.io.js`.  The latest version of that package also defaults to the &ldquo;websocket-only&rdquo; transport strategy.  If you&rsquo;ve customized the `transports` setting in your front-end code and `config/sockets.js` file, then you'll just need to continue to ensure that the values in both places match.
* The latest `sails-hook-sockets` hook uses a newer version of Socket.io.  See the [Socket.io changelog](https://github.com/socketio/socket.io/blob/master/History.md#150--2016-10-06) for a full update, but keep in mind that socket IDs no longer have `/#` prepended to them by default.

### Grunt

The Grunt task-management functionality that was formerly part of the Sails core has now been moved into the separate `sails-hook-grunt` module.  Existing apps simply need to `npm install --save sails-hook-grunt` to continue using Grunt.  However, with a modification to your app&rsquo;s `Gruntfile.js`, you can take advantage of the fact that `sails-hook-grunt` includes all of the `grunt-contrib` modules that previously had to be installed at the project level.  The new `Gruntfile.js` contains:

```
module.exports = function(grunt) {

  var loadGruntTasks = require('sails-hook-grunt/accessible/load-grunt-tasks');

  // Load Grunt task configurations (from `tasks/config/`) and Grunt
  // task registrations (from `tasks/register/`).
  loadGruntTasks(__dirname, grunt);

};
```

Assuming that you haven&rsquo;t customized the Gruntfile in your app, you can replace `Gruntfile.js` with that code and then safely run:

```
npm uninstall --save grunt-contrib-clean
npm uninstall --save grunt-contrib-coffee
npm uninstall --save grunt-contrib-concat
npm uninstall --save grunt-contrib-copy
npm uninstall --save grunt-contrib-cssmin
npm uninstall --save grunt-contrib-jst
npm uninstall --save grunt-contrib-less
npm uninstall --save grunt-contrib-uglify
npm uninstall --save grunt-contrib-watch
npm uninstall --save grunt-sails-linker
npm uninstall --save grunt-sync
npm uninstall --save grunt-cli
```

to remove those dependencies from your project.


### Troubleshooting


##### Still displaying v0.12 at launch?

Make sure you have `sails` installed locally in your project, and that you're using the v1 version of the command-line tool.

To install the v1.0 globally, run `npm install sails@^1.0.0 -g`. To install it for a particular Sails app, cd into that app's directory, then run `npm install sails@^1.0.0 --save`.  (After installing locally, be sure to also install the necessary hooks -- see above.)



<docmeta name="displayName" value="To v.1.0">
<docmeta name="version" value="1.0.0">

---

### Upgrading Upgrading (`docs/upgrading/upgrading.md`)

# Upgrading

Like most Node packages, Sails respects [semantic versioning](http://semver.org/).  For example, if you are using Sails v0.11.3, and then upgrade to Sails v0.11.4, you shouldn't need to change your application code.  This is called a **patch release**.  On the other hand, if you upgrade from Sails v0.11.3 to v1.0.0, you can expect some _breaking changes_, meaning that you will need to change your Sails app's code in order to use the new version.  With any framework or tool, _some_ breaking changes are inevitable over time, but you can expect to see these kinds of changes less often as the APIs in Node and Sails continue to stabilize.  In the meantime, the core maintainers strive to minimize breaking changes and maintain backwards compatibility where possible.

### Version notes

For details about changes between versions, as well as a migration guide to assist you in making an necessary changes to your app, please refer to the appropriate page:

- [v1.x](https://sailsjs.com/documentation/upgrading/to-v-1-0)
- [v0.12.x](https://sailsjs.com/documentation/concepts/upgrading/to-v-0-12)
- [v0.11.x](https://sailsjs.com/documentation/concepts/upgrading/to-v-0-11)
- [v0.10.x](https://sailsjs.com/documentation/concepts/upgrading/to-v-0-10)


### Notes

> - Like Node.js, minor version bumps in Sails versions prior to v1.0 included breaking changes&mdash;e.g. upgrading from v0.11.3 to v0.12.0 might force you to make some changes to your code.  But from v1.0.0 and on, minor version (the second number) releases should be fully backwards compatible.  For example, v1.1.0 to v1.2.0 should not force you to make changes to your code, whereas upgrading to v2.0.0 might.
> - If you are more than one version behind the latest release and run into difficulties, consider updating your app one step at a time. The migration guides are written with a particular version diff in mind, and it's best to isolate as many variables as possible.  For instance, if you are running Sails v0.11 and trying to upgrade to Sails v1.5.18 but having trouble, try first upgrading to Sails v0.11, then v0.12, _then_ v1.5.18.


<docmeta name="displayName" value="Upgrading">
<docmeta name="isOverviewPage" value="true">

---

### Anatomy Api Api (`docs/anatomy/api/api.md`)

# api/

This folder contains the vast majority of your app's back-end logic.  It is home to the 'M' and 'C' in <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC Framework</a>.

In it you will find the following:

- Controllers: [Actions](https://sailsjs.com/documentation/concepts/actions-and-controllers) contain back-end logic that handle incoming requests (like handling a form submission or responding with personalized, server-rendered HTML).
- Helpers: [Helpers](https://sailsjs.com/documentation/concepts/helpers) are shared functions that can be called from anywhere in your app.
- Models: [Models](https://sailsjs.com/documentation/concepts/models-and-orm) are the structures that contain data for your Sails App.
- Policies: [Policies](https://sailsjs.com/documentation/concepts/policies) are middleware that restrict access to certain actions in your app.

You may also find these folders, which are not always generated by default in new Sails apps:

- Hooks: [Hooks](https://sailsjs.com/documentation/concepts/extending-sails/hooks) are modules that add functionality to Sails core.  You can use hooks to run custom code when your app lifts and before handling every incoming request.  Hooks can also be installed as plugins, but the hooks in this folder are always custom for your application.
- Responses: [Custom responses](https://sailsjs.com/documentation/concepts/extending-sails/custom-responses) can help maintain consistent HTTP status codes and behavior across your app.  (Since not every Sails application needs to define its own custom responses, this folder is sometimes excluded.)
- Services: [Services](https://sailsjs.com/documentation/concepts/services) are shared utilities common in Sails apps written before version 1.0.  They can be _just about anything_, so for new apps, it's recommended that you use [helpers](https://sailsjs.com/documentation/concepts/helpers) instead.


<docmeta name="displayName" value="api">

---

### Anatomy Assets .Eslintrc (`docs/anatomy/assets/.eslintrc.md`)

# assets/.eslintrc

This file is for [ESLint](https://eslint.org/) configuration overrides for  the `assets/` directory.

These override the code conventions defined in the top-level [`.eslintrc`](https://sailsjs.com/documentation/anatomy/.eslintrc), to allow for variations between front-end JavaScript code vs. backend code designed to run in a Node.js/Sails process.

<docmeta name="displayName" value=".eslintrc">

---

### Anatomy Assets Assets (`docs/anatomy/assets/assets.md`)

# assets/

This is your assets folder.  It houses all of the static files that your app will need to host.  Feel free to create your own files and folders in here.  Upon lifting, a file called `assets/newFolder/data.txt` could be accessed at `http://localhost:1337/newFolder/data.txt`.



<docmeta name="displayName" value="assets">

---

### Anatomy Assets Favicon.Ico (`docs/anatomy/assets/favicon.ico.md`)

# assets/favicon.ico

This file is the [Favicon](http://en.wikipedia.org/wiki/Favicon) for your app.


<docmeta name="displayName" value="favicon.ico">

---

### Anatomy Config Blueprints.Js (`docs/anatomy/config/blueprints.js.md`)

# config/blueprints.js

This file is for the configuration of blueprint routes and actions.

For an overview of blueprints, see the [main Blueprints API concepts docs](https://sailsjs.com/documentation/concepts/blueprints).  For more information on configuring the blueprint API, check out the [reference documentation on blueprints](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints).

### Usage

See [`sails.config.blueprints`](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints) for all available options.



<docmeta name="displayName" value="blueprints.js">

---

### Anatomy Config Bootstrap.Js (`docs/anatomy/config/bootstrap.js.md`)

# config/bootstrap.js

This is a server-side JavaScript file that is executed by Sails just before your app is lifted.

This gives you an opportunity to set up your data model, run jobs, or perform some special logic.

### Usage

See [`sails.config.bootstrap`](https://sailsjs.com/documentation/reference/configuration/sails-config-bootstrap) for more info.

<docmeta name="displayName" value="bootstrap.js">

---

### Anatomy Config Config (`docs/anatomy/config/config.md`)

# config/

This folder contains various files that will allow you to customize and configure your Sails app.



<docmeta name="displayName" value="config">

---

### Anatomy Config Custom.Js (`docs/anatomy/config/custom.js.md`)

# config/custom

This is your custom configuration file. It is useful for one-off settings specific to your application-- like your base URL for linkbacks, the no-reply "From" address to use when sending automated emails, or 3rd party API keys for Stripe, Mailgun, Twilio, etc.

> Use [`sails.config.custom`](https://sailsjs.com/documentation/reference/application/sails-config-custom) to access these values from your actions and helpers.

You can learn more about custom configuration [here](https://sailsjs.com/documentation/reference/configuration/sails-config-custom).


<docmeta name="displayName" value="custom.js">

---

### Anatomy Config Datastores.Js (`docs/anatomy/config/datastores.js.md`)

# config/datastores

A set of datastore configurations which tell Sails where to fetch or save data when you execute built-in model methods like `.find()` and `.create()`.

> This file is mainly useful for configuring your development database, as well as any additional one-off databases used by individual models.

### Usage

See [`sails.config.datastores`](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores) for all available options.

<docmeta name="displayName" value="datastores.js">

---

### Anatomy Config Globals.Js (`docs/anatomy/config/globals.js.md`)

# config/globals.js

Configuration for the global variables Sails exposes to its Node process.

### Usage

See [`sails.config.globals`](https://sailsjs.com/documentation/reference/configuration/sails-config-globals) for all available options.


<docmeta name="displayName" value="globals.js">

---

### Anatomy Config Http.Js (`docs/anatomy/config/http.js.md`)

# config/http.js

This file is for configuring the underlying HTTP server in Sails, as well as any HTTP middleware your app may need.

### Usage

See [`sails.config.http`](https://sailsjs.com/documentation/reference/configuration/sails-config-http) for all available options.

<docmeta name="displayName" value="http.js">

---

### Anatomy Config I18n.Js (`docs/anatomy/config/i18n.js.md`)

# config/i18n.js

This file contains your Sails app's internationalization settings.

### Usage

See [`sails.config.i18n`](https://sailsjs.com/documentation/reference/configuration/sails-config-i-18-n) for all available options.

<docmeta name="displayName" value="i18n.js">

---

### Anatomy Config Local.Js (`docs/anatomy/config/local.js.md`)

# config/local.js

This file is used to specify configuration settings for use while developing the app on your personal system.

For more information, check out [Concepts > Configuration > The local.js file](https://sailsjs.com/docs/concepts/configuration/the-local-js-file)

> Since `config/local.js` is usually used to store sensitive credentials, it is included in your app's [.gitignore](https://sailsjs.com/documentation/anatomy/.gitignore), and isn't pushed to the remote server. If you click the link to this file below, you should see a 404 page; in this case, that's a _good_ thing!

<docmeta name="displayName" value="local.js">

---

### Anatomy Config Log.Js (`docs/anatomy/config/log.js.md`)

# config/log.js

This file contains the logger configuration for your Sails app.

Configure the log level for your app, as well as the transport.

Underneath the covers, Sails uses Winston for logging, which allows for some pretty neat custom transports/adapters for log messages.

### Usage

See [`sails.config.log`](https://sailsjs.com/documentation/reference/configuration/sails-config-log) for all available options.

<docmeta name="displayName" value="log.js">

---

### Anatomy Config Models.Js (`docs/anatomy/config/models.js.md`)

# config/models.js

Unless you override them, the properties contained in this file will be included in each of your models.

### Usage

See [`sails.config.models`](https://sailsjs.com/documentation/reference/configuration/sails-config-models) for all available options.

<docmeta name="displayName" value="models.js">

---

### Anatomy Config Policies.Js (`docs/anatomy/config/policies.js.md`)

# config/policies.js

This file contains the default policies for your app.

Policies are simply Express middleware functions which run before your controllers. You can apply one or more policies to a given controller, or protect just one of it's actions. Any policy file (e.g. `api/policies/isLoggedIn.js`) can be dropped into the `api/policies/` folder, at which point it can be accessed by it's filename, minus the extension, (e.g. `isLoggedIn`).

### Usage

See [`sails.config.policies`](https://sailsjs.com/documentation/reference/configuration/sails-config-policies) for all available options.

<docmeta name="displayName" value="policies.js">

---

### Anatomy Config Routes.Js (`docs/anatomy/config/routes.js.md`)

# config/routes.js

This file contains custom routes.  Sails uses these routes to determine what to do each time it receives a request.

If Sails receives a URL that doesn't match any of the [custom routes](https://sailsjs.com/documentation/concepts/routes/custom-routes) in this file, it will check for matching [assets](https://sailsjs.com/documentation/concepts/assets) (images, scripts, stylesheets, etc.). Finally, if those don't match either, the [default 404 handler](https://sailsjs.com/documentation/reference/response-res/res-not-found) is triggered.

When you first generate your Sails app, there is only one route in this file.  Its job is to serve the home page.

You'll probably want to add some more.

> Sails also injects _shadow routes_, or implicit routes that handle certain kinds of requests behind the scenes.  For more information about these kinds of routes, see **[Concepts > Blueprints](https://sailsjs.com/documentation/concepts/blueprints)**.

### Usage

See [`sails.config.routes`](https://sailsjs.com/documentation/reference/configuration/sails-config-routes) for all available options.

<docmeta name="displayName" value="routes.js">

---

### Anatomy Config Security.Js (`docs/anatomy/config/security.js.md`)

# config/security.js

This file is the conventional home of your Sails app's global security settings.  For a complete reference of available security configuration in Sails, see:

* CORS settings reference: [sails.config.security.cors](https://sailsjs.com/documentation/reference/configuration/sails-config-security-cors)
* CSRF settings reference: [sails.config.security.csrf](https://sailsjs.com/documentation/reference/configuration/sails-config-security-csrf)

For a conceptual explanation of CORS in Sails, see [Security > CORS](https://sailsjs.com/documentation/concepts/security/cors).

For a conceptual explanation of CSRF in Sails, see [Security > CSRF](https://sailsjs.com/documentation/concepts/security/csrf).

### Usage

See [`sails.config.security`](https://sailsjs.com/documentation/reference/configuration/sails-config-security) for all available options.


<docmeta name="displayName" value="security.js">

---

### Anatomy Config Session.Js (`docs/anatomy/config/session.js.md`)

# config/session.js

This file contains information that tells Sails where to store your sessions.

Sails session integration leans heavily on the great work already done by Express, but also unifies socket.io with the Connect session store. It uses Connect's cookie parser to normalize configuration differences between Express and socket.io and hooks into Sails' middleware interpreter to allow you to access and auto-save to `req.session` with Socket.io the same way you would with Express.

This is where you would go to configure a different session store like Redis or Mongo.  In this file you will find commented examples of what that configuration should look like.

This file also contains your 'Session Secret' that is generated by Sails when you create your app.  Do not change or remove this unless you really know what you are doing.

### Usage

See [`sails.config.session`](https://sailsjs.com/documentation/reference/configuration/sails-config-session) for all available options.


<docmeta name="displayName" value="session.js">

---

### Anatomy Config Sockets.Js (`docs/anatomy/config/sockets.js.md`)

# config/sockets.js

This is a configuration file that allows you to customize the way your app talks to clients over Socket.IO.

It provides transparent access to Sails' encapsulated pubsub/socket server for complete customizability. In it you can do things on the list below (and more!).

- Override afterDisconnect function (server side)
- Define custom authorization logic for client socket connections
- Set transport method
- Change Heartbeat Interval
- Change socket store

### More Info
> Socket.IO configuration options can be found [here](https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO).

### Usage

See [`sails.config.sockets`](https://sailsjs.com/documentation/reference/configuration/sails-config-sockets) for all available options.


<docmeta name="displayName" value="sockets.js">

---

### Anatomy Config Views.Js (`docs/anatomy/config/views.js.md`)

# config/views.js

This file is where Sails looks to find out which templating engine to use when rendering server side HTML templates.  By default Sails uses ejs, but any view engine can be used by changing the `extension` and supplying a `getRenderFn` value (see the [view engine documentation](https://sailsjs.com/documentation/concepts/views/view-engines) for more info).

### Usage

See [`sails.config.views`](https://sailsjs.com/documentation/reference/configuration/sails-config-views) for all available options.

<docmeta name="displayName" value="views.js">

---

### Anatomy Tasks Pipeline.Js (`docs/anatomy/tasks/pipeline.js.md`)

# tasks/pipeline.js

The `pipeline.js` file in your Sails app determines the order in which your stylesheets,
JavaScript, and client-side template files should be compiled and linked as `<script>`
or `<link>` tags.

If you are not relying on [automatic asset linking](https://sailsjs.com/documentation/concepts/assets/task-automation#?asset-pipeline), then you can safely ignore this file.

> Note that you can take advantage of Grunt-style wildcard/glob/splat expressions for matching multiple files, and use `!` in front of an expression to ignore files.


<docmeta name="displayName" value="pipeline.js">

---

### Anatomy Tasks Tasks (`docs/anatomy/tasks/tasks.md`)

# tasks/

The `tasks/` directory is a suite of Grunt tasks and their configurations, bundled for your convenience.  The Grunt integration is mainly useful for bundling front-end assets (like stylesheets, scripts and markup templates), but it can also be used to run all kinds of development tasks, from browserify compilation to database migrations.

If you haven't used [Grunt](http://gruntjs.com/) before, that's OK!  For many common use cases, you can get by without customizing or even looking at the files in this folder.  If you do need to customize something, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains basic concepts like the [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as how to install and use Grunt plugins. Once you're familiar with that process, read on!


### How does this work?

The asset pipeline bundled in Sails is a set of Grunt tasks configured with conventional defaults designed to make your project more consistent and productive.

The entire front-end asset workflow in Sails is completely customizable-- while it provides some suggestions out of the box, Sails makes no pretense that it can anticipate all of the needs you'll encounter building the browser-based/front-end portion of your application.  Who's to say you're even building an app for a browser?


### What tasks does Sails run automatically?

Sails runs some of these tasks (certain ones in the `tasks/register/` folder) automatically when you run certain commands.

###### `sails lift`

Runs the `default` task (`tasks/register/default.js`).

###### `sails lift --prod`

Runs the `prod` task (`tasks/register/prod.js`).

###### `sails www`

Runs the `build` task (`tasks/register/build.js`).

###### `sails www --prod` (production)

Runs the `buildProd` task (`tasks/register/buildProd.js`).


### Can I customize this for SASS, Angular, client-side Jade templates, etc?

You can modify, omit, or replace any of these Grunt tasks to fit your requirements. You can also add your own Grunt tasks- just add a `someTask.js` file in the `grunt/config` directory to configure the new task, then register it with the appropriate parent task(s) (see files in `grunt/register/*.js`).


### Do I have to use Grunt?

Nope!  The Sails core team has used Grunt on real-world projects for upwards of 4 years now, and overall it's been a fantastic tool.  But we realize it's not for everyone.  To disable Grunt integration in Sails, just delete your Gruntfile or [disable the Grunt hook](https://sailsjs.com/documentation/concepts/assets/disabling-grunt).

> You can also [generate a new Sails app `--without=grunt`](https://sailsjs.com/documentation/reference/command-line-interface/sails-new).


### What if I'm not building a web frontend?

That's ok! A core tenant of Sails is client-agnosticism-- it's especially designed for building APIs used by all sorts of clients; native Android/iOS/Cordova, serverside SDKs, etc.

You can completely disable Grunt by following the instructions [here](https://sailsjs.com/documentation/concepts/assets/disabling-grunt).

If you still want to use Grunt for other purposes, but don't want any of the default web front-end stuff, just delete your project's `assets` folder and remove the front-end oriented tasks from the `grunt/register` and `grunt/config` folders.  You can also run `sails new myCoolApi --no-frontend` to omit the `assets` folder and front-end-oriented Grunt tasks for future projects.  You can also replace your `sails-generate-frontend` module with alternative community generators, or create your own.  This allows `sails new` to create the boilerplate for native iOS apps, Android apps, Cordova apps, SteroidsJS apps, etc.

> If you know you'll _never_ need any kind of web frontend, you can also [generate a new Sails app with `--no-frontend` at all](https://sailsjs.com/documentation/reference/command-line-interface/sails-new).


### More info

> More information on using Grunt to work with static assets: http://gruntjs.com/configuring-tasks



<docmeta name="displayName" value="tasks">

---

### Anatomy Views .Eslintrc (`docs/anatomy/views/.eslintrc.md`)

# views/.eslintrc

This file overrides your Sails app's top-level [ESLint](https://eslint.org/) configuration, specifically for the `views/` directory.  It simply extends [`assets/.eslintrc`](https://sailsjs.com/documentation/anatomy/assets/.eslintrc), but omits the `eol-last` rule.

Certain CI environments, build systems, IDEs, and syntax-highlighting plugins for text editors run ESLint checks on inline `<script>` tags in HTML files to help catch common mistakes.  Which is great-- except that not all of these tools are quite smart enough to understand that each `<script>` tag isn't a separate JavaScript file.  And unfortunately, that can cause some weird issues when `eol-last` is enabled.

Luckily, all it takes to disable the `eol-last` rule for these inline `<script>` tags is to include this `.eslintrc` file in the `views/` directory (which Sails does by default).

<docmeta name="displayName" value=".eslintrc">

---

### Anatomy Views 404.Ejs (`docs/anatomy/views/404.ejs.md`)

# views/404.ejs

This is the default "404: Not Found" page. User agents that don't "Accept" HTML will see a JSON version instead. You can customize the control logic for your needs in `config/404.js`.

Sails considers a request to be in a "404: Not Found" state when a user requests a URL which doesn't match any of your app's routes or blueprints. You can also trigger this response from one of your controllers or policies with: `return res.notFound();`

<docmeta name="displayName" value="404.ejs">

---

### Anatomy Views 500.Ejs (`docs/anatomy/views/500.ejs.md`)

# views/500.ejs

This is the default "500: Server Error" page. User agents that don't "Accept" HTML will see a JSON version instead.

You can customize the control logic for your needs in `config/500.js` Sails considers a request in a "500: Server Error" state when your app throws a catchable error (not inside of an asynchronous callback).

You can also trigger this response from one of your controllers or policies with: `return res.serverError( e );` (where `e` is an optional message, error, or array of errors to include in the response).

<docmeta name="displayName" value="500.ejs">

---

### Anatomy Views Views (`docs/anatomy/views/views.md`)

# views/

This is the directory that holds all of your custom views.

To create a custom view, create a new directory inside of this then create a new .ejs file.  In order for it to be rendered by a client, you must either set up a route in `config/routes.js` or use the `res.view()` method inside of a custom controller action.



<docmeta name="displayName" value="views">

---

### Concepts ActionsAndControllers ActionsAndControllers (`docs/concepts/ActionsAndControllers/ActionsAndControllers.md`)

# Actions and controllers

### Overview

_Actions_ are responsible for responding to *requests* from a web browser, mobile application or any other system capable of communicating with a server.  They often act as a middleman between your [models](https://sailsjs.com/documentation/concepts/models-and-orm) and [views](https://sailsjs.com/documentation/concepts/views), and orchestrate the bulk of your project&rsquo;s [business logic](http://en.wikipedia.org/wiki/Business_logic): you can use actions to serve web pages, handle form submissions, manage 3rd party API requests, and everything in between.

Actions are bound to [routes](https://sailsjs.com/documentation/concepts/Routes) in your application. When a user agent requests a particular URL, the action bound to that route performs the business logic within and sends back a response.  For example, the `GET /hello` route in your application could be bound to an action like:

```javascript
async function (req, res) {
  return res.send('Hi there!');
}
```

Any time a web browser navigates to the `/hello` URL on your app's server, the page will display the message: &ldquo;Hi there!&rdquo;.

### Defining your action
Actions are defined in the `api/controllers/` folder and subfolders (we&rsquo;ll talk more about _controllers_ in a bit). In order for Sails to recognize a file as an action, the filename must be _kebab-cased_ (containing only lowercase letters, numbers and dashes).  When referencing an action in Sails (in most cases, when [binding it to a route](https://sailsjs.com/documentation/concepts/routes/custom-routes#?action-target-syntax)), use its path relative to `api/controllers`, without any file extension.  For example, to bind a route to an action located at `api/controllers/user/find.js`, you would point its URL to `user/find`.

##### File extensions for actions

By default, Sails only knows how to interpret `.js` files, but you can customize your app to use things like [CoffeeScript](https://sailsjs.com/documentation/tutorials/using-coffee-script) or [TypeScript](https://sailsjs.com/documentation/tutorials/using-type-script) as well. An action can have any file extension that isn't `.md` (Markdown) and `.txt` (text).

### Creating an action

Action files can use one of two formats: _actions2_ (recommended) or _classic_.

##### actions2

Since the release of Sails v1.0, we recommend writing your actions in the more modern "actions2" syntax, which works much the same way as Sails [helpers](https://sailsjs.com/documentation/concepts/helpers). By defining your actions in this way, they are essentially self-documenting and self-validating.

Using actions2 provides several advantages:

+ You can use [`sails generate action`](https://sailsjs.com/documentation/reference/command-line-interface/sails-generate) to quickly create an actions2 file
+ You can clearly define the names and types of the request parameters the action expects, and those parameters will be automatically validated before the action is run
+ All of the possible outcomes of running the action (`exits`) are clearly visible, without the need to dissect the code
+ The code you write is not directly dependent on `req` and `res`, making it easier to re-use or abstract into a [helper](https://sailsjs.com/documentation/concepts/helpers)
> Note that when using actions2, you can access the [request object](https://sailsjs.com/documentation/reference/request-req) as `this.req`.</br>Alternatively, you can pass `env` into the function with `inputs` and `exits` to get access to `req` without using `this.req`.

In a nutshell, your code will be standardized in a way that makes it easier to re-use and modify later.  And since you'll declare the action's parameters ahead of time, you'll be much less likely to expose edge cases and security holes.

Here's an example of the actions2 format:

```javascript
module.exports = {

  friendlyName: 'Welcome user',

  description: 'Look up the specified user and welcome them, or redirect to a signup page if no user was found.',

  inputs: {
    userId: {
      description: 'The ID of the user to look up.',
      // By declaring a numeric example, Sails will automatically respond with `res.badRequest`
      // if the `userId` parameter is not a number.
      type: 'number',
      // By making the `userId` parameter required, Sails will automatically respond with
      // `res.badRequest` if it's left out.
      required: true
    }
  },

  exits: {
    success: {
      responseType: 'view',
      viewTemplatePath: 'pages/welcome'
    },
    notFound: {
      description: 'No user with the specified ID was found in the database.',
      responseType: 'notFound'
    }
  },

  fn: async function ({userId}) {

    // Look up the user whose ID was specified in the request.
    // Note that we don't have to validate that `userId` is a number;
    // the machine runner does this for us and returns `badRequest`
    // if validation fails.
    var user = await User.findOne({ id: userId });

    // If no user was found, respond "notFound" (like calling `res.notFound()`)
    if (!user) { throw 'notFound'; }

    // Display a personalized welcome view.
    return {
      name: user.name
    };
  }
};
```

> Sails uses the [machine-as-action](https://github.com/treelinehq/machine-as-action) module to automatically create route-handling functions out of actions formatted like the example above.  See the [machine-as-action docs](https://github.com/treelinehq/machine-as-action#customizing-the-response) for more information.

###### Exit signals

In an action, helper, or script, throwing anything will trigger the `error` exit by default. If you want to trigger any other exit, you can do so by throwing a "special exit signal". This will either be a string (the name of the exit), or an object with the name of the exit as the key and the output data as the value.
For example, instead of the usual syntax:

```javascript
return exits.hasConflictingCourses();
```

You could use the shorthand:

```javascript
throw 'hasConflictingCourses';
```

Or, to include output data:

```javascript
throw { hasConflictingCourses: ['CS 301', 'M 402'] };
```

Aside from being an easy-to-read shorthand, exit signals are especially useful if you're inside of a `for` loop, `forEach`, etc., but still want to exit through a particular exit.


##### Classic actions

If you're working with an existing codebase or an app that was upgraded from v0.12, you may be more used to the classic action format. Classic actions are declared as functions with `req` and `res` arguments. When a client requests a route bound to this type of action, the function runs using the [incoming request object](https://sailsjs.com/documentation/reference/request-req) as the first argument (`req`), and the [outgoing response object](https://sailsjs.com/documentation/reference/response-res) as the second argument (`res`).

Here's a sample action that looks up a user by ID, then either displays a "welcome" view or redirects to a signup page if the user can't be found:

```javascript
module.exports = async function welcomeUser (req, res) {

  // Get the `userId` parameter from the request.
  // This could have been set on the querystring, in
  // the request body, or as part of the URL used to
  // make the request.
  var userId = req.param('userId');

   // If no `userId` was specified, or it wasn't a number, return an error.
  if (!_.isNumeric(userId)) {
    return res.badRequest(new Error('No user ID specified!'));
  }

  // Look up the user whose ID was specified in the request.
  var user = await User.findOne({ id: userId });

  // If no user was found, redirect to signup.
  if (!user) {
    return res.redirect('/signup' );
  }

  // Display the welcome view, setting the view variable
  // named "name" to the value of the user's name.
  return res.view('welcome', {name: user.name});

}
```

> You can use [`sails generate action`](https://sailsjs.com/documentation/reference/command-line-interface/sails-generate) with `--no-actions2` to quickly create a classic action.


### Controllers

For simpler projects and prototypes, often the quickest way to get started writing Sails apps is to organize your actions into _controller files_.  A controller file is a [_PascalCased_](https://en.wikipedia.org/wiki/PascalCase) file whose name must end in `Controller`, containing a dictionary of actions.  For example, a  "User Controller" could be created at `api/controllers/UserController.js` file containing:

```javascript
module.exports = {
  login: function (req, res) { ... },
  logout: function (req, res) { ... },
  signup: function (req, res) { ... },
};
```

You can use [`sails generate controller`](https://sailsjs.com/documentation/reference/command-line-interface/sails-generate#?sails-generate-controller-foo-action-1-action-2) to quickly create a controller file.

##### File extensions for controllers

Just like with action files, you can customize your app to use things like [CoffeeScript](https://sailsjs.com/documentation/tutorials/using-coffee-script) or [TypeScript](https://sailsjs.com/documentation/tutorials/using-type-script), although Sails only knows how to interpret `.js` files by default. A controller can have any file extension besides `.md` (Markdown) and `.txt` (text).


### Standalone actions

For larger, more mature apps, _standalone actions_ may be a better approach than controller files.  In this scheme, rather than having multiple actions living in a single file, each action is in its own file in an appropriate subfolder of `api/controllers`.  For example, the following file structure would be equivalent to the  `UserController.js` file:

```
api/
 controllers/
  user/
   login.js
   logout.js
   signup.js
```

Using standalone actions has several advantages over controller files:

+ It's easier to see a clear overview of the actions in your app, because you can reference your project's file structure instead of scanning through individual controller files
+ Each action file is smaller and easy to maintain, whereas controller files tend to grow as your app grows
+ [Routing to standalone actions](https://sailsjs.com/documentation/concepts/routes/custom-routes#?action-target-syntax) in nested subfolders is more intuitive than routing to actions in controller files (`foo/bar/baz.js` vs. `foo/BarController.baz`)
+ Blueprint index routes apply to top-level standalone actions, so you can create an `api/controllers/index.js` file and have it automatically bound to your app&rsquo;s `/` route (as opposed to creating an arbitrary controller file to hold the root action)


### Keeping it lean

In the tradition of most MVC frameworks, mature Sails apps usually have "thin" controllers&mdash;that is, your action code ends up lean because reusable code has been moved into [helpers](https://sailsjs.com/documentation/concepts/helpers) or occasionally even extracted into separate node modules.  This approach can definitely make your app easier to maintain as it grows in complexity.

But at the same time, extrapolating code into reusable helpers _too_ early can cause maintenance issues that waste time and productivity.  The right answer lies somewhere in the middle.

Sails recommends this general rule of thumb:  **wait until you're about to use the same piece of code for the _third_ time before you extrapolate it into a separate helper.**  But, as with any dogma, use your judgement!  If the code in question is very long or complex, then it might make sense to pull it out into a helper much sooner.  Conversely, if you know what you're building is a quick, throwaway prototype, you might just copy and paste the code to save time.

> Whether you're developing for passion or profit, at the end of the day, the goal is to make the best possible use of your time as an engineer.  Some days that means getting more code written, and other days it means looking out for the long-term maintainability of the project.  If you're not sure which of these goals is more important at your current stage of development, you might take a step back and give it some thought (better yet, have a chat with the rest of your team or [other folks building apps on Node.js/Sails](https://sailsjs.com/support)).

<docmeta name="displayName" value="Actions and controllers">
<docmeta name="nextUpLink" value="/documentation/concepts/views">
<docmeta name="nextUpName" value="Views">

---

### Concepts ActionsAndControllers GeneratingActions (`docs/concepts/ActionsAndControllers/GeneratingActions.md`)

# Generating controllers or standalone actions

You can use [`sails-generate`](https://sailsjs.com/documentation/reference/command-line-interface/sails-generate) from the Sails command line tool to quickly generate a controller, or even just an individual action.


### Generating controllers

For example, to generate a controller:

```sh
$ sails generate controller user
```

Sails will generate `api/controllers/UserController.js`:

```javascript
/**
 * UserController.js
 *
 * @description :: Server-side controller action for managing users.
 * @help        :: See https://sailsjs.com/documentation/concepts/controllers
 */
module.exports = {

}
```

### Generating standalone actions

Run the following command to generate a standalone action:

```sh
$ sails generate action user/signup
info: Created an action!
Using "actions2"...
[?] https://sailsjs.com/docs/concepts/actions
```

Sails will create `api/controllers/user/sign-up.js`:

```javascript
/**
 * user/sign-up.js
 *
 * @description :: Server-side controller action for handling incoming requests.
 * @help        :: See https://sailsjs.com/documentation/concepts/controllers
 */
module.exports = {


  friendlyName: 'Sign up',


  description: '',


  inputs: {

  },


  exits: {

  },


  fn: function (inputs, exits) {

    return exits.success();

  }


};

```


Or, using the [classic actions](https://sailsjs.com/documentation/concepts/actions-and-controllers#?classic-actions) interface:


```sh
$ sails generate action user/signup --no-actions2
info: Created a traditional (req,res) controller action, but as a standalone file
```

Sails will create `api/controllers/user/sign-up.js`:

```javascript
/**
 * Module dependencies
 */

// ...


/**
 * user/signup.js
 *
 * Signup user.
 */
module.exports = function signup(req, res) {

  sails.log.debug('TODO: implement');
  return res.ok();

};
```




<docmeta name="displayName" value="Generating actions and controllers">

---

### Concepts ActionsAndControllers RoutingToActions (`docs/concepts/ActionsAndControllers/RoutingToActions.md`)

# Routing to actions

### Manual routing

By default, controller actions in your Sails app will be inaccessible to users until you _bind_ them to a route in your [`config/routes.js` file](https://sailsjs.com/documentation/reference/configuration/sails-config-routes).  When you bind a route, you specify a URL that users can access the action at, along with options like [CORS security settings](https://sailsjs.com/documentation/concepts/security/cors#?configuring-cors-for-individual-routes).

To bind a route to an action in the `config/routes.js` file, you can use the HTTP verb and path (i.e. the **route address**) as the key, and the action identity as the value (i.e. the **route target**).

For example, the following manual route will cause your app to trigger the `make` action in `api/controllers/SandwichController.js` whenever it receives a POST request to `/make/a/sandwich`:

```js
  'POST /make/a/sandwich': 'SandwichController.make'
```

If you&rsquo;re using standalone actions, so that you had an `api/controllers/sandwich/make.js` file, a more intuitive syntax exists which uses the path to the action (relative to `api/controllers`):

```js
  'POST /make/a/sandwich': 'sandwich/make'
```

For a full discussion of routing, please see the [routes documentation](https://sailsjs.com/documentation/concepts/Routes).

### Automatic routing

Sails can also automatically bind routes to your controller actions so that a `GET` request to `/:actionIdentity` will trigger the action.  This is called _blueprint action routing_, and it can be activated by setting `actions` to `true` in the [`config/blueprints.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints) file.  For example, with blueprint action routing turned on, a `signup` action saved in `api/controllers/UserController.js` or `api/controllers/user/signup.js` would be bound to a `/user/signup` route.  See the [blueprints documentation](https://sailsjs.com/documentation/reference/blueprint-api) for more information about Sails&rsquo; automatic route binding.


<docmeta name="displayName" value="Routing to actions">

---

### Concepts Assets Assets (`docs/concepts/Assets/Assets.md`)

# Assets

### Overview

Assets refer to [static files](http://en.wikipedia.org/wiki/Static_web_page) (js, css, images, etc.) on your server that you want to make accessible to the outside world.  In Sails, these files are placed in the [`assets/`](https://sailsjs.com/documentation/anatomy/assets) folder.  When you lift your app, add files to your `assets/` folder, or change existing assets, Sails' built-in asset pipeline processes and syncs those files to a hidden folder (`.tmp/public/`).

> This intermediate step (moving files from `assets/` into `.tmp/public/`) allows Sails to pre-process assets for use on the client - things like LESS, CoffeeScript, SASS, spritesheets, Jade templates, etc.

The contents of this `.tmp/public` folder are what Sails actually serves at runtime.  This is roughly equivalent to the "public" folder in [express](https://github.com/expressjs), or the `www/` folder you might be familiar with from other web servers like Apache.


### Static middleware

Behind the scenes, Sails uses the [serve-static middleware](https://www.npmjs.com/package/serve-static) from Express to serve your assets. You can configure this middleware (e.g. to change cache settings) in [`/config/http.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-http).

##### `index.html`
Like most web servers, Sails honors the `index.html` convention.  For instance, if you create `assets/foo.html` in a new Sails project, it will be accessible at `http://localhost:1337/foo.html`.  But if you create `assets/foo/index.html`, it will be available at both `http://localhost:1337/foo/index.html` and `http://localhost:1337/foo`.

##### Precedence
It is important to note that the static [middleware](http://stephensugden.com/middleware_guide/) is installed **after** the Sails router.  So if you define a [custom route](https://sailsjs.com/documentation/concepts/Routes?q=custom-routes), but also have a file in your assets directory with a conflicting path, the custom route will intercept the request before it reaches the static middleware. For example, if you create `assets/index.html`, with no routes defined in your [`config/routes.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-routes) file, it will be served as your home page.  But if you define a custom route, `'/': 'FooController.bar'`, that route will take precedence.



<docmeta name="displayName" value="Assets">
<docmeta name="nextUpLink" value="/documentation/concepts/shell-scripts">
<docmeta name="nextUpName" value="Shell Scripts">

---

### Concepts Assets DefaultTasks (`docs/concepts/Assets/DefaultTasks.md`)

# Default tasks

### Overview

The asset pipeline bundled in Sails is a set of Grunt tasks configured with conventional defaults designed to make your project more consistent and productive. The entire frontend asset workflow is completely customizable, while providing some default tasks out of the box. Sails makes it easy to [configure new tasks](https://sailsjs.com/documentation/concepts/assets/task-automation#?task-configuration) to fit your needs.


Here are a few things that the default Grunt configuration in Sails does to help you out:
- Automatic LESS compilation
- Cache busting
- Optional automatic asset injection, minification, and concatenation
- Creation of a web ready public directory
- File watching and syncing
- Transpilation of client-side JavaScript in production to allow use of >=ES6 syntax while maintaining broad browser compatibility
- Optimization of assets in production


### Default Grunt tasks

Below is a list of the Grunt tasks that are included by default in new Sails projects:

##### clean

> This grunt task is configured to clean out the contents in the `.tmp/public/` of your Sails project.

> [usage docs](https://github.com/gruntjs/grunt-contrib-clean)

##### hash

> Creates and adds an unique hash to the end of a filename for cache busting.

> [usage docs](https://github.com/jgallen23/grunt-hash/tree/0.5.0#grunt-hash)

##### concat

> Concatenates JavaScript and CSS files, and saves concatenated files in `.tmp/public/concat/` directory.

> [usage docs](https://github.com/gruntjs/grunt-contrib-concat)

##### copy

> **dev task config**
>
> Copies all directories and files, except coffeescript and less files, from the sails assets folder into the `.tmp/public/` directory.

> **build task config**
>
> Copies all directories and files from the .tmp/public directory into a www directory.

> [usage docs](https://github.com/gruntjs/grunt-contrib-copy)

##### cssmin

> Minifies CSS files and places them into `.tmp/public/min/` directory.

> [usage docs](https://github.com/gruntjs/grunt-contrib-cssmin)

##### less

> Compiles LESS files into CSS. Only the `assets/styles/importer.less` is compiled. This allows you to control the ordering yourself (i.e. import your dependencies, mixins, variables, resets, etc. before other stylesheets).

> [usage docs](https://github.com/gruntjs/grunt-contrib-less)

##### sails-linker

> Automatically inject `<script>` tags for JavaScript files and `<link>` tags for CSS files.  Also automatically links an output file containing precompiled templates using a `<script>` tag. A much more detailed description of this task can be found [here](https://github.com/balderdashy/sails-generate-frontend/blob/master/docs/overview.md#a-litte-bit-more-about-sails-linking), but the big takeaway is that script and stylesheet injection is *only* done in files containing `` and/or `` tags.  These are included in the default **views/layouts/layout.ejs** file in a new Sails project.  If you don't want to use the linker for your project, you can simply remove those tags.

> [usage docs](https://github.com/Zolmeister/grunt-sails-linker)

##### sync

> A grunt task to keep directories in sync. It is very similar to grunt-contrib-copy but tries to copy only those files that have actually changed. It specifically synchronizes files from the `assets/` folder to `.tmp/public/`, overwriting anything that's already there.

> [usage docs](https://github.com/tomusdrw/grunt-sync)

##### babel

> This grunt task is configured to transpile any >=ES6 syntax in your front-end Javascript files into code compatible with older browsers.

> [usage docs](https://github.com/babel/grunt-babel)

##### uglify

> Minifies client-side JavaScript assets.  Note that by default, this task will "mangle" all of your function and variable names (either by changing them to a much shorter name, or stripping them entirely).  This is usually desirable as it makes your code significantly smaller, but in some cases can lead to unexpected results (particularly when you expect an object's constructor to have a certain name).  To turn off or modify this behavior, [use the `mangle` option](https://www.npmjs.com/package/uglify-es#mangle-properties-options) when setting up this task.

> [usage docs](https://github.com/gruntjs/grunt-contrib-uglify/tree/harmony)

##### watch

> Runs predefined tasks whenever watched file patterns are added, changed, or deleted. Watches for changes on files in the `assets/` folder, and re-runs the appropriate tasks (e.g. LESS compilation).  This allows you to see changes to your assets reflected in your app without having to restart the Sails server.

> [usage docs](https://github.com/gruntjs/grunt-contrib-watch)


<docmeta name="displayName" value="Default tasks">

---

### Concepts Assets DisablingGrunt (`docs/concepts/Assets/DisablingGrunt.md`)

# Disabling Grunt

To disable Grunt integration in Sails, simply delete your Gruntfile (and/or [`tasks/`](https://sailsjs.com/documentation/anatomy/tasks) folder). You can also disable the Grunt hook. Just set the `grunt` property to `false` in `.sailsrc` hooks, like this:

```json
{
    "hooks": {
        "grunt": false
    }
}
```

### Can I customize this for SASS, Angular, client-side Jade templates, etc.?

Yep! Just replace the relevant grunt task in your `tasks/` directory, or add a new one.  Like [SASS](https://github.com/sails101/using-sass), for example.

If you still want to use Grunt for other purposes, but don't want any of the default web front-end stuff, just delete your project's assets folder and remove the front-end oriented tasks from the `tasks/register/` and `tasks/config/` folders.  You can also run `sails new myCoolApi --no-frontend` to omit the assets folder and front-end-oriented Grunt tasks for future projects.  You can also replace your `sails-generate-frontend` module with alternative community generators, or [create your own](https://github.com/balderdashy/sails-generate-generator).  This allows `sails new` to create the boilerplate for native iOS apps, Android apps, Cordova apps, SteroidsJS apps, etc.



<docmeta name="displayName" value="Disabling Grunt">

### NOTE:

When removing the Grunt hook above you must also specify the following in `.sailsrc` in order for your assets to be served, otherwise all assets will return a `404`.

```json
{
    "paths": {
        "public": "assets"
    }
}
```

---

### Concepts Assets TaskAutomation (`docs/concepts/Assets/TaskAutomation.md`)

# Task automation

### Overview

The [`tasks/`](https://sailsjs.com/documentation/anatomy/tasks) directory contains a suite of [Grunt tasks](http://gruntjs.com/creating-tasks) and their [configurations](http://gruntjs.com/configuring-tasks).

Tasks are mainly useful for bundling front-end assets, (like stylesheets, scripts, & client-side markup templates) but they can also be used to automate all kinds of repetitive development chores, from [browserify](https://github.com/jmreidy/grunt-browserify) compilation to [database migrations](https://www.npmjs.org/package/grunt-db-migrate).

Sails bundles some [default tasks](https://sailsjs.com/documentation/grunt/default-tasks) for convenience, but with [literally hundreds of plugins](http://gruntjs.com/plugins) to choose from, you can use tasks to automate just about anything with minimal effort.  If someone hasn't already built what you need, you can always [author](http://gruntjs.com/creating-tasks) and [publish your own Grunt plugin](http://gruntjs.com/creating-plugins) to [npm](http://npmjs.org)!

> If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins.


### Asset pipeline

The asset pipeline is the place where you will organize the assets that will be injected into your views, and it can be found in the `tasks/pipeline.js` file. Configuring these assets is simple and uses Grunt [task file configuration](http://gruntjs.com/configuring-tasks#files) and [wildcard/glob/splat patterns](http://gruntjs.com/configuring-tasks#globbing-patterns). These are broken down into three sections:

##### CSS Files to Inject
This is an array of CSS files to be injected into your HTML as `<link>` tags.  These tags will be injected between the `` comments in any view in which they appear.

##### JavaScript Files to Inject
This is an array of JavaScript files that gets injected into your HTML as `<script>` tags.  These tags will be injected between the `` comments in any view in which they appear. The files get injected in the order in which they appear in the array, meaning you should place the path of dependencies before the file that depends on them.

##### Template Files to Inject
This is an array of HTML files that will compiled to a JST function and placed in a jst.js file. This file then gets injected as a `<script>` tag in between the `` comments in your HTML.

> The same Grunt wildcard/glob/splat patterns and task file configuration are used in some of the task configuration JS files themselves if you would like to change those too.

### Task configuration

Configured tasks are the set of rules your Gruntfile will follow when run. They are completely customizable and are located in the [`tasks/config/`](https://sailsjs.com/documentation/anatomy/my-app/tasks/config) directory. You can modify, omit, or replace any of these Grunt tasks to fit your requirements. You can also add your own Grunt tasks&mdash;just add a `someTask.js` file in this directory to configure the new task, then register it with the appropriate parent task(s) (see files in `tasks/register/*.js`). Remember, Sails comes with a set of useful default tasks that are designed to get you up and running with no configuration required.

##### Configuring a custom task.

Configuring a custom task into your project is very simple and uses Grunt&rsquo;s [config](http://gruntjs.com/api/grunt.config) and [task](http://gruntjs.com/api/grunt.task) APIs to allow you to make your task modular. Let&rsquo;s go through a quick example of creating a new task that replaces an existing task. Suppose we want to use the [Handlebars](http://handlebarsjs.com/) templating engine instead of the underscore templating engine that comes configured by default:

* The first step is to install the Handlebars Grunt plugin using the following command in your terminal:

```bash
npm install grunt-contrib-handlebars --save-dev
```

* Next, create a configuration file at `tasks/config/handlebars.js`. This is where we&rsquo;ll put our Handlebars configuration.

```javascript
// tasks/config/handlebars.js
// --------------------------------
// handlebar task configuration.

module.exports = function(grunt) {

  // We use the grunt.config api's set method to configure an
  // object to the defined string. In this case the task
  // 'handlebars' will be configured based on the object below.
  grunt.config.set('handlebars', {
    dev: {
      // We will define which template files to inject
      // in tasks/pipeline.js
      files: {
        '.tmp/public/templates.js': require('../pipeline').templateFilesToInject
      }
    }
  });

  // load npm module for handlebars.
  grunt.loadNpmTasks('grunt-contrib-handlebars');
};
```

* Replace the path to source files in asset pipeline. The only change here will be that Handlebars looks for files with the extension .hbs while underscore templates can be in simple HTML files.

```javascript
// tasks/pipeline.js
// --------------------------------
// asset pipeline

var cssFilesToInject = [
  'styles/**/*.css'
];

var jsFilesToInject = [
  'js/socket.io.js',
  'js/sails.io.js',
  'js/connection.example.js',
  'js/**/*.js'
];

// We change this glob pattern to include all files in
// the templates/ direcotry that end in the extension .hbs
var templateFilesToInject = [
  'templates/**/*.hbs'
];

module.exports = {
  cssFilesToInject: cssFilesToInject.map(function(path) {
    return '.tmp/public/' + path;
  }),
  jsFilesToInject: jsFilesToInject.map(function(path) {
    return '.tmp/public/' + path;
  }),
  templateFilesToInject: templateFilesToInject.map(function(path) {
    return 'assets/' + path;
  })
};
```

* Include the Handlebars task into the compileAssets and syncAssets registered tasks. This is where the JST task was being used; we will now replace it with the newly configured Handlebars task.

```javascript
// tasks/register/compileAssets.js
// --------------------------------
// compile assets registered grunt task

module.exports = function (grunt) {
  grunt.registerTask('compileAssets', [
    'clean:dev',
    'handlebars:dev',       // changed jst task to handlebars task
    'less:dev',
    'copy:dev',
    'coffee:dev'
  ]);
};

// tasks/register/syncAssets.js
// --------------------------------
// synce assets registered grunt task

module.exports = function (grunt) {
  grunt.registerTask('syncAssets', [
    'handlebars:dev',      // changed jst task to handlebars task
    'less:dev',
    'sync:dev',
    'coffee:dev'
  ]);
};
```

* Remove JST task config file. We are no longer using it so we can get rid of `tasks/config/jst.js`. Simply delete it from your project.

> Ideally you should delete it from your project and your project's Node dependencies. This can be done by running this command in your terminal:
```bash
npm uninstall grunt-contrib-jst --save-dev
```

### Task triggers

In [development mode](https://next.sailsjs.com/documentation/reference/configuration/sails-config#?sailsconfigenvironment), Sails runs the `default` task ([`tasks/register/default.js`](https://sailsjs.com/documentation/anatomy/tasks/register/default.js)).  This compiles LESS, CoffeeScript, and client-side JST templates, then links to them automatically from your app's dynamic views and static HTML pages.

In production, Sails runs the `prod` task ([`tasks/register/prod.js`](https://sailsjs.com/documentation/anatomy/tasks/register/prod.js)) which shares the same duties as `default`, but also minifies your app's scripts and stylesheets.  This reduces your application's load time and bandwidth usage.

These task triggers are ["basic" Grunt tasks](http://gruntjs.com/creating-tasks#basic-tasks) located in the [`tasks/register/`](https://sailsjs.com/documentation/anatomy/tasks/register) folder.  Below, you'll find the complete reference of all task triggers in Sails, and the command which kicks them off:

##### `sails lift`

Runs the **default** task (`tasks/register/default.js`).

##### `sails lift --prod`

Runs the **prod** task (`tasks/register/prod.js`).

##### `sails www`

Runs the **build** task (`tasks/register/build.js`) that compiles all the assets to `www` subfolder instead of `.tmp/public` using relative paths in references. This allows serving static content with Apache or Nginx instead of relying on ['www middleware'](https://sailsjs.com/documentation/concepts/Middleware).

##### `sails www --prod` (production)

Runs the **buildProd** task (`tasks/register/buildProd.js`) that does the same as **build** task but also optimizes assets.

You may run other tasks by specifying setting NODE_ENV and creating a task list in tasks/register/ with the same name.  For example, if NODE_ENV is QA, sails will run tasks/register/QA.js if it exists.


<docmeta name="displayName" value="Task automation">

---

### Concepts Blueprints Blueprint Actions (`docs/concepts/Blueprints/Blueprint Actions.md`)

# Blueprint actions

Blueprint actions (not to be confused with implicit [blueprint "action" _routes_](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes#?action-routes)) are generic actions designed to work with your models.  Think of them as the default behavior for your application.  For instance, if you have a `User.js` model then `find`, `create`, `update`, `destroy`, `populate`, `add` and `remove` actions exist implicitly, without you having to write them.

By default, the blueprint [RESTful routes](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes#?restful-routes) and [shortcut routes](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes#?shortcut-routes) are bound to their corresponding blueprint actions.  However, any blueprint action can be overridden for a particular controller by creating a custom action in that controller file (e.g. `ParrotController.find`).

The current version of Sails ships with the following blueprint actions:

+ [find](https://sailsjs.com/documentation/reference/blueprint-api/find-where)
+ [findOne](https://sailsjs.com/documentation/reference/blueprint-api/find-one)
+ [create](https://sailsjs.com/documentation/reference/blueprint-api/create)
+ [update](https://sailsjs.com/documentation/reference/blueprint-api/update)
+ [destroy](https://sailsjs.com/documentation/reference/blueprint-api/destroy)
+ [populate](https://sailsjs.com/documentation/reference/blueprint-api/populate)
+ [add](https://sailsjs.com/documentation/reference/blueprint-api/add-to)
+ [remove](https://sailsjs.com/documentation/reference/blueprint-api/remove-from)
+ [replace](https://sailsjs.com/documentation/reference/blueprint-api/replace)

### Socket notifications

Most blueprint actions have realtime features that take effect if your app has WebSockets enabled.  For example, if the **find** blueprint action receives a request from a socket client, it will [subscribe](https://sailsjs.com/documentation/reference/web-sockets/resourceful-pub-sub/subscribe) that socket to future notifications.  Then, any time records are changed using blueprint actions like **update**, Sails will [publish](https://sailsjs.com/documentation/reference/web-sockets/resourceful-pub-sub/publish) certain notifications.

The best way to understand the behavior of a particular blueprint action is to read its [reference page](https://sailsjs.com/documentation/reference/blueprint-api) (or see the list above).  But if you're looking for more of a birds-eye view of how realtime features work in Sails's blueprint API, see [**Concepts > Realtime**](https://sailsjs.com/documentation/concepts/realtime).  (If you're OK with some details being out of date, you might even want to check out the [original "Intro to Sails.js" video from 2013](https://www.youtube.com/watch?v=GK-tFvpIR7c).)

> For a more advanced breakdown of all notifications published by blueprint actions in Sails, see:
> + [Chart A (scenarios vs. notification types)](https://docs.google.com/spreadsheets/d/10FV9plyHR4gE9xIomIZlF-YS1S54oHEdvH8ZmTC1Fnc/edit#gid=0)
> + [Chart B (actions vs. recipients)](https://docs.google.com/spreadsheets/d/1B6i8aOoLNLtxJ4aeiA8GQ2lUQSvLOrP89RSLr7IAImw/edit#gid=0)

### Overriding blueprint actions

You may also override any of the blueprint actions for a controller by defining a [custom action](https://sailsjs.com/documentation/concepts/actions-and-controllers) with the same name.

```javascript
// api/controllers/user/UserController.js
module.exports = {

  /**
   * A custom action that overrides the built-in "findOne" blueprint action.
   * As a dummy example of customization, imagine we were working on something in our app
   * that demanded we tweak the format of the response data, and that we only populate two
   * associations: "company" and "friends".
   */
  findOne: function (req, res) {

    sails.log.debug('Running custom `findOne` action.  (Will look up user #'+req.param(\'id\')...');

    User.findOne({ id: req.param('id') }).omit(['password'])
    .populate('company', { select: ['profileImageUrl'] })
    .populate('top8', { omit: ['password'] })
    .exec(function(err, userRecord) {
      if (err) {
        switch (err.name) {
          case 'UsageError': return res.badRequest(err);
          default: return res.serverError(err);
        }
      }

      if (!userRecord) { return res.notFound(); }

      if (req.isSocket) {
        User.subscribe(req, [user.id]);
      }

      return res.ok({
        model: 'user',
        luckyCoolNumber: Math.ceil(10*Math.random()),
        record: userRecord
      });
    });
  }

}
```

> Alternatively, we could have created this as a standalone action at `api/controllers/user/findone.js` or used [actions2](https://sailsjs.com/documentation/concepts/actions-and-controllers#?actions-2).

<docmeta name="displayName" value="Blueprint actions">

---

### Concepts Blueprints Blueprint Routes (`docs/concepts/Blueprints/Blueprint Routes.md`)

# Blueprint routes

When you run `sails lift` with blueprints enabled, the framework inspects your models and configuration in order to [bind certain routes](https://sailsjs.com/documentation/concepts/Routes) automatically. These implicit blueprint routes (sometimes called "shadow routes", or even just "shadows") allow your app to respond to certain requests without you having to bind those routes manually in your `config/routes.js` file.  When enabled, the blueprint routes point to their corresponding blueprint *actions* (see "Action routes" below), any of which can be overridden with custom code.

There are four types of blueprint routes in Sails:

### RESTful blueprint routes
REST blueprints are the automatically generated routes Sails uses to expose a conventional REST API for a model, including `find`, `create`, `update`, and `destroy` actions. The path for RESTful routes is always `/:modelIdentity` or `/:modelIdentity/:id`.  These routes use the HTTP "verb" to determine the action to take.

For example, with [`rest`](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints#?routerelated-settings) enabled, having a `Boat` model in your app generates the following routes:

+ **GET /boat** -> find boats matching criteria provided on the query string, using the [`find` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/find-where).
+ **GET /boat/:id** -> find a single boat with the given unique ID (i.e. primary key) value, using the [`findOne` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/find-one).
+ **POST /boat** -> create a new boat with the attributes provided in the request body, using the [`create` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/create).
+ **PATCH /boat/:id** -> update the boat with the given unique ID with the attributes provided in the request body, using the [`update` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/update).
+ **DELETE /boat/:id** -> destroy the boat with the given unique ID, using the [`destroy` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/destroy).

If the `Boat` model has a &ldquo;to-many&rdquo; relationship with a `Driver` model through an attribute called `drivers`, then the following additional routes would be available:

+ **GET /boat/:id/drivers** -> Finds the drivers' records associated to the boat record with the ID given as `:id` using the [`populate` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/populate-where).
+ **PUT /boat/:id/drivers/:fk** -> add the driver with the unique ID equal to the `:fk` value to the `drivers` collection of the boat with the ID given as `:id`, using the [`add` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/add-to).
+ **DELETE /boat/:id/drivers/:fk** -> remove the driver with the unique ID equal to the `:fk` value to the `drivers` collection of the boat with the ID given as `:id`, using the [`remove` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/remove-from)
+ **PUT /boat/:id/drivers** -> replace the entire `drivers` collection with the drivers whose unique IDs are contained in an array provided as the body of the request, using the [`replace` blueprint](https://sailsjs.com/documentation/reference/blueprint-api/replace).

Depending on the style of app you generated, `rest` blueprint routes may be enabled by default, and could be suitable for use in a production scenario, as long as they are protected by [policies](https://sailsjs.com/documentation/concepts/Policies) to avoid unauthorized access. If you choose the "Web app" template, `rest` blueprint routes will not be enabled by default.

> Be forewarned: Most web apps, microservices, and even REST APIs eventually need custom features that aren't really as simple as "create", "update", or "destroy".  If/when the time comes, don't be afraid to write your own custom actions.  Custom actions and routes can, and in many cases _should_, still be organized as a RESTful API, and they can be mixed and matched with blueprints when necessary.  Best of all, thanks to the introduction of [async/await in Node.js](https://gist.github.com/mikermcneil/c1028d000cc0cc8bce995a2a82b29245), writing custom actions no longer requires the use of callbacks.



##### Notes

> + If CSRF protection is enabled, you'll need to provide or disable a [CSRF token](https://sailsjs.com/documentation/concepts/security/csrf) for POST/PUT/DELETE actions, otherwise you will get a 403 Forbidden response.
> + If your app contains a controller whose name matches that of your model, then you can override the default actions pointed to by the RESTful routes by providing your own controller actions.  For example, if you have an `api/controllers/BoatController.js` controller file containing a custom `find` action, then the `GET /boat` route will point at that action.
> + Also, as usual, the same logic applies whether you're using controllers or standalone actions.  (As far as Sails is concerned, once an app has been loaded into memory and normalized in `sails lift`, all of its actions look the same no matter where they came from.)
> + If your app contains a route in `config/routes.js` that matches one of the above RESTful routes, it will be used instead of the default route.

### Shortcut blueprint routes
Shortcut routes are a simple (development-mode only) hack that provides access to your models from your browser's URL bar.

The shortcut routes are as follows:

| Route | Blueprint Action | Example URL |
| ----- | ----------------------- | ------- |
| GET /:modelIdentity/find | [find](https://sailsjs.com/documentation/reference/blueprint-api/find-where) | `http://localhost:1337/user/find?name=bob`
| GET /:modelIdentity/find/:id | [findOne](https://sailsjs.com/documentation/reference/blueprint-api/find-one) | `http://localhost:1337/user/find/123`
| GET /:modelIdentity/create | [create](https://sailsjs.com/documentation/reference/blueprint-api/create) | `http://localhost:1337/user/create?name=bob&age=18`
| GET /:modelIdentity/update/:id | [update](https://sailsjs.com/documentation/reference/blueprint-api/update) | `http://localhost:1337/user/update/123?name=joe`
| GET /:modelIdentity/destroy/:id | [destroy](https://sailsjs.com/documentation/reference/blueprint-api/destroy) | `http://localhost:1337/user/destroy/123`
| GET /:modelIdentity/:id/:association/add/:fk | [add](https://sailsjs.com/documentation/reference/blueprint-api/add-to) | `http://localhost:1337/user/123/pets/add/3`
| GET /:modelIdentity/:id/:association/remove/:fk | [remove](https://sailsjs.com/documentation/reference/blueprint-api/remove-from) | `http://localhost:1337/user/123/pets/remove/3`
| GET /:modelIdentity/:id/:association/replace?association=[1,2...] | [replace](https://sailsjs.com/documentation/reference/blueprint-api/replace) | `http://localhost:1337/user/123/pets/replace?pets=[3,4]`

**Shortcut routes should always be disabled when Sails lifts in a production environment.  But they can be very handy during development, especially if you prefer not to use [the terminal](https://sailsjs.com/documentation/reference/command-line-interface/sails-console).**

##### Notes

> + Like RESTful routes, shortcut routes can be overridden by providing an action in a matching controller, or by providing a route in `config/routes.js`.
> + the same _action_ is executed for similar RESTful/shortcut routes.  For example, the `POST /user` and `GET /user/create` routes that Sails creates when it loads `api/models/User.js` will respond by running the same code (even if you [override the blueprint action](https://sailsjs.com/documentation/reference/blueprint-api#?overriding-blueprints))
> + When using a <a href="https://en.wikipedia.org/wiki/NoSQL" target="_blank">NoSQL</a> database (like <a href="https://docs.mongodb.com/" target="_blank">MongoDB</a>) with your model&rsquo;s [`schema` configuration](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?schema) set to `false`, shortcut routes will interpret any parameter value for an unknown attribute as a _string_.  Be careful doing `http://localhost:1337/game/create?players=2` if you don&rsquo;t have a `players` attribute with a `number` type!

### Action shadow routes

When action shadow routes (or "action shadows") are enabled, Sails will automatically create routes for your custom controller actions.  This is sometimes useful (especially early on in the development process) for speeding up backend development by eliminating the need to manually bind routes.  When enabled, GET, POST, PUT, and DELETE routes will be generated for every one of a controller's actions.

For example, if you have a `FooController.js` file with a `bar` method, then a `/foo/bar` route will automatically be created for you as long as `sails.config.blueprints.actions` is enabled.  Unlike RESTful and shortcut shadows, implicit, per-action shadow routes do *not* require that a controller has a corresponding model file.

If an `index` action exists, additional naked routes will be created for it. Finally, all `actions` blueprints support an optional path parameter, `id`, for convenience.

Since Sails v1.0, action shadows are **disabled by default**. They can be OK for production-- however, if you'd like to continue to use controller/action autorouting in a production deployment, you must take great care not to inadvertently expose unsafe/unintentional controller logic to GET requests. You can easily turn off a particular method or path in your [`/config/routes.js`](https://sailsjs.com/documentation/anatomy/my-app/config/routes-js) file using the [response target syntax](https://sailsjs.com/documentation/concepts/routes/custom-routes#?response-target-syntax), for example:

```javascript
'POST /user': {response: 'notFound'}
```

##### Notes
> + Action routes respond to _all_ HTTP verbs (GET, PUT, POST, etc.).  You can use `req.method` inside an action to determine which method was used.

##### "Index" actions

When action shadows (`sails.config.blueprints.actions`) are enabled, an additional, root shadow route is automatically exposed for any actions that happen to be named `index`.  For example, if you have a `FooController.js` file with an `index` action in it, a `/foo` shadow route will automatically be bound for that action.  Similarly, if you have a [standalone action](https://sailsjs.com/documentation/concepts/actions-and-controllers#?standalone-actions) at `api/controllers/foo/index.js`, a `/foo` route will be exposed automatically on its behalf.



Read more about [configuring blueprints in Sails](https://sailsjs.com/documentation/reference/configuration/sails-config-blueprints), including how to enable / disable different categories of blueprint routes.


<docmeta name="displayName" value="Blueprint routes">

---

### Concepts Blueprints Blueprints (`docs/concepts/Blueprints/Blueprints.md`)

# Blueprints

### Overview

Like any good web framework, Sails aims to reduce both the amount of code you write and the time it takes to get a functional app up and running.  _Blueprints_ are Sails&rsquo;s way of quickly generating API [routes](https://sailsjs.com/documentation/concepts/routes) and [actions](https://sailsjs.com/documentation/concepts/controllers#?actions) based on your application design.

Together, [blueprint routes](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes) and [blueprint actions](https://sailsjs.com/documentation/concepts/blueprints/blueprint-actions) constitute the **blueprint API**, the built-in logic that powers the [RESTful JSON API](http://en.wikipedia.org/wiki/Representational_state_transfer) you get every time you create a model and controller.

For example, if you create a `User.js` model file in your project, then with blueprints enabled you will be able to immediately visit `/user/create?name=joe` to create a user, and visit `/user` to see an array of your app's users.  All without writing a single line of code!

Blueprints are a powerful tool for prototyping, but in many cases can be used in production as well, since they can be overridden, protected, extended or disabled entirely.

### Up next

+ [Read more](https://sailsjs.com/documentation/concepts/blueprints/blueprint-actions) about built-in blueprint actions
+ [Read more](https://sailsjs.com/documentation/concepts/blueprints/blueprint-routes) about implicit "shadow" routes and how to configure or override them

<docmeta name="displayName" value="Blueprints">

---

### Concepts Configuration Configuration (`docs/concepts/Configuration/Configuration.md`)

# Configuration

### Overview

While Sails dutifully adheres to the philosophy of [convention-over-configuration](http://en.wikipedia.org/wiki/Convention_over_configuration), it is important to understand how to customize those handy defaults from time to time.  For almost every convention in Sails, there is an accompanying set of configuration options that allow you to adjust or override things to fit your needs.

> Here looking for a particular setting?  Head over to [Reference > Configuration](https://sailsjs.com/documentation/reference/configuration) to see a complete guide to all configuration options available in Sails.

Sails apps can be [configured programmatically](https://github.com/mikermcneil/sails-generate-new-but-like-express/blob/master/templates/app.js#L15), by specifying [environment variables](http://en.wikipedia.org/wiki/Environment_variable) or command-line arguments, by changing the local or global [`.sailsrc` files](https://sailsjs.com/documentation/anatomy/.sailsrc), or (most commonly) using the boilerplate configuration files conventionally located in the [`config/`](https://sailsjs.com/documentation/anatomy/config) folder of new projects. The authoritative, merged-together configuration used in your app is available at runtime on the `sails` global as `sails.config`.


### Standard configuration files (`config/*`)

A number of configuration files are generated in new Sails apps by default.  These boilerplate files include a number of inline comments, which are designed to provide a quick, on-the-fly reference without having to jump back and forth between the docs and your text editor.

In most cases, the top-level keys on the `sails.config` object (e.g. `sails.config.views`) correspond to a particular configuration file (e.g. `config/views.js`) in your app; however configuration settings may be arranged however you like across the files in your `config/` directory.  The important part is the name (i.e. key) of the setting&mdash;not the file it came from.

For instance, let's say you add a new file, `config/foo.js`:

```js
// config/foo.js
// The object below will be merged into `sails.config.blueprints`:
module.exports.blueprints = {
  shortcuts: false
};
```

For an exhaustive reference of individual configuration options, and the file they live in by default, check out the reference pages in this section, or take a look at ["`config/`"](https://sailsjs.com/documentation/anatomy/config) in [The Anatomy of a Sails App](https://sailsjs.com/documentation/anatomy) for a higher-level overview.

### Environment-specific files (`config/env/*`)

Settings specified in the standard configuration files will generally be available in all environments (i.e. development, production, test, etc.).  If you'd like to have some settings take effect only in certain environments, you can use the special environment-specific files and folders:

* Any files saved under the `/config/env/<environment-name>` folder will be loaded *only* when Sails is lifted in the `<environment-name>` environment.  For example, files saved under `config/env/production` will only be loaded when Sails is lifted in production mode.
* Any files saved as `config/env/<environment-name>.js` will be loaded *only* when Sails is lifted in the `<environment-name>` environment, and will be merged on top of any settings loaded from the environment-specific subfolder.  For example, settings in `config/env/production.js` will take precedence over those in the files in the  `config/env/production` folder.

By default, your app runs in the "development" environment.  The recommended approach for changing your app's environment is by using the `NODE_ENV` environment variable:
```
NODE_ENV=production node app.js
```

> The `production` environment is special: depending on your configuration, it enables compression, caching, minification, etc.
>
> Also note that if you are using `config/local.js`, the configuration exported in that file takes precedence over environment-specific configuration files.


### The `config/local.js` file

You may use the `config/local.js` file to configure a Sails app for your local environment (your laptop, for example).  The settings in this file take precedence over all other config files except [.sailsrc](https://sailsjs.com/documentation/concepts/configuration/using-sailsrc-files).  Since they're intended only for local use, they should not be put under version control (and are included in the default `.gitignore` file for that reason).  Use `local.js` to store local database settings, change the port used when lifting an app on your computer, etc.

See [Concepts > Configuration > The local.js file](https://sailsjs.com/documentation/concepts/configuration/the-local-js-file) for more information.


### Accessing `sails.config` in your app

The `config` object is available on the Sails app instance (`sails`).  By default, this is exposed on the [global scope](https://sailsjs.com/documentation/concepts/globals) during lift, and therefore available from anywhere in your app.

##### Example
```javascript
// This example checks that, if we are in production mode, csrf is enabled.
// It throws an error and crashes the app otherwise.
if (sails.config.environment === 'production' && !sails.config.security.csrf) {
  throw new Error('STOP IMMEDIATELY ! CSRF should always be enabled in a production deployment!');
}
```

### Setting `sails.config` values directly using environment variables

In addition to using configuration _files_, you can set individual configuration values on the command line when you lift Sails by prefixing the config key names with `sails_`, and separating nested key names with double underscores (`__`).  Any environment variable formatted this way will be parsed as JSON (if possible). For example, you could do the following to set the [allowed CORS origins](https://sailsjs.com/documentation/concepts/security/cors) (`sails.config.security.cors.allowOrigins`) to `["http://somedomain.com","https://anotherdomain.com:1337"]` on the command line:

```javascript
sails_security__cors__allowOrigins='["http://somedomain.com","https://anotherdomain.com:1337"]' sails console
```

> Note the use of double quotes to indicate strings within the JSON-encoded value, and the single quotes surrounding the whole value so that it is passed correctly to Sails from the console.

This value will be in effect _only_ for the lifetime of this particular Sails instance, and will override any values in the configuration files.

Also note that configuration specified using environment variables does _not_ automatically apply to Sails instances that are started [programmatically](https://sailsjs.com/documentation/concepts/programmatic-usage).

> There are a couple of special exceptions to the above rule: `NODE_ENV` and `PORT`.
> + `NODE_ENV` is a convention for any Node.js app.  When set to `'production'`, it sets [`sails.config.environment`](https://sailsjs.com/documentation/reference/configuration/sails-config#?sailsconfigenvironment).
> + Similarly, `PORT` is just another way to set [`sails.config.port`](https://sailsjs.com/documentation/reference/configuration/sails-config#?sailsconfigport).  This is strictly for convenience and backwards compatibility.
>
> Here's a relatively common example where you might use both of these environment variables at the same time:
>
> ```bash
> PORT=443 NODE_ENV=production sails lift
> ```
>
> When present in the current process environment, `NODE_ENV` and `PORT` will apply to any Sails app that is started via the command line or programmatically, unless explicitly overridden.

Environment variables are one of the most powerful ways to configure your Sails app.  Since you can customize just about any setting (as long as it's JSON-serializable), this approach solves a number of problems, and is our core team's recommended strategy for production deployments.  Here are a few:

+ Using environment variables means you don't have to worry about checking in your production database credentials, API tokens, etc.
+ This makes changing Postgresql hosts, Mailgun accounts, S3 credentials, and other maintenance straightforward, fast, and easy; plus you don't need to change any code or worry about merging in downstream commits from other people on your team
+ Depending on your hosting situation, you may be able to manage your production configuration through a UI (most PaaS providers like [Heroku](http://heroku.com) or [Modulus](https://modulus.io) support this, as does [Azure Cloud](https://azure.microsoft.com/en-us/).)


### Setting `sails.config` values using command line arguments

For situations where setting an environment variable on the command line may not be practical (such as some Windows systems), you can use regular command line arguments to set configuration options.  To do so, specify the name of the option prefixed by two dashes (`--`), with nested key names separated by dots.  Command line arguments are parsed using [minimist](https://github.com/substack/minimist/tree/0.0.10), which does _not_ parse JSON values like arrays or dictionaries, but will handle strings, numbers and booleans (using a special syntax).  Some examples:

```javascript
// Set the port to 1338
sails lift --port=1338

// Set a custom "email" value to "foo@bar.com":
sails lift --custom.email='foo@bar.com'

// Turn on CSRF support
sails lift --security.csrf

// Turn off CSRF support
sails lift --no-security.csrf

// This won't work; it'll just try to set the value to the string "[1,2,3]"
sails lift --custom.array='[1,2,3]'
```

### Custom configuration

You can also leverage Sails's configuration loader to manage your own custom settings.  See [sails.config.custom](https://sailsjs.com/documentation/reference/configuration/sails-config-custom) for more information.



### Configuring the command line interface

When it comes to configuration, most of the time you'll be focused on managing the runtime settings for a particular app: the port, database setup, and so forth.  However it can also be useful to customize the Sails CLI itself; to simplify your workflow, reduce repetitive tasks, perform custom build automation, etc.  Thankfully, Sails v0.10 added a powerful new tool to do just that.

The [`.sailsrc` file](https://sailsjs.com/documentation/anatomy/.sailsrc) is unique from other configuration sources in Sails in that it may also be used to configure the Sails CLI&mdash;either system-wide, for a group of directories, or only when you are `cd`'ed into a particular folder.  The main reason to do this is to customize the [generators](https://sailsjs.com/documentation/concepts/extending-sails/Generators) that are used when `sails generate` and `sails new` are run, but it can also be useful to install your own custom generators or apply hard-coded config overrides.

And since Sails will look for the "nearest" `.sailsrc` in the ancestor directories of the current working directory, you can safely use this file to configure sensitive settings you can't check in to your cloud-hosted code repository (_like your **database password**_.)  Just include a `.sailsrc` file in your "$HOME" directory.  See [the docs on `.sailsrc`](https://sailsjs.com/documentation/anatomy/.sailsrc) files for more information.


### Order of precedence for configuration

Depending on whether you're starting a Sails app from the command line using `sails lift` or `node app.js`, or programmatically using [`sails.lift()`](https://sailsjs.com/documentation/reference/application/advanced-usage/sails-lift) or [`sails.load()`](https://sailsjs.com/documentation/reference/application/advanced-usage/sails-load), Sails will draw its configuration from a number of sources, in a certain order.

##### Order of precedence when starting via `sails lift` or `node app.js` (in order from highest to lowest priority):

+ command line options parsed by [minimist](https://github.com/substack/minimist/tree/0.0.10); e.g. `sails lift --custom.mailgun.apiToken='foo'` becomes `sails.config.custom.mailgun.apiToken`
+ [environment variables](https://en.wikipedia.org/wiki/Environment_variable) prefixed with `sails_`, and using double underlines to indicate dots; e.g.: `sails_port=1492 sails lift` ([A few more examples](https://gist.github.com/mikermcneil/92769de1e6c10f0159f97d575e18c6cf))
+ a [`.sailsrc` file](https://sailsjs.com/documentation/concepts/configuration/using-sailsrc-files) in your app's directory, or the first found looking in `../`, `../../` etc.
+ a global `.sailsrc` file in your home folder (e.g. `~/.sailsrc`).
+ any existing `config/local.js` file in your app
+ any existing `config/env/*` files in your app that match the name of your current NODE_ENV environment (defaulting to `development`)
+ any other files in your app's `config/` directory (if one exists)

##### Order of precedence when starting programmatically (in order from highest to lowest priority):

+ an optional dictionary (`{}`) of configuration overrides passed in as the first argument to `.lift()` or `.load()`
+ any existing `config/local.js` file in your app
+ any existing `config/env/*` files in your app that match the name of your current NODE_ENV environment (defaulting to `development`)
+ any other files in your app's `config/` directory (if one exists)


### Notes
> The built-in meaning of the settings in `sails.config` are, in some cases, only interpreted by Sails during the "lift" process.  In other words, changing some options at runtime will have no effect.  To change the port your app is running on, for instance, you can't just change `sails.config.port`&mdash;you'll need to change or override the setting in a configuration file or as a command line argument, etc., then restart the server.



<docmeta name="displayName" value="Configuration">
<docmeta name="nextUpLink" value="/documentation/concepts/policies">
<docmeta name="nextUpName" value="Policies">

---

### Concepts Configuration Localjsfile (`docs/concepts/Configuration/localjsfile.md`)

# The `config/local.js` file

The config/local.js file is useful for configuring a Sails app for your local environment (your laptop, for example). This would be a good place to store settings like database or email passwords that apply only to you, and shouldn't be shared with others in your organization.

These settings take precedence over all other files in `config/`, including those in the `env/` subfolder.
 
Note:
> By default, `config/local.js` is included in your `.gitignore`, so if you're using git as a version control solution for your Sails app, keep in mind that this file won't be committed to your repository!
>
> Good news is, that means you can specify configuration for your local machine in this file without inadvertently committing personal information (like database passwords) to the repo.  Plus, this prevents other members of your team from commiting their local configuration changes on top of yours.
>
> In a production environment, you'll probably want to leave this file out entirely and configure all of your production overrides using `env/production.js`, or environment variables, or a combination of both.

<docmeta name="displayName" value="The local.js file">

---

### Concepts Configuration Usingsailsrcfiles (`docs/concepts/Configuration/usingsailsrcfiles.md`)

# Using .sailsrc files

In addition to the other methods of configuring your app, you can also specify configuration for one or more apps in `.sailsrc` file(s).  These files are useful for configuring the Sails command-line, and especially for generators.  They also allow you to apply _global_ configuration settings for generators in ANY of the Sails apps you run on your computer, if desired.

When the Sails CLI runs a command, it first looks for  `.sailsrc` files (in either JSON or [.ini](http://en.wikipedia.org/wiki/INI_file) format) in the current directory and in your home folder (i.e. `~/.sailsrc`) (every newly generated Sails app comes with a boilerplate `.sailsrc` file).  Then it merges them in to its existing configuration.

> Actually, Sails looks for `.sailsrc` files in a few other places (following [rc conventions](https://github.com/dominictarr/rc#standards)).  You can put a `.sailsrc` file at any of those paths, if you want it to apply globally to all Sails apps.  That said, stick to convention when you can- the best place to put a global `.sailsrc` file is in your home directory (i.e. `~/.sailsrc`).





<docmeta name="displayName" value="Using `.sailsrc` files">

---

### Concepts Deployment Deployment (`docs/concepts/Deployment/Deployment.md`)

# Deployment

### Before you deploy

Before you launch any web application, you should ask yourself a few questions:

+ What is your expected traffic?
+ Are you contractually required to meet any uptime guarantees, e.g. a Service Level Agreement (SLA)?
+ What sorts of user agents will be "hitting" your infrastructure? These might be:
  + desktop web browsers
  + mobile web browsers (What form factors?  Tablet? Handset? Both?)
  + embedded browsers from smart TVs or gaming consoles
  + Android/iOS/Windows Phone apps
  + PhoneGap/Electron apps
  + Developers (cURL, Postman, AJAX requests, WebSocket front-end apps)
  + other devices (TVs, watches, toasters...)
+ What kinds of things will they be requesting (e.g. HTML, JSON, XML)?
+ Will you be taking advantage of realtime features with Socket.io (e.g. chat, realtime analytics, in-app notifications/messages)?
+ How are you tracking crashes and errors? Are you using `sails.log()` in combination with a hosted service like [Papertrail](https://papertrailapp.com/)?  
+ Have you tried lifting locally with the `NODE_ENV` environment variable set to "production"? (A quick way to test this out is to run `NODE_ENV=production node app` (or, as a shortcut: `sails lift --prod`).)


### Configuring your app for production

You can provide configuration which only applies in production in a [few different ways](https://sailsjs.com/documentation/reference/configuration).  Most apps find themselves using a mix of environment variables and `config/env/production.js`.  Regardless of how you go about it, this section and the [Scaling section](https://sailsjs.com/documentation/concepts/deployment/scaling) of the documentation cover the configuration settings you should review before going to production.



### Deploying on a single server

Node.js is pretty darn fast.  For many apps, one server is enough to handle the expected traffic&mdash;initailly, at least.

> This section focuses on _single-server Sails deployment_.  This kind of deployment is inherently limited in scale.  See [Scaling](https://sailsjs.com/documentation/concepts/deployment/scaling) for information about deploying your Sails/Node app behind a load balancer.

Many teams decide to deploy their production app behind a load balancer or proxy (in a PaaS like Heroku or Now, maybe, or behind an nginx server).  This is often the right approach since it helps future-proof your app in case your scalability needs change and you need to add more servers.  If you are using a load balancer or proxy, there are a few things in the list below that you can ignore:

+ Don't worry about configuring Sails to use an SSL certificate.  SSL will almost always be resolved at your load balancer/proxy server or by your PaaS provider.
+ You _probably_ don't need to worry about setting your app to run on port 80 (if not behind a proxy like nginx). Most PaaS providers automatically figure out the port for you.  If you are using a proxy server, please refer to its documentation (whether or not you need to configure the port for your Sails app depends on how you set things up and can vary widely based on your needs).

> If your app uses sockets and you're using nginx, be sure to configure it to relay websocket messages to your server. You can find guidance on proxying WebSockets in [nginx's docs on the subject](http://nginx.org/en/docs/http/websocket.html).


##### Set the `NODE_ENV` environment variable to `'production'`

Setting your app's environment config to `'production'` tells Sails to get its game face on&mdash;i.e. that your app is running in a production environment.  This is, hands down, the most important step. If you only have the time to change _one setting_ before deploying your Sails app, _this should be that setting_!

When your app is running in a production environment:
  + middleware and other dependencies baked into Sails switch to using more efficient code.
  + all of your [models' migration settings](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings) are forced to `migrate: 'safe'`.  This is a failsafe to protect against inadvertently damaging your production data during deployment.
  + your asset pipeline runs in production mode (if relevant).  Out of the box, that means your Sails app will compile all stylesheets, client-side scripts, and precompiled JST templates into minified `.css` and `.js` files to decrease page load times and reduce bandwidth consumption.
  + error messages and stack traces from `res.serverError()` will still be logged, but will not be sent in the response (this is to prevent a would-be attacker from accessing any sensitive information, such as encrypted passwords or the path where your Sails app is located on the server's file system).


>**Note:**
>If you set [`sails.config.environment`](https://sailsjs.com/documentation/reference/configuration/sails-config#?sailsconfigenvironment) to `'production'` some other way, that's totally cool.  Just note that Sails will either set the `NODE_ENV` environment variable to `'production'` for you automatically, or it will log a warning&mdash;so keep an eye on the console! The reason this environment variable is so important is that it is a universal convention in Node.js, regardless of the framework you are using.  Built-in middleware and dependencies in Sails _expect_ `NODE_ENV` to be set in production, otherwise they use their less efficient code paths that were designed for development use only.

##### Set a `sails.config.sockets.onlyAllowOrigins` value

If you have sockets enabled for your app (that is, you have the `sails-hook-sockets` module installed), then for security reasons you'll need to set `sails.config.sockets.onlyAllowOrigins` to the array of origins that should be allowed to connect to your app via websockets.  You&rsquo;ll likely set this in your app&rsquo;s `config/env/production.js` file.  See the [socket configuration documentation](https://sailsjs.com/documentation/reference/configuration/sails-config-sockets) for more info on `onlyAllowOrigins`.

##### Configure your app to run on port 80

Whether it's by using the `sails_port` environment variable, setting the `--port` command-line option, or changing your production config file(s), add the following to the top level of your Sails config:

```javascript
port: 80
```

> As mentioned above, ignore this step if your app will be running behind a load balancer or proxy.



##### Set up production database(s) for your models

If all of your app's models use the default datastore, then setting up your production database is as simple as configuring `sails.config.datastores.default` in the [config/env/production.js](https://sailsjs.com/documentation/concepts/configuration#?environmentspecific-files-config-env) file with the correct settings.

If your app is using more than one database, your process will be similar.  For every datastore used by the app, add an item to the `sails.config.datastores` dictionary in [config/env/production.js](https://sailsjs.com/documentation/concepts/configuration#?environmentspecific-files-config-env).

Keep in mind that if you are using version control (git, for example), then any sensitive credentials (such as database passwords) will be checked in to the repo if you include them in your app's configuration files.  A common solution to this problem is to provide certain sensitive configuration settings as environment variables.  See [Configuration](https://sailsjs.com/documentation/concepts/configuration) for more information.

If you are using a relational database such as MySQL, there is an additional step.  Remember how Sails sets all your models to `migrate:safe` when run in production?  That means no auto-migrations are run when lifting the app... which means that by default your tables won't exist.  A common approach in dealing with this during the first-time setup of a relational database for your Sails app is as follows:
  + Create the database on the production database server (e.g. `frenchfryparty`).
  + Configure your app locally to use this production database, but _don't set the environment to `'production'`, and leave your models' configuration set to `migrate: 'alter'`_.  Now run `sails lift` **once**-- and when the local server finishes lifting, kill it.
    + **Be careful!**  You should only do this when there is _no data_ in the production database.

If this makes you nervous or if you can't connect to the production database remotely, you can skip the steps above.  Instead, simply dump your local schema and import it into the production database.


##### Enable CSRF protection

Protecting against CSRF is an important security measure for Sails apps.  If you haven't already been developing with CSRF protection enabled (see [`sails.config.security.csrf`](https://sailsjs.com/documentation/reference/configuration/sails-config-security#?sailsconfigsecuritycsrf)), be sure to [enable CSRF protection](https://sailsjs.com/documentation/concepts/security/csrf#?enabling-csrf-protection) before going to production.



##### Enable SSL

If your API or website does anything that requires authentication, you should use SSL in production.  To configure your Sails app to use an SSL certificate, use [`sails.config.ssl`](https://sailsjs.com/documentation/reference/configuration/sails-config).

> As mentioned above, ignore this step if your app will be running behind a load balancer or proxy.



##### Lift your app

The last step of deployment is actually starting the server. For example:

```bash
NODE_ENV=production node app.js
```

Or if you're more comfortable with command-line options you can use `--prod`:

```bash
node app.js --prod
# (Sails will set `NODE_ENV` automatically)
```

As you can see, instead of `sails lift` you should start your Sails app with `node app.js` in production.  This way, instead of relying on having access to the `sails` command-line tool, your app just runs the `app.js` file bundled in your Sails app (which does the same thing).


##### ...And keep it lifted

Unless you're deploying to a PaaS like Heroku, you will want to use a tool like [`pm2`](http://pm2.keymetrics.io/) or [`forever`](https://github.com/foreverjs/forever) to make sure your app server will start back up if it crashes.  Regardless of the daemon you choose, you'll want to make sure that it starts the server as described above.



### Next steps
+ [Security](https://sailsjs.com/documentation/concepts/security)
+ [Hosting options](https://sailsjs.com/documentation/concepts/deployment/hosting)
+ [Scaling your Sails/Node.js app](https://sailsjs.com/documentation/concepts/deployment/scaling)
+ [Complete API reference](https://sailsjs.com/documentation/reference)


<docmeta name="displayName" value="Deployment">

---

### Concepts Deployment FAQ (`docs/concepts/Deployment/FAQ.md`)

# FAQ


### Can I use environment variables?

Yes! Like any Node app, your environment variables are available as `process.env`.

Sails also comes with built-in support for creating your own custom configuration settings that will be exposed directly on `sails.config`.  And whether custom or built-in, any of the configuration properties in `sails.config` can be overridden using environment variables.  See the conceptual documentation on [Configuration](https://sailsjs.com/documentation/concepts/configuration) for details.


### Where do I put my production database credentials?  Other settings?

The easiest way to add configuration to your Sails app is by modifying the files in `config/` or adding new ones. Sails supports environment-specific configuration loading out of the box, so you can use `config/env/production.js`.  Again, see the conceptual documentation on [Configuration](https://sailsjs.com/documentation/concepts/configuration) for details.

But sometimes you don't want to put certain configuration information into your repository.  **The best place to put this kind of configuration is in environment variables.**

That said, for development (e.g. on your laptop) using environment variables can sometimes be cumbersome.  So for your other deployment/machine-specific settings, namely any kind of credentials you want to keep private, you can also use your `config/local.js` file.  This file is included in your `.gitignore` file by default, which helps prevent you from inadvertently commiting your credentials to your code repository.

**config/local.js**
```javascript
// Local configuration
// 
// Included in the .gitignore by default,
// this is where you include configuration overrides for your local system
// or for a production deployment.
//
// For example, to use port 80 on the local machine, override the `port` config
module.exports = {
    port: 80,
    environment: 'production',
    adapters: {
        mysql: {
            user: 'root',
            password: '12345'
        }
    }
}
```



### How do I get my Sails app on the server?

If you are using a Paas like Heroku or Modulus, it's easy: just follow their instructions!

Otherwise, get the IP address of your server and `ssh` onto it.  Then `npm install sails` and `npm install forever` to install Sails and `forever` globally from NPM for the first time on the server. Finally `git clone` your project (or `scp` it onto the server if it's not in a git repo) into a new folder on the server, `cd` into it, and then run `forever start app.js`.


### What should I expect as far as performance?

Baseline performance in Sails is comparable to what you'd expect from a standard Node.js/Express application.  In other words, it's fast!  We've done some optimizations ourselves in Sails core, but our primary focus is not messing up what we get for free from our dependencies.  For a quick and dirty benchmark, see [http://serdardogruyol.com/sails-vs-rails-a-quick-and-dirty-benchmark](http://serdardogruyol.com/sails-vs-rails-a-quick-and-dirty-benchmark).

The most common performance bottleneck in production Sails applications is the database.  Over the lifetime of an application with a growing user base, it becomes increasingly important to set up good indexes on your tables/collections and use queries which return paginated results.  Eventually, as your production database grows to contain tens of millions of records, you will start to locate and optimize slow queries by hand (either by calling [`.query()`](https://sailsjs.com/documentation/reference/waterline-orm/models/query) or [`.native()`](https://sailsjs.com/documentation/reference/waterline-orm/models/native), or by using the underlying database driver from NPM).  


### What's this warning about the connect session memory store?

If you are using sessions in your Sails app, you should not use the built-in memory store in production.  The memory session store is a development-only tool that does not scale to multiple servers; even if you only have one server it is not particularly performant (see [#3099](https://github.com/balderdashy/sails/issues/3099) and [#2779](https://github.com/balderdashy/sails/issues/2779)).

For instructions on configuring a production session store, see [sails.config.session](https://sailsjs.com/documentation/reference/configuration/sails-config-session).  If you want to disable session support altogether, turn off the `session` hook in your app's `.sailsrc` file:
```javascript
"hooks": {
  "session": false
}
```


<docmeta name="displayName" value="FAQ">

---

### Concepts Deployment Hosting (`docs/concepts/Deployment/Hosting.md`)

# Hosting

Here is a non-comprehensive list of Node/Sails hosting providers and a few available community tutorials.  Keep in mind that, most of the time, the process for deploying your Sails app is exactly the same as it would be for any other Node.js app.  Just be sure to take a look at the [other pages](https://sailsjs.com/documentation/concepts/deployment) in this section of the docs (as well as your app's [`config/env/production.js` file](https://sailsjs.com/documentation/anatomy/config/env/production-js)) and make any necessary adjustments before you actually deploy to production.


### Heroku

<a title="Deploy your Sails/Node.js app on Heroku" href="http://heroku.com"><img style="width:285px;" src="https://sailsjs.com/images/deployment_heroku.png" alt="Heroku logo"/></a>

Heroku offers easy, free deployment for any Sails project generated using the Web App template:

1. Create a GitHub repo and push your code up to the `master` branch.
2. Create a Heroku pipeline and a staging app within that pipeline (e.g. `my-cool-site-staging`).
3. Using the point-and-click interface, set up that staging app to auto-deploy from the `deploy` branch of your GitHub repo.
4. Under "Add-ons", set up Papertrail for logging, Redis2Go as your production session store (and for delivering socket messages, if relevant), Heroku Scheduler for scheduled jobs (if relevant), and a database host of your choosing (e.g. MySQL, PostgreSQL, MongoDB).
5. Run through `config/production.js` and `config/staging.js` in your project and set it up.  Any information you feel is too sensitive to hard-code into those files (like database credentials) can be stored in Heroku's config vars (see bundled config files for examples).
6. In the terminal, make sure you've got everything pulled/pushed and are fully in sync with the remote master branch on GitHub.
7. Deploy by typing `sails run deploy`.

You can see a demonstration of this in action [here](https://courses.platzi.com/courses/sails-js/).

##### More resources for using Heroku with Node.js/Sails.js:

+ [Platzi: Full Stack JavaScript: Pt 5 (2018)](https://courses.platzi.com/courses/sails-js/)
+ [Hello Sails.js: Hosting your Sails.js application on Heroku (2016-2017)](https://hellosails.com/hosting-your-sails-js-application-heroku/)
+ [Platzi: Develop Apps with Sails.js: Pt 2 (2015)](https://courses.platzi.com/classes/develop-apps-sails-js/)  _(see part 2)_
+ [Sails.js on Heroku (2015)](http://vort3x.me/sailsjs-heroku/)
+ [SailsCasts: Deploying a Sails App to Heroku (2013)](http://irlnathan.github.io/sailscasts/blog/2013/11/05/building-a-sails-application-ep26-deploying-a-sails-app-to-heroku/)



### Microsoft Azure

<a title="Deploy a Sails.js web app to Azure App Service" href="https://docs.microsoft.com/en-us/azure/app-service-web/app-service-web-nodejs-sails"><img style="width:350px;" src="https://sailsjs.com/images/deployment_azure.png" alt="Azure logo"/></a>

+ [Deploy a Sails.js web app to Azure App Service (2017)](https://docs.microsoft.com/en-us/azure/app-service-web/app-service-web-nodejs-sails)



### Google Cloud Platform

<a title="Deploy your Sails/Node.js app to Google Cloud Platform" href="https://cloud.google.com/nodejs/resources/frameworks/sails"><img style="width:350px;" src="https://sailsjs.com/images/deployment_googlecloud.png" alt="Google Cloud Platform logo"/></a>

Using Google Cloud Platform means that your apps run on the same infrastructure that powers all of Google's products, so you can be confident that they'll scale seamlessly&mdash;no matter how many users you have.

+ [Run Sails.js on Google Cloud Platform (2016)](https://cloud.google.com/nodejs/resources/frameworks/sails)

+ [A couple of Googlers demonstrate and deploy their app built on Sails.js and GO in a talk called `runtime:yours` at Google Cloud Platform Live (2014)](https://www.facebook.com/sailsjs/posts/721341477911963)


### DigitalOcean

<a title="DigitalOcean" href="https://aws.amazon.com/"><img style="width:225px;" src="https://sailsjs.com/images/deployment_digitalocean.png" alt="DigitalOcean logo"/></a>

+ [Troubleshooting: Can't install Sails.js on DigitalOcean (2017)](https://www.digitalocean.com/community/questions/can-t-install-sails-js)
+ [How to use PM2 to set up a Node.js production environment on an Ubuntu VPS (2014)](https://www.digitalocean.com/community/articles/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps)
+ [How to create a Node.js app using Sails.js on an Ubuntu VBS (2013)](https://www.digitalocean.com/community/articles/how-to-create-an-node-js-app-using-sails-js-on-an-ubuntu-vps)




### Amazon Web Services (AWS)

<a title="Amazon Web Services (AWS)" href="https://aws.amazon.com/"><img style="width:275px;" src="https://sailsjs.com/images/deployment_aws.png" alt="AWS logo"/></a>


+ [Creating a Sails.js application on AWS (2017)](http://bussing-dharaharsh.blogspot.com/2013/08/creating-sailsjs-application-on-aws-ami.html) _(see also [this question on ServerFault](http://serverfault.com/questions/531560/creating-an-sails-js-application-on-aws-ami-instance))_
+ [Your own mini-Heroku on AWS (2014)](http://blog.grio.com/2014/01/your-own-mini-heroku-on-aws.html)



### PM2 (KeyMetrics)

<a title="About PM2" href="http://pm2.keymetrics.io/"><img style="width:285px;" src="https://sailsjs.com/images/deployment_pm2.png" alt="PM2 logo"/></a>

+ [Deploying with PM2](http://devo.ps/blog/goodbye-node-forever-hello-pm2/)

> Note: PM2 isn't really a hosting platform, but it's worth mentioning in this section just so you're aware of it.


### OpenShift (Red Hat)

<a href="https://www.openshift.com/"><img style="width:350px;" alt="Red Hat™ OpenShift logo" src="https://sailsjs.com/images/deployment_openshift.png"/></a>

+ [Deploying a Sails / Node.js application to OpenShift (2017)](https://gist.github.com/mikermcneil/b6136aa219f6d15b01a05b14cc681fcb)
+ [Listening to a different IP address on OpenShift (2017-2018)](https://coderwall.com/p/dhhfcw/sailsjs-listening-on-a-different-ip-address) _(courtesy [@otupman](https://github.com/otupman))_
+ [Get Sails/Node.js running on OpenShift (2017)](https://gist.github.com/mdunisch/4a56bdf972c2f708ccc6) _(Warning: quite out of date, but still useful for context.  Courtesy [@mdunisch](https://github.com/mdunisch).)_



### Nanobox

+ [Getting Started: A Simple Sails.js App (2017)](https://content.nanobox.io/a-simple-sails-js-example-app/) on Nanobox
+ [Quickstart: nanobox-sails](https://github.com/nanobox-quickstarts/nanobox-sails)
+ [Official Sails.js Guides](https://guides.nanobox.io/nodejs/sails/)
+ [Official Nanobox Docs](https://docs.nanobox.io)
+ [Nanobox Slack](https://slack.nanoapp.io)


### exoscale / CloudControl

+ [Deploying a Sails.js application to exoscale / CloudControl](https://github.com/exoscale/apps-documentation/blob/88d9f157093f0690f139337ff934c027482d4727/Guides/NodeJS/Sailsjs.md) _([rendered version of tutorial](https://webcache.googleusercontent.com/search?q=cache:gq8UZXarNq8J:https://community.exoscale.ch/documentation/apps/nodejs-app-sailsjs/+&cd=1&hl=en&ct=clnk&gl=us))_


### RoseHosting

 + [Install Sails.js with Apache as a reverse proxy on CentOS 7 (2016)](https://www.rosehosting.com/blog/install-sails-js-with-apache-as-a-reverse-proxy-on-centos-7/)
 + [Install Sails.js on Ubuntu (2014)](https://www.rosehosting.com/blog/install-the-sails-js-framework-on-an-ubuntu-vps/)


### More options

+ Like [Heroku](https://stackshare.io/heroku), there are many [other Platform as a Service (PaaS) solutions that support Node.js/Sails.js](https://stackshare.io/heroku/alternatives).
+ Like [Microsoft Azure](https://stackshare.io/microsoft-azure) and [EC2](https://stackshare.io/amazon-ec2), there are many [other Node.js/Sails.js-compatible "bare-metal"/IaaS cloud servers](https://stackshare.io/amazon-ec2/alternatives).
+ Like [Cloudflare](https://stackshare.io/cloudflare), there are [other great CDNs for optimized hosting of your static assets](https://stackshare.io/cloudflare/alternatives).

<docmeta name="displayName" value="Hosting">

---

### Concepts Deployment Scaling (`docs/concepts/Deployment/Scaling.md`)

# Scaling

If you have the immediate expectation of lots of traffic to your application (or better yet, you already have the traffic),
you'll want to set up a scalable architecture that will allow you to add servers as more and more requests hit your app.

### Performance

In production, Sails performs like any Connect, Express or Socket.io app ([example](http://serdardogruyol.com/?p=111)).  If you have your own benchmark you'd like to share, please write a blog post or article and tweet [@sailsjs](http://twitter.com/sailsjs).  But benchmarks aside, keep in mind that most performance and scalability metrics are application-specific.  The actual performance of your app will have a lot more to do with the way you implement your business logic and model calls than it will about the underlying framework you are using.



### Example architecture

```
                             ....
                    /  Sails.js server  \      /  Database (e.g. Mongo, Postgres, etc)
Load Balancer  <-->    Sails.js server    <-->    Socket.io message queue (Redis)
                    \  Sails.js server  /      \  Session store (Redis, Mongo, etc.)
                             ....
```


### Preparing your app for a clustered deployment

Node.js (and consequently Sails.js) apps scale horizontally. It's a powerful, efficient approach, but it involves a tiny bit of planning. At scale, you'll want to be able to copy your app onto multiple Sails.js servers and throw them behind a load balancer.

One of the big challenges of scaling an application is that these sorts of clustered deployments cannot share memory, since they are on physically different machines. On top of that, there is no guarantee that a user will "stick" with the same server between requests (whether HTTP or sockets), since the load balancer will route each request to the Sails server with the most available resources. The most important thing to remember about scaling a server-side application is that it should be **stateless**.  That means you should be able to deploy the same code to _n_ different servers, expecting any given incoming request handled by any given server, and everything should still work.  Luckily, Sails apps come ready for this kind of deployment almost right out of the box.  But before deploying your app to multiple servers, there are a few things you need to do:

+ ensure none of the other dependencies you might be using in your app rely on shared memory
+ make sure the database(s) for your models (e.g. MySQL, Postgres, Mongo) are scalable (e.g. sharding/cluster)
+ **If your app uses sessions:**
  + Configure your app to use a shared session store such as Redis (simply uncomment the `adapter` option in `config/session.js`) and install the "@sailshq/connect-redis" session adapter as a dependency of your app (e.g. `npm install @sailshq/connect-redis --save`).
  + For more information about configuring your session store for production, see the [sails.config.session](https://sailsjs.com/documentation/reference/configuration/sails-config-session#?production-config) docs.
+ **If your app uses sockets:**
  + Configure your app to use Redis as a shared message queue for delivering socket.io messages. Socket.io (and consequently Sails.js) apps support Redis for sockets by default, so to enable a remote redis pubsub server, uncomment the relevant lines in `config/env/production.js`.
  + Install the "@sailshq/socket.io-redis" adapter as a dependency of your app (e.g. `npm install @sailshq/socket.io-redis`)
+ **If your cluster is on a single server (for instance, using [pm2 cluster mode](http://pm2.keymetrics.io/docs/usage/cluster-mode/))**:
  + To avoid file conflict issues due to Grunt tasks, always start your apps in `production` environment and/or consider [turning Grunt off completely](https://sailsjs.com/documentation/concepts/assets/disabling-grunt).  See [here](https://github.com/balderdashy/sails/issues/3577#issuecomment-184786535) for more details on Grunt issues in single-server clusters.
  + Be careful with [`config/bootstrap.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-bootstrap) code that persists data in a database, to avoid conflicts when the bootstrap runs multiple times (once per node in the cluster).


### Deploying a Node/Sails app to a PaaS

Deploying your app to a PaaS like Heroku or Modulus is simple! Take a look at [Hosting](https://sailsjs.com/documentation/concepts/deployment/Hosting) for platform-specific information.


### Deploying your own cluster

+ Deploy multiple instances (servers running a copy of your app) behind a [load balancer](https://en.wikipedia.org/wiki/Load_balancing_(computing) (e.g. nginx).
+ Configure your load balancer to terminate SSL requests.
+ Remember that you won't need to use the SSL configuration in Sails, since the traffic will already be decrypted by the time it reaches Sails.
+ Lift your app on each instance using a daemon like `forever` or `pm2` (see https://sailsjs.com/documentation/concepts/deployment for more about daemonology).


### Optimization

Optimizing an endpoint in your Node/Sails app is exactly like optimizing an endpoint in any other server-side application; e.g. identifying and manually optimizing slow queries, reducing the number of queries, etc.  For Node apps, if you find you have a heavily trafficked endpoint that is eating up CPU, look for synchronous (blocking) model methods, services, or machines that might be getting called over and over again in a loop or recursive dive.

But remember:

> Premature optimization is the root of all evil.
> &mdash;[Donald Knuth](http://c2.com/cgi/wiki?PrematureOptimization)

No matter what tool you're using, it is important to spend your time and energy writing high quality, well documented, readable code.  That way, if/when you are forced to optimize a code path in your application, you'll find it much easier to do.



### Notes
> + You don't have to use Redis for your sessions; you can actually use any Connect or Express-compatible session store.  See [sails.config.session](sailsjs.com/documentation/reference/configuration/sails-config-session) for more information.
> + Some hosted Redis providers (such as <a href="https://elements.heroku.com/addons/redistogo" target="_blank">Redis To Go</a>) set a <a href="https://redis.io/topics/clients#client-timeouts" target="_blank">timeout for idle connections</a>.  In most cases you&rsquo;ll want to turn this off to avoid unexpected behavior in your app.  Details on how to turn off the timeout vary depending on provider, so you may have to contact their support team.

<docmeta name="displayName" value="Scaling">

---

### Concepts E Commerce E Commerce (`docs/concepts/E-commerce/E-commerce.md`)

# E-commerce

Like any web application framework, Sails can be used for e-commerce apps. Depending on your project's specific needs, you can use Sails as the base for your own custom solution, or integrate with an existing e-commerce platform.

When building a custom e-commerce solution on Sails, there are a number of possibilities for how to structure your data. A good place to start is with four [models](https://sailsjs.com/documentation/concepts/models-and-orm): `User` (already included in the "Web app" template for new Sails apps), `CartItem`, `Product`, and `Order`. By including [associations](https://sailsjs.com/documentation/concepts/models-and-orm/associations), you can track things like shopping carts and a user's individual order history.

> If the prospect of rolling custom e-commerce features from scratch is rather daunting, you may consider building your Sails app on top of an existing Sails-based platform (e.g. [Ymple](https://www.ymple.com/en/)).

<docmeta name="displayName" value="E-commerce">

---

### Concepts File Uploads File Uploads (`docs/concepts/File Uploads/File Uploads.md`)

# File uploads

Uploading files in Sails is similar to uploading files for a vanilla Node.js or Express application. However, the process may be unfamiliar if you're coming from a different server-side platform like PHP, .NET, Python, Ruby, or Java.  But fear not: the core team has gone to great lengths to make file uploads easier without sacrificing scalability or security.

Sails comes with a powerful "body parser", [Skipper](https://github.com/balderdashy/skipper), which makes it easy to implement streaming file uploads&mdash;not only to the server's filesystem (i.e. hard disk), but also to Amazon S3, MongoDB's gridfs, or any other supported file adapter.

Sails does not automatically virus scan file uploads, or do any other attempt to detect whether uploaded files might be infected, broken, or unusual.  If you allow users to upload and share files with each other, it is your responsibility to protect your users from each other.  Always assume any request coming into your server could be malicious or misrepresent itself.


### Uploading a file

Files are uploaded to HTTP web servers as _file parameters_.  In the same way that you might send a form POST to a URL with text parameters like "name", "email", and "password", you send files as file parameters like "avatar" or "newSong".

Take this simple example:

```javascript
req.file('avatar').upload(function (err, uploadedFiles) {
  // ...
});
```

Files should be uploaded inside of an [action](https://sailsjs.com/documentation/concepts/actions-and-controllers).  Below is a more in-depth example that demonstrates how you could allow users to upload an avatar image and link it to an account.  This example assumes that you've already taken care of access control in a policy, and that you're storing the id of the logged-in user in `req.session.userId`.

```
/* Detailed source-code truncated for AI context efficiency. */
```




#### Where do the files go?
When using the default `receiver`, file uploads go to the `myApp/.tmp/uploads/` directory.  This can be overridden using the `dirname` option.  Note that you'll need to specify this option both when you call the `.upload()` function and when you invoke the skipper-disk adapter (so that you are uploading to and downloading from the same place).

> Any Node.js app (or other server-side app) that receives untrusted file uploads and stores them on disk should never upload those files into paths within a Java server web root or any directory that a legacy web server might automatically dive into recursively to execute arbitrary code files that it finds.  For best results, upload files to S3 or a safe directory on disk.  Always assume any request coming into your server could be malicious or misrepresent itself.

#### Uploading to a custom folder
In the example above we upload the file to .tmp/uploads, but how can we configure it with a custom folder, say `assets/images`? We can achieve this by adding options to the upload function as shown below.

```javascript
req.file('avatar').upload({
  dirname: require('path').resolve(sails.config.appPath, 'assets/images')
},function (err, uploadedFiles) {
  if (err) return res.serverError(err);

  return res.json({
    message: uploadedFiles.length + ' file(s) uploaded successfully!'
  });
});
```

### Sending text parameters in the same form as a file upload

If you need to send text parameters along with your file upload, the simplest way is by including them in the URL.

If you must send text parameters in the body of your request, the easiest way to handle this is by using the built in Cloud SDK that comes with the "Web app" template. (This also makes JSON parameters sent alongside file uploads "just work" when they wouldn't without extra work.)

> As of Parasails v0.9.x, [the bundled Cloud SDK](https://github.com/mikermcneil/parasails/compare/v0.8.4...v0.9.0-4) properly handles additional parameters for you, so if you've generated your Sails app with the "Web app" template, you might want to make sure you're using the latest version of [`dist/parasails.js` and `dist/cloud.js`](https://github.com/mikermcneil/parasails/releases) in your project.

Regardless of what you're using on the client side, you'll need to do things a little differently than usual in your Sails action on the back end. Because we're dealing with a multipart upload, any text parameters in your request body _must be sent before any files_.  This allows Sails to run your action code while files are still uploading, rather than having to wait for them to finish (avoiding a [famous DDoS vulnerability in Express-based Node.js apps](https://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html)). See the [Skipper docs](https://github.com/balderdashy/skipper#text-parameters) for advanced information on how this works behind the scenes.

### Example

#### Generate an `api`
First we need to generate a new `api` for serving/storing files.  Do this using the sails command line tool.

```sh
$ sails generate api file

debug: Generated a new controller `file` at api/controllers/FileController.js!
debug: Generated a new model `File` at api/models/File.js!

info: REST API generated @ http://localhost:1337/file
info: and will be available the next time you run `sails lift`.
```

#### Write Controller Actions

Lets make an `index` action to initiate the file upload and an `upload` action to receive the file.

```javascript

// myApp/api/controllers/FileController.js

module.exports = {

  index: function (req,res){

    res.writeHead(200, {'content-type': 'text/html'});
    res.end(
    '<form action="http://localhost:1337/file/upload" enctype="multipart/form-data" method="post">'+
    '<input type="text" name="title"><br>'+
    '<input type="file" name="avatar" multiple="multiple"><br>'+
    '<input type="submit" value="Upload">'+
    '</form>'
    )
  },
  upload: function  (req, res) {
    req.file('avatar').upload(function (err, files) {
      if (err)
        return res.serverError(err);

      return res.json({
        message: files.length + ' file(s) uploaded successfully!',
        files: files
      });
    });
  }

};
```

### Notes
> While loading untrusted JavaScript as an `<img src="…">` [is not an XSS vulnerability in modern browsers](https://stackoverflow.com/a/46041031), the MIME type in the request headers of file uploads should never be relied upon.  Always assume any request coming into your server could be malicious or misrepresent itself.


## Read more

+ [Skipper docs](https://github.com/balderdashy/skipper)
+ [Uploading to Amazon S3](https://sailsjs.com/documentation/concepts/file-uploads/uploading-to-s-3)
+ [Uploading to Mongo GridFS](https://sailsjs.com/documentation/concepts/file-uploads/uploading-to-grid-fs)



<docmeta name="displayName" value="File uploads">

---

### Concepts File Uploads Uploading To Amazon S3 (`docs/concepts/File Uploads/uploading-to-amazon-s3.md`)

# Uploading to Amazon S3

> Please note that your Amazon S3 bucket must be created in the 'US East (N. Virginia)' region.
> If you fail to do so, the uploads will not work and you'll see an 'InvalidRequest' error from AWS.

With Sails, you can stream file uploads to Amazon S3 with very little additional configuration.


First install the [S3 Skipper adapter](https://github.com/balderdashy/skipper-s3):
```sh
npm install skipper-s3 --save
```

Then use it in one of your controllers:

```javascript
  uploadFile: function (req, res) {
    req.file('avatar').upload({
      adapter: require('skipper-s3'),
      key: 'S3 Key',
      secret: 'S3 Secret',
      bucket: 'Bucket Name'
    }, function (err, filesUploaded) {
      if (err) return res.serverError(err);
      return res.ok({
        files: filesUploaded,
        textParams: req.allParams()
      });
    });
  }
```

<docmeta name="displayName" value="Uploading to S3">

---

### Concepts File Uploads Uploading To Mongo Gridfs (`docs/concepts/File Uploads/uploading-to-mongo-gridfs.md`)

# Uploading to Mongo GridFS

Uploading files to MongoDB is possible thanks to Mongo's GridFS filesystem.  With Sails, you can accomplish this with very little additional configuration using the Skipper adapter for [MongoDB's GridFS](https://github.com/willhuang85/skipper-gridfs).

Install it with:

```sh
$ npm install skipper-gridfs --save
```

Then use it in one of your controllers:

```javascript
  uploadFile: function (req, res) {
    req.file('avatar').upload({
      adapter: require('skipper-gridfs'),
      uri: 'mongodb://[username:password@]host1[:port1][/[database[.bucket]]'
    }, function (err, filesUploaded) {
      if (err) return res.serverError(err);
      return res.ok();
    });
  }
```

<docmeta name="displayName" value="Uploading to GridFS">

---

### Concepts Globals DisablingGlobals (`docs/concepts/Globals/DisablingGlobals.md`)

# Disabling globals

Sails determines which globals to expose by looking at [`sails.config.globals`](https://sailsjs.com/documentation/reference/configuration/sails-config-globals), which is conventionallly configured in [`config/globals.js`](https://sailsjs.com/documentation/anatomy/config/globals.js).

To disable all global variables, just set the setting to `false`:

```js
// config/globals.js
module.exports.globals = false;
```

To disable _some_ global variables, specify an object instead, e.g.:

```js
// config/globals.js
module.exports.globals = {
  _: false,
  async: false,
  models: false,
  services: false
};
```

### Notes

> + Bear in mind that none of the globals, including `sails`, are accessible until _after_ sails has loaded.  In other words, you won't be able to use `sails.models.user` or `User` outside of a function (since `sails` will not have finished loading yet.)



<docmeta name="displayName" value="Disabling globals">

---

### Concepts Globals Globals (`docs/concepts/Globals/Globals.md`)

# Globals
### Overview

For convenience, Sails exposes a handful of global variables.  By default, your app's [models](https://sailsjs.com/documentation/concepts/models-and-orm), [services](https://sailsjs.com/documentation/concepts/services), and the global `sails` object are all available on the global scope, meaning you can refer to them by name anywhere in your backend code (as long as Sails [has been loaded](https://github.com/balderdashy/sails/tree/master/lib/app)).

Nothing in Sails core relies on these global variables&mdash;each and every global exposed in Sails may be disabled in `sails.config.globals` (conventionally configured in `config/globals.js`.)


### The App Object (`sails`)
In most cases, you will want to keep the `sails` object globally accessible, as it makes your app code much cleaner.  However, if you _do_ need to disable _all_ globals, including `sails`, you can get access to `sails` on the request object (`req`).

### Models and Services
Your app's [models](https://sailsjs.com/documentation/concepts/models-and-orm) and [services](https://sailsjs.com/documentation/concepts/services) are exposed as global variables using their `globalId`.  For instance, the model defined in the file `api/models/Foo.js` will be globally accessible as `Foo`, and the service defined in `api/services/Baz.js` will be available as `Baz`.

### Async (`async`) and Lodash (`_`)
Sails also exposes an instance of [lodash](http://lodash.com) as `_`, and an instance of [async](https://github.com/caolan/async) as `async`.  These commonly-used utilities are provided by default so that you don't have to `npm install` them in every new project.  Like any of the other globals in sails, they can be disabled.



<docmeta name="displayName" value="Globals">

---

### Concepts Helpers ExampleHelper (`docs/concepts/Helpers/ExampleHelper.md`)

# An example helper

A common use of helpers is to encapsulate some repeated database queries.  For example, suppose our app had a `User` model which included a field `lastActiveAt` which tracked the time of their last login.  A common task in such an app might be to retrieve the list of users most recently online.  Rather than hard-coding this query into multiple locations, we could write a helper instead:

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Usage

To call this helper from app code using the default options (in an action, for example), we would use:

```javascript
var users = await sails.helpers.getRecentUsers();
```

To alter the criteria for the returned users, we could pass in some values:

```javascript
var users = await sails.helpers.getRecentUsers(50);
```

Or, to get the 10 most recent users who have logged in since St. Patrick's Day, 2017:

```javascript
await sails.helpers.getRecentUsers(10, (new Date('2017-03-17')).getTime());
```

> Note: These values passed into a helper at runtime are sometimes called **argins**, or options, and they correspond with the key order of the helper's declared input definitions (e.g. `numUsers` and `activeSince`).

Again, chaining `.with()` in order to use named parameters:

```javascript
await sails.helpers.getRecentUsers.with({
  numUsers: 10,
  activeSince: (new Date('2017-03-17')).getTime()
});
```


##### Exceptions

Finally, to handle the `noUsersFound` exit explicitly rather than simply treating it like any other error, we can use [`.intercept()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/intercept) or [`.tolerate()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/tolerate):

```javascript
var users = await sails.helpers.getRecentUsers(10)
.tolerate('noUsersFound', ()=>{
  // ... handle the case where no users were found. For example:
  sails.log.verbose(
    'Worth noting: Just handled a request for active users during a time frame '+
    'where no users were found.  Anyway, I didn\'t think this was possible, because '+
    'our app is so cool and popular.  But there you have it.'
  );
});
```

```javascript
var users = await sails.helpers.getRecentUsers(10)
.intercept('noUsersFound', ()=>{
  return new Error('Inconceivably, no active users were found for that timeframe.');
});
```

The main advantage of using helpers is the ability to update functionality in many parts of an app by changing code in a single place.  For example, by changing the default value of `numUsers` from `5` to `15`, we update the size of the default list returned in _any_ place that uses the helper.  Also, by using well-defined inputs like `numUsers` and `activeSince`, we guarantee we&rsquo;ll get helpful errors if we accidentally use an invalid (i.e. non-numeric) value.


### Notes

A few more notes about the example `getRecentUsers()` helper above:

> * Many of the fields such as `description` and `friendlyName` are not strictly required but are immensely helpful in keeping the code maintainable, especially when sharing the helper across multiple apps.
> * The `noUsersFound` exit may or may not be helpful, depending on your app.  If you always want to perform a specific action when no users are returned (for example, redirecting to a different page), this exit would be a good idea.  On the other hand, if you simply want to tweak some text in a view based on whether or not users were returned, it might be better to just have the `success` exit and check the `length` of the returned array in your action or view code.

<docmeta name="displayName" value="Example helper">

---

### Concepts Helpers Helpers (`docs/concepts/Helpers/Helpers.md`)

# Helpers

As of v1.0, all Sails apps come with built-in support for **helpers**, simple utilities that let you share Node.js code in more than one place.  This helps you avoid repeating yourself, and makes development more efficient by reducing bugs and minimizing rewrites.  Like actions2, this also makes it much easier to create documentation for your app.

### Overview

In Sails, helpers are the recommended approach for pulling repeated code into a separate file, then reusing that code in various [actions](https://sailsjs.com/documentation/concepts/actions-and-controllers), [custom responses](https://sailsjs.com/documentation/concepts/extending-sails/custom-responses), [command-line scripts](https://www.npmjs.com/package/machine-as-script), [unit tests](https://sailsjs.com/documentation/concepts/testing), or even other helpers. You don't _have_ to use helpers&mdash;in fact you might not even need them right away.  But as your code base grows, helpers will become more and more important for your app's maintainability (plus, they're really convenient).

For example, in the course of creating the actions that your Node.js/Sails app uses to respond to client requests, you will sometimes find yourself repeating code in several places.  That can be pretty bug-prone, of course, not to mention annoying.  Fortunately, there's a neat solution: replace the duplicate code with a call to a custom helper:

```javascript
const greeting = await sails.helpers.formatWelcomeMessage('Bubba');
sails.log(greeting);
// => "Hello, Bubba!"
```

> Helpers can be called from almost anywhere in your code, as long as that place has access to the [`sails` app instance](https://sailsjs.com/documentation/reference/application).


### How helpers are defined

Here's an example of a simple, well-defined helper:

```javascript
// api/helpers/format-welcome-message.js
module.exports = {

  friendlyName: 'Format welcome message',


  description: 'Return a personalized greeting based on the provided name.',


  inputs: {

    name: {
      type: 'string',
      example: 'Ami',
      description: 'The name of the person to greet.',
      required: true
    }

  },


  fn: async function (inputs, exits) {
    const result = `Hello, ${inputs.name}!`;
    return exits.success(result);
  }

};
```

Though simple, this file displays several characteristics of a good helper: it starts with a friendly name and description that make it immediately clear what the utility does, it describes its inputs so that it&rsquo;s easy to see how the utility is used, and it accomplishes a discrete task in the simplest way possible.

> Look familiar?  Helpers follow the same specification as [shell scripts](https://sailsjs.com/documentation/concepts/shell-scripts) and [actions2](https://sailsjs.com/documentation/concepts/actions-and-controllers#?actions-2).

##### The `fn` function

The core of the helper is the `fn` function, which contains the actual code that the helper will run.  The function takes two arguments: `inputs` (a dictionary of input values, or "argins") and `exits` (a dictionary of callback functions).  The job of `fn` is to utilize and process the argins, and then trigger one of the provided exits to return control back to whatever code called the helper.  Note that, as opposed to a typical JavaScript function that uses `return` to provide output to the caller, helpers provide that result value by passing it in to `exits.success()`.

##### Inputs

A helper&rsquo;s declared _inputs_ are analogous to the parameters of a typical JavaScript function: they define the values that the code has to work with.  However, unlike standard JavaScript function parameters, inputs are validated automatically.  If a helper is called using argins of the wrong type for their corresponding inputs or missing a value for a required input, it will trigger an error.  Thus, helpers are _self-validating_.

Input for a helper are defined in the `inputs` dictionary.  Each input definition is composed of, at minimum, a `type` property.  Helper inputs support types like:

* `string` - a string value
* `number` - a number value (both integers and floats are valid)
* `boolean` - the value `true` or `false`
* `ref` - a JavaScript variable reference (can be _any_ value, including dictionaries, arrays, functions, streams, etc.)

These are the same data types (and related semantics) that you might already be accustomed to from [defining model attributes](https://sailsjs.com/documentation/concepts/models-and-orm/attributes).
So, as you might expect, you can provide a default value for an input by setting its `defaultsTo` property.  Or you can make it required by setting `required: true`.  You can even use `allowNull` and almost any of the higher-level validation rules like `isEmail`.


The arguments you pass in when calling a helper correspond with the order of keys in that helper's declared `inputs`.  Alternatively, if you'd rather pass in argins by name, use `.with()`:

```javascript
const greeting = await sails.helpers.formatWelcomeMessage.with({ name: 'Bubba' });
```

##### Exits

Exits describe all the different possible outcomes a helper can have, good or bad.  Every helper automatically supports the `error` and `success` exits.
When calling a helper, if its `fn` triggers `success`, then it will return normally.  But if its `fn` triggers some exit _other than_ `success`, then it will throw an Error (unless [`.tolerate()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/tolerate) was used).

When necessary, you can also expose other custom exits (known as "exceptions"), allowing the userland code that calls your helper to handle specific, exceptional cases.
This helps guarantee your code&rsquo;s transparency and maintainability by making it painless and easy to declare and negotiate errors.

> Exceptions (custom exits) for a helper are defined in the `exits` dictionary.  It is a good practice to provide all custom exceptions with an explicit `description` property.


Imagine a helper called &ldquo;inviteNewUser&rdquo; which exposes a custom `emailAddressInUse` exit.  The helper's `fn` might trigger this custom exit if the provided email already exists, allowing your userland code to handle this specific scenario-- without muddying up your result values or resorting to extra `try/catch` blocks.

For example, if this helper was called from within an action that has its own "badRequest" exit:

```javascript
const newUserId = sails.helpers.inviteNewUser('bubba@hawtmail.com')
.intercept('emailAddressInUse', 'badRequest');
```

> The fancy-looking shorthand above is just a quicker way to write:
>
> ```javascript
> .intercept('emailAddressInUse', (err)=>{
>   return 'badRequest';
> });
> ```
>
> As for [.intercept()](https://sailsjs.com/documentation/reference/waterline-orm/queries/intercept),  it's just another shortcut so you're not forced to write custom try/catch blocks to negotiate these errors by hand all the time.

Internally, your helper's `fn` is responsible for triggering one of its exits, either by throwing a [special exit signal](https://sailsjs.com/documentation/concepts/actions-and-controllers#?exit-signals) or by invoking an exit callback (e.g. `exits.success('foo')`).  If your helper sends back a result through the success exit (e.g. `'foo'`), then that will be the return value of the helper.

> Note: For non-success exits, Sails will use the exit's predefined description to create an appropriate JavaScript Error instance automatically, if needed.

##### Synchronous helpers

By default, all helpers are considered _asynchronous_.  While this is a safe default assumption, it's not always true. When you know for certain that your helper is _synchronous_, you can optimize performance by telling Sails using the `sync: true` property. This allows userland code to [call the helper without `await`](https://sailsjs.com/documentation/concepts/helpers#?synchronous-usage). But if you set `sync` to `true`, don't forget to change `fn: async function` to `fn: function`!

> Note: Calling an asynchronous helper without `await` _will not work_.


##### Accessing `req` in a helper

If you&rsquo;re designing a helper that parses request headers specifically for use from within actions, then you'll want to take advantage of pre-existing methods and/or properties of the [request object](https://sailsjs.com/documentation/reference/request-req).  The simplest way to allow the code in your action to pass along `req` to your helper is to define a `type: 'ref'` input:

```javascript
inputs: {

  req: {
    type: 'ref',
    description: 'The current incoming request (req).',
    required: true
  }

}
```


Then, to use your helper in your actions, you might write code like this:

```javascript
const headers = await sails.helpers.parseMyHeaders(req);
```

### Generating a helper

Sails provides a built-in generator that you can use to create a new helper automatically:

```bash
sails generate helper foo-bar
```

This will create a file `api/helpers/foo-bar.js` that can be accessed in your code as `sails.helpers.fooBar`.  The file that is initially created will be a generic helper with no inputs and just the default exits (`success` and `error`), which immediately triggers its `success` exit when executed.

### Calling a helper

Whenever a Sails app loads, it finds all of the files in `api/helpers/`, compiles them into functions, and stores them in the `sails.helpers` dictionary using the camel-cased version of the filename.  Any helper can then be invoked from your code, simply by calling it with `await`, and providing some argin values:

```javascript
const result = await sails.helpers.formatWelcomeMessage('Dolly');
sails.log('Ok it worked!  The result is:', result);
```

> This is roughly the same usage you might already be familiar with from [model methods](sailsjs.com/documentation/concepts/models-and-orm/models) like `.create()`.

##### `.timeout(ms)`

The `.timeout()` method sets a maximum number of milliseconds to wait for the helper to complete. If execution takes longer than the specified time, it will throw a `TimeoutError`.

```javascript
// Throws TimeoutError if the helper takes longer than 5 seconds
var result = await sails.helpers.someLongRunningTask()
  .timeout(5000);
```

You can use `0` to disable any timeout that may have been set by the helper's implementation.

##### `.retry(negotiationRule, retryDelaySeries)`

The `.retry()` method attaches an exponential backoff and retry strategy to the helper invocation. When the helper fails, it will automatically retry after a delay.

| Argument | Type | Description |
|----------|------|-------------|
| `negotiationRule` | String, Object, or Array | _(Optional)_ Specifies which errors should trigger a retry. Can be an error code string (e.g. `'TimeoutError'`), a dictionary (e.g. `{code: 'E_TIMEOUT'}`), or an array of rules. If omitted, retries on any error. |
| `retryDelaySeries` | Array of Numbers | _(Optional)_ An array of milliseconds to wait between each retry attempt. The length of the array determines the number of retries. Defaults to `[250, 500, 1000]` (3 retries with increasing delays). |

```javascript
// Retry up to 3 times with default delays (250ms, 500ms, 1000ms)
var result = await sails.helpers.riskyOperation()
  .retry();

// Retry only on TimeoutError
var result = await sails.helpers.externalApiCall()
  .retry('TimeoutError');

// Retry with custom exponential backoff (4 retries: 1s, 2s, 4s, 8s)
var result = await sails.helpers.flakyService()
  .retry('TimeoutError', [1000, 2000, 4000, 8000]);
```

##### Chaining `.timeout()` and `.retry()`

These methods are fully chainable with each other and with other helper modifiers like `.intercept()` and `.tolerate()`:

```javascript
var data = await sails.helpers.externalApiCall(apiPayload)
  .timeout(10000)
  .retry('TimeoutError', [1000, 2000, 5000])
  .intercept('serviceUnavailable', 'backboneError')
  .intercept((err) => {
    sails.log.error('API call failed:', err);
    return err;
  });
```

When combining `.timeout()` with `.retry()`, the timeout applies to each individual attempt, not the total elapsed time across all retries.

##### Synchronous usage

If a helper declares the `sync` property, you can also call it without `await`:

```javascript
const greeting = sails.helpers.formatWelcomeMessage('Timothy');
```

But before you remove `await`, make sure the helper is actually synchronous. Without `await` an asynchronous helper will never execute!

##### Organizing helpers
If your application uses many helpers, you might find it helpful to group related helpers into subdirectories. For example, imagine you had a number of `user` helpers and several `item` helpers, organized in the following directory structure

```
api/
 helpers/
  user/
   find-by-username.js
   toggle-admin-role.js
   validate-username.js
  item/
   set-price.js
   apply-coupon.js
```
When calling these helpers, each subfolder name (e.g. `user` and `item`) becomes an additional property layer in the `sails.helpers` object, so you can call `find-by-username.js` using `sails.helpers.user.findByUsername()` and you can call `set-price.js` with `sails.helpers.item.setPrice()`.

> For more information, you can read a [conversation between Ryan Emberling and Mike McNeil](https://www.linkedin.com/feed/update/urn:li:activity:6998946887701565440?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A6998946887701565440%2C7000154787505668096%29) which goes into more detail about this use case, including some general tips and tricks for working with custom helpers and organics.

### Handling exceptions

For more granular error handling (and even for those exceptional cases that aren't _quite_ errors) you may be used to setting some kind of error code, then sniffing out the error.  This approach works fine, but it can be time-consuming and hard to track.

Fortunately, there are a few different ways to conveniently handle errors in Sails helpers.  See the pages on [.tolerate()](https://sailsjs.com/documentation/reference/waterline-orm/queries/tolerate), [.intercept()](https://sailsjs.com/documentation/reference/waterline-orm/queries/intercept), and [special exit signals](https://sailsjs.com/documentation/concepts/actions-and-controllers#?exit-signals) for more information.




##### As much or as little as you need

While the usage in this example is excessive, it's easy to imagine a scenario in which it would be helpful to rely on custom exits like `notUnique`.  Still, you don't want to have to handle _every_ custom exit _every_ time.  Ideally, you'd only have to handle a custom exit in your userland code when necessary: whether to implement a feature of some kind or even to improve user experience or provide a better internal error message.

Luckily, Sails helpers support "automatic exit forwarding".  That means userland code can choose to integrate with _as few or as many custom exits as you like_, on a case by case basis.  In other words, when calling a helper it's OK to completely ignore its custom `notUnique` exit if you don't need it.  That way, your code remains as concise and intuitive as possible.  And if things change, you can always revise your code to handle the custom exit later.

### Next steps

+ [Explore a practical example](https://sailsjs.com/documentation/concepts/helpers/example-helper) of a helper in a Node.js/Sails app.
+ `sails-hook-organics` (which is bundled in the "Web App" template) comes with several free, open-source, and MIT-licensed helpers for many common use cases.  [Have a look!](https://npmjs.com/package/sails-hook-organics)
+ [Click here](https://sailsjs.com/support) if you're unsure about helpers, or if you want to see more tutorials and examples.

<docmeta name="displayName" value="Helpers">
<docmeta name="nextUpLink" value="/documentation/concepts/deployment">
<docmeta name="nextUpName" value="Deployment">

---

### Concepts Internationalization Internationalization (`docs/concepts/Internationalization/Internationalization.md`)

# Internationalization

### Overview

If your app will touch people or systems from all over the world, internationalization and localization (also known as "i18n") may be an important part of your international strategy.  This is particularly important for applications whose main user base is split across different languages: for example a tutorial site providing both Spanish and English content, or an online store with customers all over Quebec and British Columbia.

Fortunately, Sails provides built-in support for detecting user language preferences and translating static words/sentences.  As of Sails v1, this is implemented using the lightweight [`i18n-node-2` package](https://www.npmjs.com/package/i18n-2).  This package provides several additional options beyond what is covered here, which you can read about in its README file.  But for many Node.js/Sails.js apps with basic internationalization requirements, the simple usage below is all you'll need.

### Usage

In Sails, it's easy to translate words and phrases using the locale specified in the request header:

From a view:
```ejs
<h1> <%= __('Hello') %> </h1>
<h1> <%= __('Hello %s, how are you today?', 'Mike') %> </h1>
<p> <%= i18n('That\'s right-- you can use either i18n() or __()') %> </p>
```


##### Overriding language headers

Sometimes, it is useful to override browser/device language headers -- for example, if you want to allow a user to set their own language preference.  Whether such a preference is session-based or associated with their account in the database, this is pretty straightforward to accomplish using [`req.setLocale()`](https://sailsjs.com/documentation/reference/request-req/req-set-locale).


##### Internationalizing a shell script

Finally, if you are building a [command-line script](https://sailsjs.com/documentation/concepts/shell-scripts) using Sails, or pursuing some other advanced use case, you can also translate abritrary strings to the [configured default locale](https://sailsjs.com/documentation/reference/configuration/sails-config-i-18-n) from almost anywhere in your application using `sails.__`:

```javascript
sails.__('Welcome');
// => 'Bienvenido'

sails.__('Welcome, %s', 'Mary');
// => 'Bienvenido, Mary'
```



### Locales

See [**Concepts > Internationalization > Locales**](https://sailsjs.com/documentation/concepts/internationalization/locales) for more information about creating your locale files (aka "stringfiles").


### Additional options

Settings for localization/internationalization may be configured in [`config/i18n.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-i-18-n).  The most common reason you'll need to modify these settings is to edit the list of your app's supported locales.

For more information on configuring your Node.js/Sails.js app's internationalization settings, see [sails.config.i18n](https://sailsjs.com/documentation/reference/configuration/sails-config-i-18-n).


### Disabling or customizing Sails' default internationalization support

Of course you can always `require()` any Node modules you like, anywhere in your project, and use any internationalization strategy you want.

But worth noting is that since Sails implements [node-i18n-2](https://github.com/jeresig/i18n-node-2) integration in the [i18n hook](https://sailsjs.com/documentation/concepts/Internationalization), you can completely disable or override it using the [`loadHooks`](https://github.com/balderdashy/sails/blob/master/docs/PAGE_NEEDED.md) and/or [`hooks`](https://github.com/balderdashy/sails/blob/master/docs/PAGE_NEEDED.md) configuration options.


### Translating dynamic content

See [**Concepts > Internationalization > Translating dynamic content**](https://sailsjs.com/documentation/concepts/internationalization/translating-dynamic-content).


### What about i18n on the client?

The above technique works great out of the box for server-side views. But what about rich client apps that serve static HTML templates from a CDN or static host? 

Well, the easiest option is just to keep internationalizing from your server-rendered views.  But if you'd rather not do that, there are [lots of different options available](https://web.archive.org/web/20160505184006/https://stackoverflow.com/questions/9640630/javascript-i18n-internationalization-frameworks-libraries-for-client-side-use) for client-side internationalization.  Like other client-side technologies, you should have no problem integrating any of them with Sails.

> If you'd prefer not to use an external internationalization library, you can actually reuse Sails' i18n support to help you get your translated templates to the browser.  If you want to use Sails to internationalize your _client-side templates_, put your front-end templates in a subdirectory of your app's `/views` folder.
> + In development mode, you should retranslate and precompile your templates each time the relevant stringfile or template changes using grunt-contrib-watch, which is already installed by default in new Sails projects.
> + In production mode, you'll want to translate and precompile all templates on lift(). In loadtime-critical scenarios (e.g. mobile web apps) you can even upload your translated, precompiled, minified templates to a CDN like Cloudfront for further performance gains.


<docmeta name="displayName" value="Internationalization">

---

### Concepts Internationalization Locales (`docs/concepts/Internationalization/Locales.md`)

# Locales

### Overview

The i18n hook reads JSON-formatted translation files from your project's "locales" directory (`config/locales` by default).  Each file corresponds with a [locale](http://en.wikipedia.org/wiki/Locale) (usually a language) that your Sails backend will support.

These files contain locale-specific strings (as JSON key-value pairs) that you can use in your views, controllers, etc.  The name of the file should match the language that you are supporting. This allows for automatic language detection based on request headers.

Here is an example locale file (`config/locales/es.json`):
```json
{
    "Hello!": "Hola!",
    "Hello %s, how are you today?": "¿Hola %s, como estas?"
}
```

Locales can be accessed in controller actions and policies through `req.i18n()`, or in views through the `__(key)` or `i18n(key)` functions.

```ejs
<h1> <%= __('Welcome to PencilPals!') %> </h1>
<h2> <%= i18n('Hello %s, how are you today?', 'Pencil Maven') %> </h2>
<p> <%= i18n('That\'s right-- you can use either i18n() or __()') %> </p>
```

Note that the keys in your stringfiles (e.g. "Hello %s, how are you today?") are **case sensitive** and require exact matches.  There are a few different schools of thought on the best approach here; it really depends on who is editing the stringfiles and how often.  Especially if you'll be editing the translations by hand, simpler, all-lowercase key names may be preferable for maintainability.

For example, here's another way you could approach `config/locales/es.json`:

```json
{
    "hello": "hola",
    "howAreYouToday": "cómo estás"
}
```

And here's `config/locales/en.json`:

```json
{
    "hello": "hello",
    "howAreYouToday": "how are you today"
}
```

To represent nested strings, use `.` in keys.  For example, here are some of the strings for an app's "Edit profile" page:

``` json
{
  "editProfile.heading": "Edit your profile",
  "editProfile.username.label": "Username",
  "editProfile.username.description": "Choose a new unique username.",
  "editProfile.username.placeholder": "callmethep4rtysquid"
}
```


### Detecting and/or overriding the desired locale for a request

To determine the current locale used by the request, use [`req.getLocale()`](https://github.com/jeresig/i18n-node-2/tree/9c77e01a772bfa0b86fab8716619860098d90d6f#getlocale).

To override the auto-detected language/localization preference for a request, use [`req.setLocale()`](https://sailsjs.com/documentation/reference/request-req/req-set-locale), calling it with the unique code for the new locale, e.g.:

```js
// Force the language to German for the remainder of the request:
req.setLocale('de');
// (this will use the strings located in `config/locales/de.json` for translation)
```

By default, node-i18n will detect the desired language of a request by examining its language headers.  Language headers are set in your users' browser settings, and while they're correct most of the time, you may need the flexibility to override this detected locale and provide your own.  For a deeper dive into one way you might go about implementing this, check out [this gist](https://gist.github.com/mikermcneil/0af155ed546f3ddf164b4885fb67830c).


<docmeta name="displayName" value="Locales">

---

### Concepts Internationalization TranslatingDynamicContent (`docs/concepts/Internationalization/TranslatingDynamicContent.md`)

### Translating dynamic content

If your backend is storing interlingual data (e.g. product data is entered in multiple languages via a CMS), you shouldn't rely on simple JSON locale files unless you're somehow planning on editing your locale translations dynamically.  One option is to edit the locale translations programatically, either with a custom implementation or through a translation service.  Sails/node-i18n JSON stringfiles are compatible with the format used by [webtranslateit.com](https://webtranslateit.com/en).

On the other hand, you might opt to store these types of dynamic translated strings in a database.  If so, just make sure to build your data model accordingly so you can store and retrieve the relevant dynamic data by locale id (e.g. "en", "es", "de", etc.).  That way, you can leverage the [`req.getLocale()`](https://github.com/jeresig/i18n-node-2/tree/9c77e01a772bfa0b86fab8716619860098d90d6f#getlocale) method to help you figure out which translated content to use in any given response, and keep consistent with the conventions used elsewhere in your app.
<docmeta name="displayName" value="Translating dynamic content">

---

### Concepts Logging Custom Log Messages (`docs/concepts/Logging/Custom log messages.md`)

# Custom log messages

It is often useful to emit custom log messages or events from your application code; whether you are tracking the status of outbound emails sent in the background, or just looking for a configurable alternative to calling [`console.log()`](https://nodejs.org/api/console.html#console_console_log_data) in your application code.

For convenience, Sails exposes its internal logging interface as `sails.log`.  Its usage is purposely very similar to Node's `console.log()`, but with a handful of extra features; namely support for multiple log levels with colorized, prefixed console output.

See [sails.log()](https://sailsjs.com/documentation/reference/application/sails-log) for more information and examples, or  [sails.config.log](https://sailsjs.com/documentation/reference/configuration/sails-config-log) for configuration options.


## Available methods

Each of the log methods below accepts an infinite number of arguments of any data type, seperated by commas.  Like `console.log`, data passed as arguments to the Sails logger are automatically prettified for readability using Node's [`util.inspect()`](http://nodejs.org/api/util.html#util_util_inspect_object_options). Consequently, standard Node.js conventions apply; _any_ dictionaries, errors, dates, arrays, or other data types are pretty-printed using the built-in logic in [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) (e.g. you see `{ pet: { name: 'Hamlet' } }` instead of `[object Object]`.)  Also, if you log an object that has a custom `inspect()` method, the logger will run that method automatically and write the string it returns to the console.


### sails.log.error()

Writes log output to `stderr` at the "error" log level.
Useful for tracking major errors.

```js
sails.log.error('Sending 500 ("Server Error") response.');
// -> error: Sending 500 ("Server Error") response.
```

### sails.log.warn()

Writes log output to `stderr` at the "warn" log level.
Useful for tracking information about operations that failed silently.

```js
sails.log.warn('File upload quota exceeded for user #%d.  Request aborted.', user.id);
// -> warn: File upload quota exceeded for user #94271.  Request aborted.
```


### sails.log()

_aka sails.log.debug()_

The default log function, which writes console output to `stderr` at the "debug" log level.
Useful for passing around important technical information amongst your team; or as a general alternative to `console.log()`.

```js
sails.log('This endpoint (`POST /accounts`) will be deprecated in the next few days.  Please use `POST /signup` instead. ');
// -> debug: This endpoint (`POST /accounts`) will be deprecated in the next few days.  Please use `POST /signup` instead.
```



### sails.log.info()

Writes log output to `stdout` at the "info" log level.
Useful for capturing information about your app's business logic.

```js
sails.log.info('A new user (', newUser.emailAddress, ') just signed up!');
// -> info: A new user ( irl@foobar.com ) just signed up!
```


### sails.log.verbose()

Writes log output to `stdout` at the "verbose" log level.
Useful for capturing detailed information about your app that you only need on rare occasions.

```js
sails.log.verbose('A user (IP adddress: `%s`) initiated an account transfer...', req.ip);
// -> verbose: A user (IP adddress: `10.48.1.191`) initiated an account transfer...
```


### sails.log.silly()

Writes log output to `stdout` at the "silly" log level.
Useful for capturing technical details about your app that are only useful for diagnostics and/or troubleshooting.

```js
sails.log.silly(
'Successfully fetched Account record for requesting authenticated user (`%d`).',
'Took %dms.', req.param('id'), msElapsed);
// -> silly: Successfully fetched Account record for authenticated user (`49722`). Took 41ms.
```




<docmeta name="displayName" value="Custom log messages">

---

### Concepts Logging Logging (`docs/concepts/Logging/Logging.md`)

# Logging

Sails comes with a simple, built-in logger called [`captains-log`](https://github.com/balderdashy/captains-log).  Its usage is functionally very similar to Node's [`console.log`](https://nodejs.org/api/console.html#console_console_log_data), but with a handful of extra features, namely support for multiple log levels with colorized, prefixed console output. The logger serves two purposes:
+ it emits warnings, errors, and other console output from inside the Sails framework
+ it can be used to emit [custom events/messages](https://sailsjs.com/documentation/concepts/logging/custom-log-messages) from within your application code


### Configuration
Sails' log configuration is determined by [`sails.config.log`](https://sailsjs.com/documentation/reference/configuration/sails-config-log), which is conventionally set by a generated configuration file ([`config/log.js`](https://sailsjs.com/documentation/anatomy/my-app/config/log-js)) in new Sails projects out of the box.

### Usage

```javascript
sails.log.info('I am an info-level message.');
sails.log('I am a debug-level message');
sails.log.warn('I am a warn-level message');
```

### Log levels

Using the built-in logger, Sails will write output (to stdout/stderr) for log function calls that are _at_ or _above_ the priority of the currently-configured log level.  This log level is normalized and also applied to generated output from Grunt, Socket.io, Waterline, Express, and other dependencies. The hierarchy of log levels and their relative priorities is summarized by the chart below:

| Priority | Level     | Log fns that produce visible output   |
|----------|-----------|:--------------------------------------|
| 0        | silent    | _N/A_
| 1        | error     | `.error()`            |
| 2        | warn      | `.warn()`, `.error()` |
| 3        | debug     | `.debug()`, `.warn()`, `.error()` |
| 4        | info      | `.info()`, `.debug()`, `.warn()`, `.error()` |
| 5        | verbose   | `.verbose()`, `.info()`, `.debug()`, `.warn()`, `.error()` |
| 6        | silly     | `.silly()`, `.verbose()`, `.info()`, `.debug()`, `.warn()`, `.error()` |


#### Notes
 + The [default log level](https://sailsjs.com/documentation/reference/configuration/sails-config-log) is **info**.  When your app's log level is set to "info", Sails logs limited information about the server/app's status.
 + When running automated tests for your app, it is often helpful to set the log level to **error**.
 + When the log level is set to **verbose**, Sails logs Grunt output, as well as much more detailed information on the routes, models, hooks, etc. that were loaded.
 + When the log level is set to **silly**, Sails outputs everything from **verbose** as well as internal information on which routes are being bound and other detailed framework lifecycle information, diagnostics, and implementation details.



<docmeta name="displayName" value="Logging">

---

### Concepts Middleware ConventionalDefaults (`docs/concepts/Middleware/ConventionalDefaults.md`)

# Conventional defaults

Sails comes bundled with a suite of conventional HTTP middleware, ready to use.  Naturally, you may choose to disable, override, append to, or rearrange it, but the pre-installed stack is perfectly acceptable for most apps in development or production.  Below is a list of the standard HTTP middleware functions that come bundled in Sails, in the order they execute every time the server receives an incoming HTTP request:

 HTTP Middleware Key       | Purpose
 :------------------------ |:------------
 _cookieParser_ *          | Parses the cookie header into a clean object for use in subsequent middleware and your application code.
 _session_ *               | Creates or loads a unique session object (`req.session`) for the requesting user agent based on their cookies and your [session configuration](https://sailsjs.com/documentation/reference/configuration/sails-config-session).
 **bodyParser**            | Parses parameters and binary upstreams (for streaming file uploads) from the HTTP request body using [Skipper](https://github.com/balderdashy/skipper).
 **compress**              | Compresses response data using gzip/deflate. See [`compression`](https://github.com/expressjs/compression) for details.
 **poweredBy**             | Attaches an `X-Powered-By` header to outgoing responses.
 _router_ *                | This is where the bulk of your app logic gets applied to any given request.  In addition to running `"before"` handlers in hooks (e.g. csrf token enforcement) and some internal Sails logic, this routes requests using your app's explicit routes (in [`sails.config.routes`](https://sailsjs.com/documentation/reference/configuration/sails-config-routes)) and/or route blueprints.
 _www_ *                   | Serves static files&mdash;usually images, stylesheets, scripts&mdash;in your app's "public" folder (configured in [`sails.config.paths`](https://github.com/balderdashy/sails/blob/master/docs/PAGE_NEEDED.md), conventionally [`.tmp/public/`](https://github.com/balderdashy/sails/blob/master/docs/PAGE_NEEDED.md)) using Connect's [static middleware](http://www.senchalabs.org/connect/static.html).
 **favicon**               | Serves the [browser favicon](http://en.wikipedia.org/wiki/Favicon) for your app if one is provided as `/assets/favicon.ico`.


###### Legend:

+ `*` : The middleware with an asterisk (*) should _almost never_ need to be modified or removed. Please only do so if you really understand what you're doing.


<docmeta name="displayName" value="Conventional defaults">

---

### Concepts Middleware Middleware (`docs/concepts/Middleware/Middleware.md`)

# Middleware

Technically, much of the code you&rsquo;ll write in a Sails app is _middleware_, in that runs in between the incoming request and the outgoing response&mdash;that is, in the "middle" of the request/response stack.  In an MVC framework, the term &ldquo;middleware&rdquo; typically refers more specifically to code that runs _before_ or _after_ your route-handling code (i.e. your [controller actions](https://sailsjs.com/documentation/concepts/Controllers?q=actions)), making it possible to apply the same piece of code to multiple routes or actions.  Sails has robust support for the middleware design pattern.  Depending on your needs, you may choose to implement:

* HTTP middleware&mdash;to apply code before _every_ HTTP request (see below for more details)
* [Policies](https://sailsjs.com/documentation/concepts/policies)&mdash;to apply code before one or more controller actions
* [Hooks with the `routes` feature implemented](https://sailsjs.com/documentation/concepts/extending-sails/hooks/hook-specification/routes)&mdash;to apply code before one or more route handlers
* [Custom responses](https://sailsjs.com/documentation/concepts/custom-responses)&mdash;to apply code after one or more controller actions

### HTTP middleware

Sails is fully compatible with Express / Connect middleware, which are functions that accept `req`, `res` and `next` as arguments.  Every app utilizes a configurable _middleware stack_ for handling HTTP requests.  Each time the app receives an HTTP request, its configured HTTP middleware stack runs in order.

> Note that this HTTP middleware stack is only used for "true" HTTP requests; it is ignored for **virtual requests** (e.g. requests from a live Socket.io connection).

##### Built-in HTTP middleware

By default, Sails uses a few different middleware functions to handle low-level HTTP-related tasks.  These are things like interpreting cookies, parsing HTTP request bodies, serving assets, and even attaching your app's routes.  You can read more about the default middleware stack [here](https://sailsjs.com/documentation/concepts/middleware/conventional-defaults).


### Configuring the HTTP middleware stack

Since the middleware stack comes with reasonable defaults, many Sails apps won't need to modify this configuration at all.  But for situations where you need more flexibility, Sails makes it simple to add, reorder, override, and disable the functions in your app's HTTP middleware stack.

##### Adding middleware
To configure a new custom HTTP middleware function, add a middleware function as a new key in `middleware` (e.g. "foobar"), then add the name of its key ("foobar") in the `middleware.order` array, wherever you'd like it to run in the middleware chain.

With the exception of "order", which is reserved for configuring the order of the middleware stack, any value assigned to a key of `sails.config.middleware` should be a function which takes three arguments: `req`, `res` and `next`.  This function works almost exactly like a [policy](https://sailsjs.com/documentation/concepts/policies), the only visible difference is when it's executed.

##### Initializing middleware
If you need to run some one-time set up code for a custom middleware function, you'll need to do so _before_ passing it in.  The recommended way of doing this is with a self-calling (i.e. ["immediately-invoked"](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)) wrapper function.  In the example below, note that rather than setting the value to a "req, res, next" function directly, a self-calling function is used to "wrap" some initial setup code.  That self-calling wrapper function then returns the final middleware (req,res,next) function, so it gets set on the key just the same was as if it had been passed in directly.

##### Example: using custom middleware
The following example shows how you might set up three different custom HTTP middleware functions:

```js
// config/http.js
module.exports.http = {

  middleware: {

    order: [
      'cookieParser',
      'session',
      'passportInit',            // <==== If you're using "passport", you'll want to have its two
      'passportSession',         // <==== middleware functions run after "session".
      'bodyParser',
      'compress',
      'foobar',                  // <==== We can put other, custom HTTP middleware like this wherever we want.
      'poweredBy',
      'router',
      'www',
      'favicon',
    ],


    // An example of a custom HTTP middleware function:
    foobar: (function (){
      console.log('Initializing `foobar` (HTTP middleware)...');
      return function (req,res,next) {
        console.log('Received HTTP request: '+req.method+' '+req.path);
        return next();
      };
    })(),

    // An example of a couple of 3rd-party HTTP middleware functions:
    // (notice that this time we're using an existing middleware library from npm)
    passportInit    : (function (){
      var passport = require('passport');
      var reqResNextFn = passport.initialize();
      return reqResNextFn;
    })(),

    passportSession : (function (){
      var passport = require('passport');
      var reqResNextFn = passport.session();
      return reqResNextFn;
    })()

  },
}
```

##### Overriding or disabling built-in HTTP middleware

You can also use the strategy described above to _override_ built-in middleware like the body parser (see [Customizing the body parser](https://sailsjs.com/documentation/reference/configuration/sails-config-http#?customizing-the-body-parser)).

> While this is not recommended, you can even _disable_ a built-in HTTP middleware function entirely&mdash;just remove it from the `middleware.order` array.  This allows for complete flexibility, but it should be used with care.  If you choose to disable a piece of built-in middleware, make sure you fully understand the consequences. Disabling built-in HTTP middleware may dramatically change the way your app works.


### Express middleware in Sails

One of the really nice things about Sails apps is that they can take advantage of the wealth of existing Express/Connect middleware,  but a common question arises when people _actually_ try to do this:

> _"Where do I `app.use()` this thing?"_.

In most cases, the answer is to install the Express middleware as a custom HTTP middleware in [`sails.config.http.middleware`](https://sailsjs.com/documentation/reference/configuration/sails-config-http).  This will trigger it for all HTTP requests to your Sails app, and allow you to configure the order in which it runs in relation to other HTTP middleware.

> You should never override or remove the `router` HTTP middleware.  It is built-in to Sails; without it, your app's explicit routes and blueprint routes will not work.


##### Express middleware as policies

To make Express middleware apply to only a particular action, you can also include Express middleware as a policy&mdash;just be sure that you actually want it to run for both HTTP _and_ virtual socket requests.

To do this, edit [`config/policies.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-policies) to either require and setup the middleware in an actual wrapper policy (usually a good idea) or to require it directly in your policies.js file.  The following example uses the latter strategy for brevity:

```js
var auth = require('http-auth');
var basic = auth.basic({
  realm: 'admin area'
}, function (username, password, onwards) {
  return onwards(username === 'Tina' && password === 'Bullock');
});

//...
module.exports.policies = {
  '*': [true],

  // Prevent end users from doing CRUD operations on products reserved for admins
  // (uses HTTP basic auth)
  'product/*': [auth.connect(basic)],

  // Everyone can view product pages
  'product/show': [true]
}
```










<docmeta name="displayName" value="Middleware">

---

### Concepts ORM Attributes (`docs/concepts/ORM/Attributes.md`)

# Attributes
### Overview

Model attributes are basic pieces of information about a model.  For example, a model called `Person` might have attributes named `firstName`, `lastName`, `phoneNumber`, `age`, `birthDate` and `emailAddress`.





### Defining attributes

A model's `attributes` [setting](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings) allows you to provide a set of attributes, each defined as a dictionary (a plain JavaScript object):

```javascript
// api/models/User.js
{
  attributes: {
    emailAddress: { type: 'string', required: true, },
    karma: { type: 'number', },
    isSubscribedToNewsletter: { type: 'boolean', defaultsTo: true, },
  },
}
```

Within each attribute, there are one or more keys&mdash;or options&mdash;which are used to provide additional direction to Sails and Waterline.  These attribute keys tell the model how to go about ensuring type safety, enforcing high-level validation rules, and (if you have automigrations enabled) how it should go about setting up tables or collections in your database.


##### Default attributes

You can also define default attributes that will appear in _all_ of your models, by defining `attributes` as a [default model setting](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings) (e.g. in `config/models.js`).  For example, new Sails apps come with three default attributes out of the box: `id`, `createdAt`, and `updatedAt`.

These attributes will be available in all models unless they are overridden or disabled.  To override a default attribute, define an attribute with the same name in the model definition.  To _disable_ a default attribute, define it as `false`.  For instance, to disable the default `updatedAt` attribute for a particular model:

```javascript
// api/models/ProductCategory.js
module.exports = {
  attributes: {
    updatedAt: false,
    label: { type: 'string', required: true },
  }
}
```



### Type safety


##### Type

Except for [associations](https://sailsjs.com/documentation/concepts/models-and-orm/associations), every attribute must declare a `type`.

This is the type of data that will be stored for this attribute and used for logical type safety checks of queries and results.  Here is a list of the data types supported by Sails and Waterline:

- string
- number
- boolean
- json
- ref



##### Required

If an attribute is `required: true`, then a value must always be specified for it when calling `.create()`.  This prevents the attribute value from being created as or updated to `null` or empty string ("").


##### Default values

In addition to the five data types, there are a couple of other basic guarantees that you can define for an attribute; one of these is the ability to assign it a default value.

The default value (`defaultsTo`) of an attribute only applies on `.create()`, and only when the key is omitted entirely.


```javascript
attributes: {
  phoneNumber: {
    type: 'string',
    defaultsTo: '111-222-3333'
  }
}
```

##### Allow Null

The `string`, `number`, and `boolean` data types do _not_ accept `null` as a value when creating or updating records.  In order to allow a `null` value to be set, you can toggle the `allowNull` flag on the attribute. Note that the `allowNull` flag is only valid on the data types listed above. It is _not_ valid on attributes with types `json` or `ref`, any associations, or any primary key attributes.


```javascript
attributes: {
  phoneNumber: {
    type: 'string',
    allowNull: true
  }
}
```

### Validations

In addition to basic type safety checks, Sails offers several different high-level validation rules.  For example, the `isIn` rule verifies that any new value stored for this attribute must _exactly match_ one of a few different hard-coded constants:

```javascript
unsubscribeReason: {
  type: 'string',
  isIn: ['boring', 'too many emails', 'recipes too difficult', 'other'],
  required: true
}
```

For a complete list of high-level validation rules, see [Validations](https://sailsjs.com/documentation/concepts/models-and-orm/validations).







### columnName

Inside an attribute definition, you can specify a `columnName` to force Sails/Waterline to store data for that attribute in a specific column in the configured datastore (i.e. database).  Be aware that this is not necessarily SQL-specific&mdash;it will also work for MongoDB fields, etc.

While the `columnName` property is primarily designed for working with existing/legacy databases, it can also be useful in situations where your database is being shared by other applications, or those in which you don't have access permissions to change the schema.

To store/fetch your model's `numberOfWheels` attribute into/from the `number_of_round_rotating_things` column:
```javascript
  // An attribute in one of your models:
  // ...
  numberOfWheels: {
    type: 'number',
    columnName: 'number_of_round_rotating_things'
  }
  // ...
```


Now for a more comprehensive example.

Let's say you have a `User` model in your Sails app that looks like this:

```javascript
// api/models/User.js
module.exports = {
  datastore: 'shinyNewMySQLDatabase',
  attributes: {
    name: {
      type: 'string'
    },
    password: {
      type: 'string'
    },
    email: {
      type: 'string',
      unique: true
    }
  }
};
```


Everything works great, but instead of using an existing MySQL database sitting on a server somewhere that happens to house your app's intended users...

```javascript
// config/datastores.js
module.exports = {
  // ...

  // Existing users are in here!
  rustyOldMySQLDatabase: {
    adapter: 'sails-mysql',
    url: 'mysql://ofh:Gh19R!?@db.eleven.sameness.foo/jonas'
  },
  // ...
};
```

... let's say there's a table called `our_users` in the old MySQL database that looks like this:

| the_primary_key | email_address | full_name | seriously_hashed_password|
|------|---|----|---|
| 7 | mike@sameness.foo | Mike McNeil | ranchdressing |
| 14 | nick@sameness.foo | Nick Crumrine | thousandisland |


In order to use this from Sails, you'd change your `User` model to look like this:

```javascript
// api/models/User.js
module.exports = {
  datastore: 'rustyOldMySQLDatabase',
  tableName: 'our_users',
  attributes: {
    id: {
      type: 'number',
      unique: true,
      columnName: 'the_primary_key'
    },
    name: {
      type: 'string',
      columnName: 'full_name'
    },
    password: {
      type: 'string',
      columnName: 'seriously_hashed_password'
    },
    email: {
      type: 'string',
      unique: true,
      columnName: 'email_address'
    }
  }
};
```

> You might have noticed that we also used the [`tableName`](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?tablename) property in this example.  This allows us to control the name of the table that will be used to house our data.


### Encryption at rest

##### encrypt

Setting `encrypt` allows you to decide whether this attribute should be automatically encrypted. If set to `true`, when a record is retrieved, it will still contain the encrypted value for this attribute unless [`.decrypt()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/decrypt) is used.

```javascript
attributes: {
  ssn: {
    type: 'string',
    encrypt: true
  }
}
```
> If you're using `encrypt: true` for an attribute, you won't be able to look up records by the unencrypted value.




### Automigrations

These settings are used to indicate how Sails should create the physical-level (e.g. PostgreSQL, MySQL or MongoDB) database field for an attribute when an app is lifted.

> When a model&rsquo;s `migrate` property is set to `safe`, these settings will be ignored and the database columns will remain unchanged.

##### columnType

Indicates the type of physical-level column data type to use for an attribute when Sails creates the database table. This allows you to specify types that are tied directly to how your underlying database will create them. For example, you may have an attribute that sets its `type` property to `number` and to store that in the database you want to use the column type `float`. Your attribute definition would look like:

```javascript
attributes: {
  placeInLine: {
    type: 'number',
    columnType: 'float'
  }
}
```

> * Column types are entirely database-dependent.  Be sure that the `columnType` you select corresponds to a data type that is valid for your database!  If you don&rsquo;t specify a `columnType`, the adapter will choose one for you based on the attribute&rsquo;s `type`.
> * The `columnType` value is used verbatim in the statement that creates the database column, so you can use it to specify additional options, e.g. `varchar(255) CHARACTER SET utf8mb4`.
> * If you intend to store binary data in a Sails model, you&rsquo;ll want to set the `type` of the attribute to `ref`, and then use the appropriate `columnType` for your chosen database (e.g. `mediumblob` for MySQL or `bytea` for PostgreSQL).  Keep in mind that whatever you attempt to store will have to fit in memory before being transferred to the database, as there is currently no mechanism in Sails for streaming binary data to a datastore adapter.  As an alternative to storing blobs in a database, you might consider streaming them to disk or to a remote filesystem like S3, using the [`.upload()` method](https://sailsjs.com/documentation/concepts/file-uploads).
> * Keep in mind that custom column options like `CHARACTER SET utf8mb4` in MySQL can affect a column&rsquo;s storage size. This is especially relevant when used in conjunction with the `unique` property, where you may have to specify a smaller column size to avoid errors.  See the [`unique` property](https://sailsjs.com/documentation/concepts/models-and-orm/attributes#?unique) docs below for more info.

##### autoIncrement

Sets up the attribute as an auto-increment key.  When a new record is added to the model, if a value for this attribute is not specified, it will be generated by incrementing the most recent record's value by one. Note: attributes that specify `autoIncrement` should always be of `type: 'number'`. Also bear in mind that the level of support varies across different datastores. For instance, MySQL will not allow more than one auto-incrementing column per table.

```javascript
attributes: {
  placeInLine: {
    type: 'number',
    autoIncrement: true
  }
}
```

##### unique

Ensures no two records will be allowed with the same value for the target attribute. This is an adapter-level constraint, so in most cases this will result in a unique index on the attribute being created in the underlying datastore.

```javascript
attributes: {
  username: {
    type: 'string',
    unique: true
  }
}
```

Depending on your database, when using `unique: true`, you may also need set `required: true`. 

> When using `unique: true` on an attribute with the `utf8mb4` character set in a MySQL database, you will need to set the column size manually via the [`columnType` property](https://sailsjs.com/documentation/concepts/models-and-orm/attributes#?columntype) to avoid a possible 'index too long' error.  For example: `columnType: varchar(100) CHARACTER SET utf8mb4`.










<docmeta name="displayName" value="Attributes">

---

### Concepts ORM Lifecyclecallbacks (`docs/concepts/ORM/Lifecyclecallbacks.md`)

# Lifecycle callbacks

### Overview

Lifecycle callbacks are functions that are called before or after certain model methods.  For example, you might use lifecycle callbacks to automatically compute the value of a `fullName` attribute before creating or updating a `User` record.

Sails exposes a handful of lifecycle callbacks by default:

##### Lifecycle callbacks on `.create()`

The `afterCreate` lifecycle callback will only be run on queries that have the `fetch` meta flag set to `true`. For more information on using the `meta` flags, see [Waterline Queries](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).

  - beforeCreate: fn(recordToCreate, proceed)
  - afterCreate: fn(newlyCreatedRecord, proceed)

> `beforeCreate` is also run on bulk inserts of data when you call `.createEach()`. However, `afterCreate` is **not**.

##### Lifecycle callbacks on `.update()`

The `afterUpdate` lifecycle callback will only be run on `.update()` queries that have the `fetch` meta flag set to `true`. For more information on using the `meta` flags, see [Waterline Queries](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).

  - beforeUpdate: fn(valuesToSet, proceed)
  - afterUpdate: fn(updatedRecord, proceed)

##### Lifecycle callbacks on `.destroy()`

The `afterDestroy` lifecycle callback will only be run on `.destroy()` queries that have the `fetch` meta flag set to `true`. For more information on using the `meta` flags, see [Waterline Queries](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).

  - beforeDestroy: fn(criteria, proceed)
  - afterDestroy: fn(destroyedRecord, proceed)


### Example

If you want to hash a password before saving in the database, you might use the `beforeCreate` lifecycle callback.

```javascript
// User.js
module.exports = {

  attributes: {

    username: {
      type: 'string',
      required: true
    },

    password: {
      type: 'string',
      minLength: 6,
      required: true
    }

  },


  beforeCreate: function (valuesToSet, proceed) {
    // Hash password
    sails.helpers.passwords.hashPassword(valuesToSet.password).exec((err, hashedPassword)=>{
      if (err) { return proceed(err); }
      valuesToSet.password = hashedPassword;
      return proceed();
    });//_∏_
  }
  
};
```


<docmeta name="displayName" value="Lifecycle callbacks">

---

### Concepts ORM Models (`docs/concepts/ORM/Models.md`)

# Models

A model represents a set of structured data, called records.  Models usually correspond to a table/collection in a database, attributes correspond to columns/fields, and records correspond to rows/documents.

### Defining models

By convention, models are defined by creating a file in a Sails app's `api/models/` folder:

```javascript
// api/models/Product.js
module.exports = {
  attributes: {
    nameOnMenu: { type: 'string', required: true },
    price: { type: 'string', required: true },
    percentRealMeat: { type: 'number', defaultsTo: 20, columnType: 'FLOAT' },
    numCalories: { type: 'number' },
  },
};
```

For a complete walkthrough of available options when setting up a model definition, see [Model Settings](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings), [Attributes](https://sailsjs.com/documentation/concepts/models-and-orm/attributes), and [Associations](https://sailsjs.com/documentation/concepts/models-and-orm/associations).





### Using models

Once a Sails app is running, its models may be accessed from within controller actions, helpers, tests, and just about anywhere else you normally write backend code.  This allows your code's call model methods to communicate with your database (or even with multiple databases).

There are many built-in methods available on models, the most important of which are the model methods like [.find()](https://sailsjs.com/documentation/reference/waterline/models/find) and [.create()](https://sailsjs.com/documentation/reference/waterline/models/create).  You can find detailed usage documentation for methods like these in [Reference > Waterline (ORM) > Models](https://sailsjs.com/documentation/reference/waterline-orm/models).


### Query methods

Every model in Sails has a set of methods exposed on it to allow you to interact with the database in a normalized fashion. This is the primary way of interacting with your app's data.

Since they usually have to send a query to the database and wait for a response, most model methods are **asynchronous**.  That is, they don't come back with an answer right away.  Like other asynchronous logic in JavaScript (`setTimeout()` for example), that means we need some other way of determining when they've finished executing, whether they were successful, and, if not, what kind of error (or other exceptional circumstance) occurred.

In Node.js, Sails, and JavaScript in general, the recommended way to handle this is by using [`async/await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await).

For more information about working with queries, see [Reference > Waterline (ORM) > Queries](https://sailsjs.com/documentation/reference/waterline-orm/queries).

### Resourceful pubsub methods

Sails also provides a few other "resourceful pubsub" (or RPS) methods specifically designed for performing simple realtime operations using dynamic rooms.  For more information about those methods, see [Reference > WebSockets > Resourceful PubSub](https://sailsjs.com/documentation/reference/web-sockets/resourceful-pub-sub).


### Custom model methods

In addition to the built-in functionality provided by Sails, you can also define your own custom model methods.  Custom model methods are most useful for extrapolating controller code that relates to a particular model. They allow code to be pulled out of controllers and inserted into reusuable functions that can be called from anywhere (independent of `req` or `res`).

> This feature takes advantage of the fact that models ignore unrecognized settings, so you do need to be careful about inadvertently overriding built-in methods (don't define methods named "create", for example).
>
> If you're at all unsure, write a [helper](https://sailsjs.com/documentation/concepts/helpers) instead.

Custom model methods can be synchronous or asynchronous functions, but more often than not, they're _asynchronous_.  By convention, asynchronous model methods should be `async` functions, which accept a dictionary of `options` as their argument.

For example:

```js
// in api/models/Monkey.js...

// Find monkeys with the same name as the specified person
findWithSameNameAsPerson: async function (opts) {
	var person = await Person.findOne({ id: opts.id });
	
	if (!person) {
		throw require('flaverr')({
      message: `Cannot find monkeys with the same name as the person w/ id=${opts.id} because that person does not exist.`,
      code: 'E_UNKNOWN_PERSON'
    });
	}
	
	return await Monkey.find({ name: person.name });
}
```
> Notice we didn't `try/catch` any of the code within that function. That's because we intend to leave that responsibility to whoever calls our function.

Then you can do:

```js
var monkeys = await Monkey.findWithSameNameAsPerson({id:37});
```

> For more tips, read about the incident involving [Timothy the Monkey]().

##### What about instance methods?

As of Sails v1.0, instance methods have been removed from Sails and Waterline.  While instance methods like `.save()` and `.destroy()` were sometimes convenient in app code, in Node.js at least, many users found that they led to unintended consequences and design pitfalls.

For example, consider an app that manages wedding records.  It might seem like a good idea to write an instance method on the Person model to update the `spouse` attribute on both individuals in the database.  This would allow you to write controller code like:

```js
personA.marry(personB, function (err) {
  if (err) { return res.serverError(err); }
  return res.ok();
})
```

Which looks great...until it comes time to implement a slightly different action with roughly the same logic, but where the only available data is the id of "personA" (not the entire record).  In that case, you're stuck rewriting your instance method as a static method anyway!

A better strategy is to write a custom (static) model method from the get-go.  This makes your function more reusable/versatile, since it will be accessible whether or not you have an actual record instance on hand.  You might refactor the code from the previous example to look like:

```js
Person.marry(personA.id, personB.id, function (err) {
  if (err) { return res.serverError(err); }
  return res.ok();
})
```

### Case sensitivity

Queries in Sails v1.0 are no longer forced to be case *insensitive* regardless of how the database processes the query. This leads to much-improved query performance and better index utilization. Most databases are case *sensitive* by default, but in the rare cases where they aren't and you would like to change that behavior you must modify the database to do so.

For example, MySQL will use a database collation that is case *insensitive* by default. This is different from sails-disk, so you may experience different results from development to production. In order to fix this, you can set the tables in your MySQL database to a case *sensitive* collation such as `utf8_bin`.




<docmeta name="displayName" value="Models">
<docmeta name="nextUpLink" value="/documentation/concepts/configuration">
<docmeta name="nextUpName" value="Configuration">

---

### Concepts ORM ORM (`docs/concepts/ORM/ORM.md`)

# Waterline: SQL/noSQL Data Mapper (ORM/ODM)


Sails comes installed with a powerful [ORM/ODM](http://stackoverflow.com/questions/12261866/what-is-the-difference-between-an-orm-and-an-odm) called [Waterline](https://github.com/balderdashy/waterline), a datastore-agnostic tool that dramatically simplifies interaction with one or more databases. It provides an abstraction layer on top of the underlying database, allowing you to easily query and manipulate your data _without_ writing vendor-specific integration code.

### Database Agnosticism

In schemaful databases like [Postgres](http://www.postgresql.org/), [Oracle](https://www.oracle.com/database), and [MySQL](http://www.mysql.com), models are represented by tables.  In [MongoDB](http://www.mongodb.org), they're represented by Mongo "collections".  In [Redis](http://redis.io), they're represented using key/value pairs.  Each database has its own distinct query dialect, and in some cases even requires installing and compiling a specific native module to connect to the server.  This involves a fair amount of overhead, and garners an unsettling level of [vendor lock-in](https://en.wikipedia.org/wiki/Vendor_lock-in) to a specific database; for example, if your app uses a bunch of SQL queries, it will be very hard to switch to Mongo later, or Redis, and vice versa.

Waterline query syntax floats above all that, focusing on business logic like creating new records, fetching/searching existing records, updating records, or destroying records.  No matter what database you're contacting, the usage is _exactly the same_.  Furthermore, Waterline allows you to [`.populate()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/populate) associations between models, _even if_ the data for each model lives in a different database.  That means you can switch your app's models from Mongo, to PostgreSQL, to MySQL and back again&mdash; with minimal code changes.  For the times when you need low-level, database-specific functionality, Waterline provides a query interface that allows you to talk directly to your models' underlying database driver (see [.query()](https://sailsjs.com/documentation/reference/waterline-orm/models/query) and [.native()](https://sailsjs.com/documentation/reference/waterline-orm/models/native)).



### Scenario

Let's imagine you're building an e-commerce website, with an accompanying mobile app.  Users browse products by category or search for products by keyword, then they buy them.  That's it!  Some parts of your app are quite ordinary: you have an API-driven flow for logging in, signing up, order/payment processing, resetting passwords, etc. However, you know there are a few mundane features lurking in your roadmap that will likely become more involved.  Sure enough:

##### Flexibility

_You ask the business what database they would like to use:_

> "Datab... what?  Let's not be hasty, wouldn't want to make the wrong choice.  I'll get ops/IT on it.  Go ahead and get started though."

The traditional methodology of choosing one single database for a web application/API is actually prohibitive for some production use cases. While most apps can get away with just one type of database, some applications need to maintain compatibility with existing data sets, or (if you're working on a high-volume production app) use more than one type of database for performance reasons.

Since Sails uses `sails-disk` by default, you can start building your app with zero configuration, using a local temporary file as storage.  When you're ready to switch to the real thing (and when everyone knows what that is), just change your app's [datastore configuration](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores).



##### Compatibility

_The product owner/stakeholder walks up to you and says:_

> "Oh hey by the way, the product's actually already live in our point of sale system. It's some ERP thing I guess, something like "DB2"?  Anyway, I'm sure you'll figure it out. Sounds easy right?"

Many enterprise applications must integrate with an existing database.  If you're lucky, a one-time data migration may be all that's necessary, but more commonly, the existing dataset is still being modified by other applications.  In order to build your app, you might need to marry data from multiple legacy systems, or with a separate dataset stored elsewhere.  These datasets could live on five different servers scattered across the world! One colocated database server might house a SQL database with relational data, while another cloud server might hold a handful of Mongo or Redis collections.

Sails/Waterline lets you hook up different models to different datastores, locally or anywhere on the internet.  You can build a User model that maps to a custom MySQL table in a legacy database (with weird crazy column names).  Likewise for a Product model that maps to a table in DB2, or an Order model that maps to a MongoDB collection.  Best of all, you can `.populate()` across these different datastores and adapters, so if you configure a model to live in a different database, your controller/model code doesn't need to change (note that you _will_ need to migrate any important production data manually).

##### Performance

_You're sitting in front of your laptop late at night, and you realize:_
> "How can I do keyword search?  The product data doesn't have any keywords, and the business wants search results ranked based on n-gram word sequences.  Also I have no idea how this recommendation engine is going to work.  Also if I hear the words `big data` one more time tonight I'm quitting and going back to work at the coffee shop."

So what about the "big data"?  Normally when you hear bloggers and analyst use that buzzword, you think of data mining and business intelligence.  You might imagine a process that pulls data from multiple sources, processes/indexes/analyzes it, then writes that extracted information somewhere else and either keeps the original data or throws it away.

However, there are some much more common challenges that lend themselves to the same sort of indexing/analysis needs: for example, features like "driving-direction-proximity" search, or a recommendation engine for related products.  Fortunately, a number of databases simplify specific big-data use cases. MongoDB, for instance, provides geospatial indexing, while ElasticSearch provides excellent support for indexing data for full-text search.

Using databases in the way they're intended affords tremendous performance benefits, particularly when it comes to complex report queries, searching (which is really just customized sorting), and NLP/machine learning.  Certain databases are very good at answering traditional relational business queries, while others are better suited for map/reduce-style processing of data, with both optimizations and trade-offs for blazing-fast read/writes.  This consideration is especially important as your app's user-base scales.

### Adapters

Like most MVC frameworks, Sails supports [multiple databases](https://sailsjs.com/features).  That means the syntax to query and manipulate our data is always the same, whether we're using MongoDB, MySQL, or any other supported database.

Waterline builds on this flexibility with its concept of adapters.  An adapter is a bit of code that maps methods like `find()` and `create()` to a lower-level syntax like `SELECT * FROM` and `INSERT INTO`.  The Sails core team maintains open-source adapters for a handful of the [most popular databases](https://sailsjs.com/features), and a wealth of [community adapters](https://sailsjs.com/documentation/concepts/extending-sails/adapters/available-adapters#?communitysupported-database-adapters) are also available.

Custom Waterline adapters are actually [pretty simple to build](https://github.com/balderdashy/sails-generate-adapter), and can make for more maintainable integrations: anything from a proprietary enterprise account system, to a cache, to a traditional database.


### Datastores

A **datastore** represents a particular database configuration.  This configuration object includes an adapter to use, plus information like the host, port, username, password, and so forth.  Datastores are defined in the Sails config [`config/datastores.js`](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores).

```javascript
// in config/datastores.js
// ...
{
  adapter: 'sails-mysql',
  host: 'localhost',
  port: 3306,
  user: 'root',
  password: 'g3tInCr4zee&stUfF',
  database: 'database-name'
}
// ...
```


### Analogy

Imagine a file cabinet full of completed pen-and-ink forms. All of the forms have the same fields (e.g. "name", "birthdate", "maritalStatus"), but for each form, the _values_ written in the fields vary.  For example, one form might contain "Lara", "2000-03-16T21:16:15.127Z", "single", while another form contains "Larry", "1974-01-16T21:16:15.127Z", "married".

Now imagine you're running a hot dog business.  If you were _very_ organized, you might set up your file cabinets as follows:

+ **Employee** (contains your employee records)
  + `fullName`
  + `hourlyWage`
  + `phoneNumber`
+ **Location** (contains a record for each location you operate)
  + `streetAddress`
  + `city`
  + `state`
  + `zipcode`
  + `purchases`
    + a list of all the purchases made at this location
  + `manager`
    + the employee who manages this location
+ **Purchase** (contains a record for each purchase made by one of your customers)
  + `madeAtLocation`
  + `productsPurchased`
  + `createdAt`
+ **Product** (contains a record for each of your various product offerings)
  + `nameOnMenu`
  + `price`
  + `numCalories`
  + `percentRealMeat`
  + `availableAt`
    + a list of the locations where this product offering is available.


In your Sails app, a **model** is like one of the file cabinets.  It contains **records**, which are like the forms.  `Attributes` are like the fields in each form.



### Notes
+ This documentation on models is not applicable if you are overriding the built-in ORM, [Waterline](https://github.com/balderdashy/waterline).  In that case, your models will follow whatever convention you set up, on top of whatever ORM library you're using (e.g. Mongoose).





<docmeta name="displayName" value="Models and ORM">
<docmeta name="nextUpLink" value="/documentation/concepts/models-and-orm/models">
<docmeta name="nextUpName" value="Models">

---

### Concepts ORM Querylanguage (`docs/concepts/ORM/Querylanguage.md`)

# Waterline query language

The syntax supported by Sails' model methods is called Waterline Query Language.  Waterline knows how to interpret this syntax to retrieve or mutate records from any supported database.  Under the covers, Waterline uses the database adapter(s) installed in your project to translate this language into native queries and send those queries to the appropriate database.  This means that you can use the same query with MySQL as you do with Redis or MongoDB. It also means that you can change your database with minimal (if any) changes to your application code.


### Query language basics

The criteria objects are formed using one of four types of object keys. These are the top level
keys used in a query object. They are loosely based on the criteria used in MongoDB, with a few slight variations.

Queries can be built using either a `where` key to specify attributes, or excluding it.

Using the `where` key allows you to also use [query options](https://sailsjs.com/documentation/concepts/models-and-orm/query-language#query-options), such as `limit`, `skip`, and `sort`.


```javascript
var thirdPageOfRecentPeopleNamedMary = await Model.find({
  where: { name: 'mary' },
  skip: 20,
  limit: 10,
  sort: 'createdAt DESC'
});
```
Constraints can be further joined together in a more complex example.

```javascript
var teachersNamedMaryInMaine = await Model.find({
  where: { name: 'mary', state: 'me', occupation: { contains: 'teacher' } },
  sort: [{ firstName: 'ASC'}, { lastName: 'ASC'}]
});
```

If `where` is excluded, the entire object will be treated as a `where` criteria.

```javascript
var peopleNamedMary = await Model.find({
  name: 'mary'
});
```

#### Key pairs

A key pair can be used to search records for values matching exactly what is specified. This is the base of a criteria object where the key represents an attribute on a model and the value is a strict equality check of the records for matching values.

```javascript
var peopleNamedLyra = await Model.find({
  name: 'lyra'
});
```

They can be used together to search multiple attributes.

```javascript
var waltersFromNewMexico = await Model.find({
  name: 'walter',
  state: 'new mexico'
});
```

#### Complex constraints

Complex constraints also have model attributes for keys but they also use any of the supported criteria modifiers to perform queries where a strict equality check wouldn't work.

```javascript
var peoplePossiblyNamedLyra = await Model.find({
  name : {
    'contains' : 'yra'
  }
});
```

#### In modifier

Provide an array to find records whose value for this attribute exactly matches _any_ of the specified search terms.

> This is more or less equivalent to "IN" queries in SQL, and the `$in` operator in MongoDB.

```javascript
var waltersAndSkylers = await Model.find({
  name : ['walter', 'skyler']
});
```

#### Not-in modifier

Provide an array wrapped in a dictionary under a `!=` key (like `{ '!=': [...] }`) to find records whose value for this attribute _ARE NOT_ exact matches for any of the specified search terms.

> This is more or less equivalent to "NOT IN" queries in SQL, and the `$nin` operator in MongoDB.

```javascript
var everyoneExceptWaltersAndSkylers = await Model.find({
  name: { '!=' : ['walter', 'skyler'] }
});
```

#### Or predicate

Use the `or` modifier to match _any_ of the nested rulesets you specify as an array of query pairs.  For records to match an `or` query, they must match at least one of the specified query modifiers in the `or` array.

```javascript
var waltersAndTeachers = await Model.find({
  or : [
    { name: 'walter' },
    { occupation: 'teacher' }
  ]
});
```

### Criteria modifiers

The following modifiers are available to use when building queries.

* `'<'`
* `'<='`
* `'>'`
* `'>='`
* `'!='`
* `nin`
* `in`
* `contains`
* `startsWith`
* `endsWith`

> Note that the availability and behavior of the criteria modifiers when matching against attributes with [JSON attributes](https://sailsjs.com/documentation/concepts/models-and-orm/validations#?builtin-data-types) may vary according to the database adapter you&rsquo;re using.  For instance, while `sails-postgresql` will map your JSON attributes to the <a href="https://www.postgresql.org/docs/9.4/static/datatype-json.html" target="_blank">JSON column type</a>, you&rsquo;ll need to [send a native query](https://sailsjs.com/documentation/reference/waterline-orm/datastores/send-native-query) in order to query those attributes directly.  On the other hand, `sails-mongo` supports queries against JSON-type attributes, but you should be aware that if a field contains an array, the query criteria will be run against every _item_ in the array, rather than the array itself (this is based on the behavior of MongoDB itself).

#### '<'

Searches for records where the value is less than the value specified.

```usage
Model.find({
  age: { '<': 30 }
});
```

#### '<='

Searches for records where the value is less or equal to the value specified.

```usage
Model.find({
  age: { '<=': 20 }
});
```

#### '>'

Searches for records where the value is greater than the value specified.

```usage
Model.find({
  age: { '>': 18 }
});
```

#### '>='

Searches for records where the value is greater than or equal to the value specified.

```usage
Model.find({
  age: { '>=': 21 }
});
```

#### '!='

Searches for records where the value is not equal to the value specified.

```usage
Model.find({
  name: { '!=': 'foo' }
});
```

#### in

Searches for records where the value is in the list of values.

```usage
Model.find({
  name: { in: ['foo', 'bar'] }
});
```

#### nin

Searches for records where the value is NOT in the list of values.

```usage
Model.find({
  name: { nin: ['foo', 'bar'] }
});
```

#### contains

Searches for records where the value for this attribute _contains_ the given string.

```usage
var musicCourses = await Course.find({
  subject: { contains: 'music' }
});
```

_For performance reasons, case-sensitivity of `contains` depends on the database adapter._

#### startsWith

Searches for records where the value for this attribute _starts with_ the given string.

```usage
var coursesAboutAmerica = await Course.find({
  subject: { startsWith: 'american' }
});
```

_For performance reasons, case-sensitivity of `startsWith` depends on the database adapter._

#### endsWith

Searches for records where the value for this attribute _ends with_ the given string.

```usage
var historyCourses = await Course.find({
  subject: { endsWith: 'history' }
});
```

_For performance reasons, case-sensitivity of `endsWith` depends on the database adapter._


### Query options

Query options allow you refine the results that are returned from a query. They are used
in conjunction with a `where` key. The current options available are:

* `limit`
* `skip`
* `sort`

#### Limit

Limits the number of results returned from a query.

```usage
Model.find({ where: { name: 'foo' }, limit: 20 });
```

> Note: if you set `limit` to 0, the query will always return an empty array.

#### Skip

Returns all the results excluding the number of items to skip.

```usage
Model.find({ where: { name: 'foo' }, skip: 10 });
```

##### Pagination

`skip` and `limit` can be used together to build up a pagination system.

```usage
Model.find({ where: { name: 'foo' }, limit: 10, skip: 10 });
```

> **Waterline**
>
> You can find out more about the Waterline API below:
> * [Sails.js Documentation](https://sailsjs.com/documentation/reference/waterline-orm/queries)
> * [Waterline README](https://github.com/balderdashy/waterline/blob/master/README.md)
> * [Waterline Reference Docs](https://sailsjs.com/documentation/reference/waterline-orm)
> * [Waterline Github Repository](https://github.com/balderdashy/waterline)


#### Sort

Results can be sorted by attribute name. Simply specify an attribute name for natural (ascending)
sort, or specify an `ASC` or `DESC` flag for ascending or descending orders respectively.

```usage
// Sort by name in ascending order
Model.find({ where: { name: 'foo' }, sort: 'name' });

// Sort by name in descending order
Model.find({ where: { name: 'foo' }, sort: 'name DESC' });

// Sort by name in ascending order
Model.find({ where: { name: 'foo' }, sort: 'name ASC' });

// Sort by object notation
Model.find({ where: { name: 'foo' }, sort: [{ 'name': 'ASC' }] });

// Sort by multiple attributes
Model.find({ where: { name: 'foo' }, sort: [{ name:  'ASC'}, { age: 'DESC' }] });
```


<docmeta name="displayName" value="Query language">

---

### Concepts ORM Records (`docs/concepts/ORM/Records.md`)

# Records

A _record_ is what you get back from `.find()` or `.findOne()`.  Each record is a uniquely identifiable object that corresponds one-to-one with a physical database entry; e.g. a row in Oracle/MSSQL/PostgreSQL/MySQL, a document in MongoDB, or a hash in Redis.

```js
var records = await Order.find();

console.log('Found %d records', records.length);
if (records.length > 0) {
  console.log('Found at least one record, and its `id` is:',records[0].id);
}
```


### JSON serialization

In Sails, records are just dictionaries (plain JavaScript objects), which means they can easily be represented as JSON. But you can also customize the way that records from a particular model are _stringified_ using the [`customToJSON` model setting](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?customtojson).


### Populated values

In addition to basic attribute data like email addresses, phone numbers, and birthdates, Waterline can dynamically store and retrieve linked sets of records using [associations](https://sailsjs.com/documentation/concepts/models-and-orm/associations).  When [`.populate()`](https://sailsjs.com/documentation/reference/waterline-orm/queries/populate) is called on a query, each of the resulting records will contain one or more populated values.  Each one of those populated values is a snapshot of the record (or array of records) linked to that particular association at the time of the query.

The type of a populated value depends on what kind of association it is:

+ `null`, or a plain JavaScript object (if it corresponds to a "model" association)
+ an empty array, or an array of plain JavaScript objects (if it corresponds to a "collection" association)



For example, assuming we're dealing with orders of adorable wolf puppies:

```js
var orders = await Order.find()
.populate('buyers')  // a "collection" association
.populate('seller');  // a "model" association

// this array is a snapshot of the Customers who are associated with the first Order as "buyers"
console.log(orders[0].buyers);
// => [ {id: 1, name: 'Robb Stark'}, {id: 6, name: 'Arya Stark'} ]

// this object is a snapshot of the Company that is associated with the first Order as the "seller"
console.log(orders[0].seller);
// => { id: 42941, corporateName: 'WolvesRUs Inc.' }

// this array is empty because the second Order doesn't have any "buyers"
console.log(orders[1].buyers);
// => []

// this is `null` because there is no "seller" associated with the second Order
console.log(orders[1].seller);
// => null
```

##### Expected types / values for association attributes

The table below shows what values you can expect in records returned from a `.find()` or `.findOne()` call under different circumstances.  

| &nbsp; |  without a `.populate()` added for the association | with `.populate()`, but no associated records found | with `.populate()`, with associated records found
|:--- |:--- | --- |:--- |
| Singular association (e.g. `seller`) | Whatever is in the database record for this attribute (typically `null` or a foreign key value) | `null` | A POJO representing a child record |
| Plural association (e.g. `buyers`) |  `undefined` (the key will not be present) | `[]` (an empty array) | An array of POJOs representing child records


##### Modifying populated values

To modify the populated values of a particular record or set of records, call the [.addToCollection()](https://sailsjs.com/documentation/reference/waterline-orm/models/add-to-collection), [.removeFromCollection()](https://sailsjs.com/documentation/reference/waterline-orm/models/remove-from-collection), or [.replaceCollection()](https://sailsjs.com/documentation/reference/waterline-orm/models/replace-collection) model methods.



<docmeta name="displayName" value="Records">

---

### Concepts ORM Validations (`docs/concepts/ORM/Validations.md`)

# Validations

Sails bundles support for automatic validations of your models' attributes. Any time a record is updated, or a new record is created, the data for each attribute will be checked against all of your predefined validation rules. This provides a convenient failsafe to ensure that invalid entries don't make their way into your app's database(s).

Except for `unique` (which is implemented as a database-level constraint; [see "Unique"](https://sailsjs.com/documentation/concepts/models-and-orm/validations#?unique)), all validations below are implemented in JavaScript and run in the same Node.js server process as Sails.  Also keep in mind that, no matter what validations are used, an attribute must _always_ specify one of the built-in data types (`string`, `number`, `json`, etc).

```javascript
// User
module.exports = {
  attributes: {
    emailAddress: {
      type: 'string',
      unique: true,
      required: true
    }
  }
};
```

### Built-in data types

In Sails/Waterline, model attributes always have some kind of data type guarantee.  This is above and beyond any physical-layer constraints which might exist in your underlying database&mdash;it's more about providing a way for developers to maintain reasonable assumptions about the data that goes in or comes out of a particular model.

This data type guarantee is used for logical validation and coercion of results and criteria.  Here is a list of the data types supported by Sails and Waterline:

| Data Type        | Usage                         | Description                                                  |
|:----------------:|:----------------------------- |:------------------------------------------------------------ |
| ((string))       | `type: 'string'`              | Any string.
| ((number))       | `type: 'number'`              | Any number.
| ((boolean))      | `type: 'boolean'`             | `true` or `false`.
| ((json))         | `type: 'json'`                | Any JSON-serializable value, including numbers, booleans, strings, arrays, dictionaries (plain JavaScript objects), and `null`.
| ((ref))          | `type: 'ref'`                 | Any JavaScript value except `undefined`. (Should only be used when taking advantage of adapter-specific behavior.)    |

Sails' ORM (Waterline) and its adapters perform loose validation to ensure that the values provided in criteria dictionaries and as values to `.create()` or `.update()` match the expected data type.

**NOTE:** In adapters that don't support the ((json)) type natively, the adapter must support it in other ways. For example, in MySQL the data being written to a ((json)) attribute gets `JSON.stringify()` called on it and then is stored in a column with a type set to `text`. Each time the record is returned, the data has `JSON.parse()` called on it. This is something to be aware of when considering performance and compatibility with other applications or existing data in the database. The official PostgreSQL and mongoDB adapters can read and write ((json)) data natively.


##### Null and empty string

The `string`, `number` and `boolean` data types do _not_ accept `null` as a value when creating or updating records.  In order to allow a `null` value to be set, toggle the `allowNull` flag on the attribute. The `allowNull` flag is only valid on the above data types; it is _not_ valid on attributes with types `json` or `ref`, any associations, or any primary key attributes.

Since empty string ("") is a string, it is normally supported by `type: 'string'` attributes; but there are a couple of exceptions:  primary keys (because primary keys never support empty string) and any attribute which has `required: true`.


##### Required

If an attribute is `required: true`, then a value must always be specified for it when calling `.create()`.  This also prevents a value from being set to `null` or empty string ("") when created or updated.

### Validation rules

_None_ of the following validation rules impose any additional restrictions against `null`.  That is, if `null` would be allowed normally, then enabling the `isEmail` validation rule will not cause `null` to be rejected as invalid.

Similarly, _most_ of the following validation rules don't impose any additional restrictions against empty string ("").  There are a few exceptions (`isNotEmptyString` and non-string-related rules like `isBoolean`, `isNumber`, `max`, and `min`), but otherwise, for any attribute where empty string ("") would normally be allowed, adding a validation rule will not cause it to be rejected.

In the table below, the "Compatible Attribute Type(s)" column shows what data type(s) (i.e. for the attribute definition's `type` property) are appropriate for each validation rule.  In many cases, a validation rule can be used with more than one type.  Note that the table below takes a shortcut:  if compatible with ((string)), ((number)), or ((boolean)), then the validation rule is also compatible with ((json)) and ((ref)), even if it doesn't explicitly say so.


| Name of Rule      | What It Checks For                                                                                                  | Notes On Usage                                         | Compatible Attribute Type(s) |
|:------------------|:--------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------|:----------------------------:|
| custom            | A value such that when it is provided as the first argument to the custom function, the function returns `true`.                          | [Example](https://sailsjs.com/documentation/concepts/models-and-orm/validations#?custom-validation-rules)            |  _Any_   |
| isAfter           | A value that, when parsed as a date, refers to a moment _after_ the configured JavaScript `Date` instance.          | `isAfter: new Date('Sat Nov 05 1605 00:00:00 GMT-0000')`  | ((string)), ((number))       |
| isBefore          | A value that, when parsed as a date, refers to a moment _before_ the configured JavaScript `Date` instance.         | `isBefore: new Date('Sat Nov 05 1605 00:00:00 GMT-0000')` | ((string)), ((number))       |
| isBoolean         | A value that is `true` or `false` | isBoolean: true | ((json)), ((ref)) |
| isCreditCard      | A value that is a credit card number.                                                                               | **Do not store credit card numbers in your database unless your app is PCI compliant!**  If you want to allow users to store credit card information, a safe alternative is to use a payment API like [Stripe](https://stripe.com). | ((string)) |
| isEmail           | A value that looks like an email address.                                                                           | `isEmail: true`                                         | ((string)) |
| isHexColor        | A string that is a hexadecimal color.                                                                               | `isHexColor: true`                                      | ((string)) |
| isIn              | A value that is in the specified array of allowed strings.                                                          | `isIn: ['paid', 'delinquent']`                          | ((string)) |
| isInteger         | A number that is an integer (a whole number)                                                                        | `isInteger: true`                                       | ((number)) |
| isIP              | A value that is a valid IP address (v4 or v6)                                                                       | `isIP: true`                                              | ((string)) |
| isNotEmptyString  | A value that is _not_ an empty string | `isNotEmptyString: true` | ((json)), ((ref))
| isNotIn           | A value that **is not in** the configured array.                                                                    | `isNotIn: ['profanity1', 'profanity2']`                   | ((string)) |
| isNumber          | A value that is a Javascript number | `isNumber: true` | ((json)), ((ref))
| isString          | A value that is a string (i.e. `typeof(value) === 'string'`) | `isString: true` | ((json)), ((ref))
| isURL             | A value that looks like a URL. | `isURL: true` | ((string)) |
| isUUID            | A value that looks like a UUID (v3, v4 or v5) | `isUUID: true` | ((string))
| max               | A number that is less than or equal to the configured number. | `max: 10000` | ((number)) |
| min               | A number that is greater than or equal to the configured number. | `min: 0` | ((number)) |
| maxLength         | A string that has no more than the configured number of characters. |  `maxLength: 144` | ((string)) |
| minLength         | A string that has at least the configured number of characters. | `minLength: 8` | ((string)) |
| regex             | A string that matches the configured regular expression. | `regex: /^[a-z0-9]$/i` | ((string)) |


##### Example: optional email address

Imagine that you have an attribute defined as follows:

```javascript
workEmail: {
  type: 'string',
  isEmail: true,
}
```

When you call `.create()` _or_ `.update()`, this value can be set to any valid email address (like "santa@clause.com") OR to an empty string ("").  You would _not_ be able to set it to `null`, though, because that would violate the type safety restriction imposed by `type: 'string'`.

> To make this attribute accept `null` (e.g. if you are working with a pre-existing database), change it to `type: 'json'`.  You'd normally also want to add `isString: true`, but since we already enforce `isEmail: true` in this example, there's no need to do so.
>
> A more advanced feature to keep in mind is that, depending on your database, you can choose to take advantage of [`columnType`](https://sailsjs.com/documentation/concepts/models-and-orm/attributes#?columntype) to inform Sails / Waterline which column type to define during auto-migrations (if relevant).


##### Example: required star rating

If we want to indicate that an attribute supports certain numbers, like a star rating, we might do something like this:

```javascript
starRating: {
  type: 'number',
  min: 1,
  max: 5,
  required: true,
}
```


##### Example: optional star rating

If we want to make our star rating optional, it's easiest to just remove the `required: true` flag.  If omitted, the starRating will default to zero.


##### Example: optional star rating (with `null`)

But what if the star rating can't _always_ be a number? Imagine we need to integrate with a legacy database in which star ratings could be either a number or the special null literal. In this scenario, we would like to define the `starRating` attribute to support both certain numbers and `null`.

To accomplish this, just use `allowNull`:

```javascript
starRating: {
  type: 'number',
  allowNull: true,
  min: 1,
  max: 5,
}
```

> Sails and Waterline attributes support `allowNull` for convenience, but another viable solution is to change `starRating` from `type: 'number'` to `type: 'json'`.  Remember, though, that the `json` type allows other data, like booleans, arrays, etc. If we want to explicitly protect against those data types being supported by `starRating`, we could add the `isNumber: true` validation rule:
>
>
> ```javascript
> starRating: {
>   type: 'json',
>   isNumber: true,
>   min: 1,
>   max: 5,
> }
> ```



### Unique

`unique` is different from all of the validation rules listed above.  In fact, it isn't really a validation rule at all: it is a **database-level constraint**.  More on that in a second.

If an attribute declares itself `unique: true`, then Sails ensures that no two records will be allowed with the same value.  The canonical example is an `emailAddress` attribute on a `User` model:

```javascript
// api/models/User.js
module.exports = {

  attributes: {
    emailAddress: {
      type: 'string',
      unique: true,
      required: true
    }
  }

};
```

##### Why is `unique` different from other validations?

Imagine you have 1,000,000 user records in your database.  If `unique` was implemented like other validations, every time a new user signed up for your app, Sails would need to search through _one million_ existing records to ensure that no one else was already using the email address provided by the new user.  That would be so slow that by the time we finished searching through all those records, someone else could have signed up!

Fortunately, this type of uniqueness check is perhaps the most universal feature of _any_ database.  To take advantage of that, Sails relies on the [database adapter](https://sailsjs.com/documentation/concepts/models-and-orm#?adapters) to implement support for `unique`&mdash;specifically, it adds a **uniqueness constraint** to the relevant field/column/attribute in the database itself during [auto-migration](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?migrate).  That is, while your app is set to `migrate:'alter'`, Sails will automatically generate tables/collections in the underlying database with uniqueness constraints built right in.  Once you switch to `migrate:'safe'`, updating your database constraints is up to you.

##### What about indexes?

When you start using your production database, it is always a good idea to set up indexes to boost your database's performance.  The exact process and best practices for setting up indexes varies between databases and is beyond the scope of this documentation.  That said, if you've never done this before, don't worry: it's [easier than you think](http://stackoverflow.com/a/1130/486547).

Just like everything else related to your production schema, once you set your app to use `migrate: 'safe'`, Sails leaves database indexes entirely up to you.

> Note that this means you should be sure to update your indexes alongside your uniqueness constraints when performing [manual migrations](https://github.com/BlueHotDog/sails-migrations).


### When to use validations

Validations can save you from writing many hundreds of lines of repetitive code,  but keep in mind that model validations are run for _every create or update_ in your application.  Before using a validation rule in one of your attribute definitions, make sure you are okay with it being applied _every time_ your application calls `.create()` or `.update()` to specify a new value for that attribute.  If that is _not_ the case, write code that validates the incoming values inline in your controller, or call a custom function in one of your [services](https://sailsjs.com/documentation/concepts/services) or a [model class method](https://sailsjs.com/documentation/concepts/models-and-orm/models#?model-methods-aka-static-or-class-methods).

Suppose that your Sails app allows users to sign up for an account by either (A) entering an email address and password and then confirming that email address or (B) signing up with LinkedIn.  Your `User` model might have one attribute called `manuallyEnteredEmail` and another called `linkedInEmail`.  While one of those email address attributes is required, _which_ one that is depends on how a user signs up.  In this case, your `User` model cannot use the `required: true` validation. In order to confirm that one of the two emails has been provided&mdash;and that the provided email is valid&mdash;you'll instead have to manually check these values before the relevant `.create()` and `.update()` calls in your code:

```javascript
if ( !_.isString( req.param('email') ) ) {
  return res.badRequest();
}
```

Taking this one step further, let's say your application accepts payments.  During the sign-up flow, if the user signs up with a paid plan, they must provide an email address for billing purposes (`billingEmail`), while if the user signs up with a free account, they skip that step.  On the account settings page, users on the paid plan see a "Billing Email" form field where they can customize their billing email. Users with the free plan, on the other hand, see a call to action which links to the "Upgrade Plan" page.

While these requirements seem specific, there are still unanswered questions:

- Do we update the billing email automatically when the other email address from which it was defaulted changes?
- What if the billing email had been changed at least once?
- What happens to the billing email after a user downgrades to the free plan? If that user upgrades to a paid plan again, do we request their billing email address anew or use the old one?
- What happens to the billing email when an existing user connects their LinkedIn account and a new `linkedInEmail` is saved?
- What happens to the billing email if a monthly invoice email cannot be delivered?
- What happens to the billing email if a member of your support team logs into the admin interface and changes it manually?
- What happens to the billing email if a POST request is received on the callback URL we provided to the LinkedIn API to notify our app that the user changed their email address on http://linkedin.com, saving a new `linkedInEmail`?
- What happens to the billing email when an existing user disconnects their LinkedIn account?
- Are two user accounts in the database allowed to have the same billing email?  What about the email from LinkedIn?  Or the one they entered manually?

Depending on the answers to questions like these, we might end up keeping the `required` validation on `billingEmail`, adding new attributes (like `hasBillingEmailBeenChangedManually`), or even rethinking whether we use a `unique` constraint.

### Best practices

Finally, here are a few tips:

+ Your initial decision about whether or not to use validations for a particular attribute should depend on your app's requirements and how you are calling `.update()` and `.create()`. Don't be afraid to forgo built-in validation support in favor of checking values by hand in your controllers or in a helper function.  Oftentimes this is the cleanest and most maintainable approach.
+ There's nothing wrong with adding or removing validations from your models as your app evolves, but once in production, there is one **very important exception**: `unique`.  During development, when your app is configured to use [`migrate: 'alter'`](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?migrate), you can add or remove `unique` validations at will.  However, if you are using `migrate: safe` (e.g. with your production database), you will want to update constraints/indices in your database, as well as [migrate your data by hand](https://github.com/BlueHotDog/sails-migrations).
+ It is a very good idea to take the time to fully understand your application's user interface _first_, before setting up complex validations on your model attributes.

> As much as possible, it is best to obtain or flesh out your own wireframes of your app's user interface _before_ you spend any serious amount of time implementing _any_ backend code.  Of course, this isn't always possible, and that's what the [blueprint API](https://sailsjs.com/documentation/concepts/blueprints) is for.  Applications built with a UI-centric, or "front-end first", philosophy are easier to maintain, tend to have fewer bugs, and&mdash;since mindfulness of the user experience is at their core&mdash;often have more elegant APIs.



### Custom validation rules

You can define your own custom validation rules by specifying a `custom` function in your attributes.

```javascript
// api/models/User.js
module.exports = {

  // Values passed for creates or updates of the User model must obey the following rules:
  attributes: {

    firstName: {
      // Note that a base type (in this case "string") still has to be defined, even though validation rules are in use.
      type: 'string',
      required: true,
      minLength: 5,
      maxLength: 15
    },

    location: {
      type: 'json',
      custom: function(value) {
        return _.isObject(value) &&
        _.isNumber(value.x) && _.isNumber(value.y) &&
        value.x !== Infinity && value.x !== -Infinity &&
        value.y !== Infinity && value.y !== -Infinity;
      }
    },

    password: {
      type: 'string',
      custom: function(value) {
        // • be a string
        // • be at least 6 characters long
        // • contain at least one number
        // • contain at least one letter
        return _.isString(value) && value.length >= 6 && value.match(/[a-z]/i) && value.match(/[0-9]/);
      }
    }

  }

}
```

Custom validation functions receive the incoming value to be validated as their first argument. They are expected to return `true` if valid and `false` otherwise.



##### Custom validation messages

Out of the box, Sails.js does not support custom validation messages.  Instead, your code should [look at (or "negotiate") validation errors](https://sailsjs.com/documentation/concepts/models-and-orm/errors#?usage-errors) thrown by `.create()` or `.update()` calls and take the appropriate action, whether that's sending a particular error code in your JSON response or rendering the appropriate message in an HTML error page.


<docmeta name="displayName" value="Validations">

---

### Concepts ORM Errors (`docs/concepts/ORM/errors.md`)

# Errors

When a call to any model method or helper fails, Sails throws a [JavaScript Error instance](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) whose properties can be useful in diagnosing what went wrong.

Waterline normalizes these Error instances, classifying them with consistent `err.name` values and, when applicable, `err.code`:

```js
try {
  await Something.create({…});
} catch (err) {
  // err.name
  // err.code
  // …
}
```


### Negotiating errors

Catch-all error handling, while better than nothing, often just isn't enough. (There's a big difference between "that is not a valid username" and "we aren't able to create new users at all right now".)  In order to negotiate the different kinds of errors appropriately, you'll need to be able to examine them in a granular way.

Fortunately, Sails provides some syntactic sugar for doing this out of the box, without resorting to try… catch: [.intercept()](https://sailsjs.com/documentation/reference/waterline-orm/queries/intercept) and [.tolerate()](https://sailsjs.com/documentation/reference/waterline-orm/queries/tolerate).

```javascript
await Something.create({…})
.intercept((err)=>{
 // Return a modified error here (or a special exit signal)
 // and .create() will throw that instead
 err.message = 'Uh oh: '+err.message;
 return err;
});
```


| Property       | Type          | Details            |
|:---------------|---------------|:-------------------|
| name           | ((string))    | The broad classification of the error. <br/><br/> e.g.`'UsageError'`     |
| message        | ((string))    | <em>See [.message](https://nodejs.org/dist/latest/docs/api/errors.html#errors_error_message).</em> |
| stack          | ((string))    | <em>See [.stack](https://nodejs.org/dist/latest/docs/api/errors.html#errors_error_stack).<em>     |
| _code_         | ((string?))   | A narrower classification of the error that is sometimes included.<br/><br/>e.g. `'E_UNIQUE'`       |

When using code that interacts with Waterline (usually through model methods) there are a few different kinds of error you may encounter.


### Usage errors

When an error has `name: 'UsageError'`, this indicates that a Waterline method was used incorrectly, or executed with invalid options (for example, attempting to create a new record that would violate one of your model's [high-level validation rules](https://sailsjs.com/documentation/concepts/models-and-orm/validations#?validation-rules).)

This sort of error can come from any model method.

```
err.name === 'UsageError'
```

### Adapter errors

Adapter errors usually indicate a problem in the underlying adapter, and not in the request itself. This can happen when a database goes offline, when there is a permission issue, because of some database-specific edge case, or (more rarely) a bug in the adapter. This kind of error will have `name: 'AdapterError'`.

This sort of error can come from any model method.

```
err.name === 'AdapterError'
```


##### E_UNIQUE

A uniqueness error occurs when a value that _should_ be unique matches that of another record in the database. While this is considered an adapter error, it has its own `code` to differentiate it from a normal adapter error: `code: 'E_UNIQUE'`.

This sort of error can only come from the `.create()`, `.update()`, `.addToCollection()`, and `.replaceCollection()` model methods.

```
err.code === 'E_UNIQUE'
```

### Examples

The exact strategy you use to do this in your Sails app depends on whether you're using `await`, promises, or callbacks.

##### Negotiating errors with `await`

To handle the different errors that may occur when attempting to create a new user from within an action:

```javascript
await User.create({ emailAddress: inputs.emailAddress })
// Uniqueness constraint violation
.intercept('E_UNIQUE', (err)=> {
  return 'emailAlreadyInUse';
})
// Some other kind of usage / validation error
.intercept({name:'UsageError'}, (err)=> {
  return 'invalid';
});
// If something completely unexpected happened, the error will be thrown as-is.

return exits.success();
```

##### Negotiating errors with callbacks or promise chaining

If you're not able to use `await` because you're using Node.js <= v7.9, then prepare yourself: error handling works a bit differently when [using callbacks or promise chaining](https://github.com/mikermcneil/parley/tree/49c06ee9ed32d9c55c24e8a0e767666a6b60b7e8#flow-control) instead of `await`.

> Please use `await` if at all possible!  It is much safer for your app, your code will be cleaner, and you will be happier.

For example, if you're using promise chaining, here's how you might handle the different errors that could occur when attempting to create a new user:

```javascript
User.create({
  emailAddress: req.param('emailAddress')
})
.then(function (){
  res.ok();
})
// Uniqueness constraint violation
.catch({ code: 'E_UNIQUE' }, function (err) {
  res.sendStatus(409);
})
// Some other kind of usage / validation error
.catch({ name: 'UsageError' }, function (err) {
  res.badRequest();
})
// If something completely unexpected happened.
.catch(function (err) {
  res.serverError(err);
});
```

Here's the same example, but written with traditional Node.js callbacks instead of promise chaining:

```javascript
User.create({
  emailAddress: req.param('emailAddress')
})
.exec(function (err){
  if (err && err.code === 'E_UNIQUE') {
    return res.sendStatus(409);
  } else if (err && err.name === 'UsageError') {
    return res.badRequest();
  } else if (err) {
    return res.serverError(err);
  }

  return res.ok();
});
```

> But beware [uncaught exceptions](https://github.com/mikermcneil/parley/tree/49c06ee9ed32d9c55c24e8a0e767666a6b60b7e8#handling-uncaught-exceptions)!


<docmeta name="displayName" value="Errors">

---

### Concepts ORM Model Settings (`docs/concepts/ORM/model-settings.md`)

# Model settings

In Sails, the top-level properties of model definitions are called **model settings**.  This includes everything from [attribute definitions](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?attributes), to the [database settings](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings#?datastore) the model will use, as well as a few other options.

The majority of this page is devoted to a complete tour of the model settings supported by Sails.  But before we begin, let's look at how to actually apply these settings in a Sails app.


### Overview

Model settings allow you to customize the behavior of the models in your Sails app.  They can be specified on a per-model basis by setting top-level properties in a [model definition](https://sailsjs.com/documentation/concepts/models-and-orm/models), or as app-wide defaults in [`sails.config.models`](https://sailsjs.com/documentation/reference/configuration/sails-config-models).

##### Changing default model settings

To modify the [default model settings](https://sailsjs.com/documentation/reference/configuration/sails-config-models) shared by all of the models in your app, edit [`config/models.js`](https://sailsjs.com/documentation/anatomy/my-app/config/models-js).

For example, when you generate a new app, Sails automatically includes three different default attributes in your `config/models.js` file:  `id`, `createdAt`, and `updatedAt`.  Let's say that, for all of your models, you wanted to use a slightly different, customized `id` attribute. To do so, you could just override `attributes: {  id: {...}  }` in your `config/models.js` definition.


##### Overriding settings for a particular model

To further customize these settings for a particular model, you can specify them as top-level properties in that model's definition file (e.g. `api/models/User.js`).  This will override default model settings with the same name.

For example, if you add `fetchRecordsOnUpdate: true` to one of your model definitions (`api/models/UploadedFile.js`), then that model will now return the records that were updated.  But the rest of your models will be unaffected: they will still use the default setting (which is `fetchRecordsOnUpdate: false`, unless you've changed it).


##### Choosing an approach

In your day to day development, the model setting you'll interact with most often is `attributes`. Attributes are used in almost every model definition, and some default attributes are included in `config/models.js`.  For future reference, here are a few additional tips:

+ If you are specifying a `tableName`, you should always do so on a per-model basis.  (An app-wide table name wouldn't make sense!)
+ There is no reason to specify an app-wide datastore, since you already have one out of the box (named "default"). Even so, you might want to override `datastore` for a particular model in certain situations&mdash;if, for example, your default datastore is PostgreSQL but you have an `CachedBloodworkReport` model that you want to live in Redis.
+ For the sake of clarity, it is best to only specify `migrate` and `schema` settings as app-wide defaults, never on a per-model basis.


Now that you have an idea of what model settings are and how to configure them, let's run through and have a look at each one.

--------------------




### attributes

The set of attribute definitions for a model.

```
attributes: { /* ... */ }
```

| Type           | Example                 | Default       |
| -------------- |:------------------------|:--------------|
| ((dictionary)) | _See below._            | `{}`          |

Most of the time, you'll define attributes in your individual model definitions (in `api/models/`), but you can also specify **default attributes** in `config/models.js`.  This allows you to define a set of global attributes in one place, then rely on Sails to make them available to all of your models implicitly and without repeating yourself.  Default attributes can also be overridden on a per-model basis by defining a replacement attribute with the same name in the relevant model definition.

```js
attributes: {
  id: { type: 'number', autoIncrement: true },
  createdAt: { type: 'number', autoCreatedAt: true },
  updatedAt: { type: 'number', autoUpdatedAt: true },
}
```

For a complete introduction to model attributes, including how to define and use them in your Sails app, see [Concepts > ORM > Attributes](https://sailsjs.com/documentation/concepts/orm/attributes).

### customToJSON

A function that allows you to customize the way a model's records are serialized to JSON.

```
customToJSON: function() { /*...*/ }
```

| Type         | Example                 | Default       |
| ------------ |:------------------------|:--------------|
| ((function)) | _See below._            | _n/a_         |

Adding the `customToJSON` setting to a model changes the way that the model&rsquo;s records are _stringified_.  In other words, it allows you to inject custom logic that runs any time one of these records are passed into `JSON.stringify()`.  This is most commonly used to implement a failsafe, making sure sensitive data like user passwords aren't accidentally included in a response (since [`res.send()`](https://sailsjs.com/documentation/reference/response-res/res-send) and actions2 may stringify data before sending).

The `customToJSON` function takes no arguments, but provides access to the record as the `this` variable.  This allows you to omit sensitive data and return the sanitized result, which is what `JSON.stringify()` will actually use when generating a JSON string.  For example:

```js
customToJSON: function() {
  // Return a shallow copy of this record with the password and ssn removed.
  return _.omit(this, ['password', 'ssn'])
}
```

The customToJSON function is deisgned not to support async capabilities. This allows synchronous bits in core to stay synchronous and provide better stability to the system as a whole.

> Note that the `this` variable available in `customToJSON` is a _direct reference to the actual record object_, so be careful not to modify it.  In other words, avoid writing code like `delete this.password`.  Instead, use methods like `_.omit()` or `_.pick()` to get a _copy_ of the record.  Or just construct a new dictionary and return that (e.g. `return { foo: this.foo }`).

### tableName

The name of the SQL table (/MongoDB collection) where a model will store and retrieve its records as rows (/MongoDB documents).

```
tableName: 'some_preexisting_table'
```

| Type        | Example                    | Default       |
| ----------- |:---------------------------|:--------------|
| ((string))  | `'some_preexisting_table'` | _Same as model's identity._

The **tableName** setting gives you the ability to customize the name of the underlying _physical model_ that a particular model should use.  In other words, it lets you control where a model stores and retrieves records within the database, _without_ affecting the code in your controller actions / helpers.

By default, Sails uses the model's [identity](https://sailsjs.com/documentation/concepts/models-and-orm/model-settings?identity) to determine its table name:

```js
await User.find();
// => SELECT * FROM user;
```

This is a recommended convention, and shouldn't need to be changed in most cases.  But, if you are sharing a legacy database with an existing application written for a different platform like Python or C#, or if your team prefers a different naming convention for their database tables, then it may be useful to customize this mapping.

Returning to the example above, if you modified your model definition in `api/models/User.js`, and set `tableName: 'foo_bar'`, then you'd see slightly different results:

```js
await User.find();
// => SELECT * FROM foo_bar;
```

> What's in a `tableName`?  In databases like MySQL and PostgreSQL, the setting refers to a literal "table".  In MongoDB, it refers to a "collection".  It's really just about familiarity: That which we call a "table", by any other word would query as well.



### migrate

The **auto-migration strategy** that Sails will run every time your app loads.

```
migrate: 'alter'
```

| Type        | Example                 | Default       |
| ----------- |:------------------------|:--------------|
| ((string))  | `'alter'`               | _You'll be prompted._<br/><br/>_**Note**: In production, this is always `'safe'`._

The `migrate` setting controls your app's auto-migration strategy.  In short, this tells Sails whether or not you'd like it to attempt to automatically rebuild the tables/collections/sets/etc. in your database(s).

##### Database migrations

In the course of developing an app, you will almost always need to make at least one or two **breaking changes** to the structure of your database.  Exactly _what_ constitutes a "breaking change" depends on the database you're using:  For example, imagine you add a new attribute to one of your model definitions.  If that model is configured to use MongoDB, then this is no big deal; you can keep developing as if nothing happened.  But if that model is configured to use MySQL, then there is an extra step: a column must be added to the corresponding table (otherwise model methods like `.create()` will stop working).  So for a model using MySQL, adding an attribute is a breaking change to the database schema.

> Even if all of your models use MongoDB, there are still some breaking schema changes to watch out for.  For example, if you add `unique: true` to one of your attributes, a [unique index](https://docs.mongodb.com/manual/core/index-unique/) must be created in MongoDB.


In Sails, there are two different modes of operation when it comes to [database migrations](https://en.wikipedia.org/wiki/Schema_migration):

1. **Manual migrations**: The art of updating your database tables/collections/sets/etc. by hand.  For example, writing a SQL query to [add a new column](http://dev.mysql.com/doc/refman/5.7/en/alter-table.html), or sending a [Mongo command to create a unique index](https://docs.mongodb.com/manual/core/index-unique/).  If the database contains data you care about (in production, for example), you must carefully consider whether that data needs to change to fit the new schema, and, if necessary, write scripts to migrate it.  While a [number of](https://www.npmjs.com/package/sails-migrations) great [open-source tools](http://knexjs.org/#Migrations-CLI) exist for managing manual migration scripts, as well as hosted products like the [database migration service on AWS](https://aws.amazon.com/blogs/aws/aws-database-migration-service/), we recommend doing all database migrations by hand, using [`sails run`](https://sailsjs.com/documentation/concepts/shell-scripts).
2. **Auto-migrations**: A convenient, built-in feature in Sails that allows you to make iterative changes to your model definitions during development, without worrying about the reprecussions.  Auto-migrations should _never_ be enabled when connecting to a database with data you care about.  Instead use auto-migrations with fake data, or with cached data that you can easily recreate.


Whenever you need to apply breaking changes to your _production database_, you should use manual database migrations. Otherwise, when you're developing on your laptop or running your automated tests, auto-migrations can save you tons of time.


##### How auto-migrations work

When you lift your Sails app in a development environment (e.g. running `sails lift` in a brand new Sails app), the configured auto-migration strategy will run.  If you are using `migrate: 'safe'`, then nothing additional will happen,  but if you are using `drop` or `alter`, Sails will load every record in your development database into memory, then drop and recreate the physical layer representation of the data (i.e. tables/collections/sets/etc.).  This allows any breaking changes you've made in your model definitions, like removing a uniqueness constraint, to be automatically applied to your development database.  Finally, if you are using `alter`, Sails will then attempt to re-seed the freshly generated tables/collections/sets with the records it saved earlier.


| Auto-migration strategy  | Description |
|:-------------------------|:---------------------------------------------|
| `safe`                    | never auto-migrate my database(s). I will do it myself, by hand.
| `alter`                   | auto-migrate columns/fields, but attempt to keep my existing data (experimental)
| `drop`                    | wipe/drop ALL my data and rebuild models every time I lift Sails


> Keep in mind that when using the `alter` or `drop` strategies, any manual changes you have made to your database since the last time you lifted your app may be lost.  This includes things like custom indexes, foreign key constraints, column order and comments.  In general, tables created by auto-migrations are not guaranteed to be consistent regarding any details of your physical database columns besides setting the column name, type (including character set / encoding if specified) and uniqueness.

##### Can I use auto-migrations in production?

The `drop` and `alter` auto-migration strategies in Sails exist as a feature for your convenience during development, and when running automated tests.  **They are not designed to be used with data you care about.**  Please take care to never use `drop` or `alter` with a production dataset.  In fact, as a failsafe to help protect you from doing this inadvertently, any time you lift your app [in a production environment](https://sailsjs.com/documentation/reference/configuration/sails-config#?sailsconfigenvironment), Sails _always_ uses `migrate: 'safe'`, no matter what you have configured.

In many cases, hosting providers automatically set the `NODE_ENV` environment variable to "production" when they detect a Node.js app.  Even so, please don't rely only on that failsafe, and take the usual precautions to keep your users' data safe.  Any time you connect Sails (or any other tool or framework) to a database with pre-existing production data, **do a dry run**,  especially the very first time.  Production data is sensitive, valuable, and in many cases irreplaceable.  Customers, users, and their lawyers are not cool with it getting flushed.

As a best practice, make sure to never lift or [deploy](https://sailsjs.com/documentation/concepts/deployment) your app with production database credentials unless you are 100% sure you are running in a production environment.  A popular approach for solving this at an organization-wide scale is simply to _never_ push up production database credentials to your source code repository in the first place, instead relying on [environment variables](https://sailsjs.com/documentation/reference/configuration) for all sensitive credentials.  (This is an especially good idea if your app is subject to regulatory requirements, or if a large number of people have access to your code base.)


##### Are auto-migrations slow?

If you are working with a relatively large amount of development/test data, the `alter` auto-migration strategy may take a long time to complete at startup.  If you notice that a command like `npm test`, `sails console`, or `sails lift` appears to hang, consider decreasing the size of your development dataset.  (Remember: Sails auto-migrations should only be used on your local laptop/desktop computer, and only with small, development datasets.)



### schema

Whether or not a model expects records to conform to a specific set of attributes.

```
schema: true
```

| Type        | Example                 | Default       |
| ----------- |:------------------------|:--------------|
| ((boolean)) | `true`                  | _Depends on the adapter._


The `schema` setting allows you to toggle a model between "schemaless" or "schemaful" mode.  More specifically, it governs the behavior of methods like `.create()` and `.update()`.  Normally you are allowed to store arbitrary data in a record, as long as the adapter you're using supports it.  But if you enable `schema:true`, only properties that correspond with the model's `attributes` will actually be stored.

> This setting is only relevant for models using schemaless databases like MongoDB.  When hooked up to a relational database like MySQL or PostgreSQL, a model is always effectively `schema:true`, since the underlying database can only store data in tables and columns that have been set up ahead of time.



### datastore

The name of the [datastore configuration](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores) that a model will use to find records, create records, etc.

```
datastore: 'legacyECommerceDb'
```

| Type       | Example                 | Default       |
| ---------- |:------------------------|:--------------|
| ((string)) | `'legacyECommerceDb'`   | `'default'`   |

This allows you to indicate the database where this model will fetch and save its data.  Unless otherwise specified, every model in your app uses a built-in datastore named "default", which is included in every new Sails app out of the box.  This makes it easy to configure your app's primary database while still allowing you to override the `datastore` setting for any particular model.

For more about configuring your app's datastores, see [Reference > Configuration > Datastores](https://sailsjs.com/documentation/reference/configuration/sails-config-datastores).


### dataEncryptionKeys

A set of keys to use when decrypting data.  The `default` data encryption key (or "DEK") is always used for encryption unless configured otherwise.


```javascript
dataEncryptionKeys: {
  default: 'tVdQbq2JptoPp4oXGT94kKqF72iV0VKY/cnp7SjL7Ik='
}
```

> Unless your use case requires key rotation, the `default` key is all you need.  Any other data encryption keys besides `default` are just there to allow for decrypting older data that was encrypted with them.

##### Key rotation

To retire a data encryption key, you'll need to give it a new key id (like `2028`) and then create a new `default` key for use in any new encryption. For example, if you release a Sails app in year 2028 and your keys are rotated out yearly, then the following year your `dataEncryptionKeys` may look like this:

```javascript
dataEncryptionKeys: {
  default: 'DZ7MslaooGub3pS/0O734yeyPTAeZtd0Lrgeswwlt0s=',
  '2028': 'C5QAkA46HD9pK0m7293V2CzEVlJeSUXgwmxBAQVj+xU='
}
```

After changing out the default key _the year after that_ in January 2030, you might have:

```javascript
dataEncryptionKeys: {
  default: 'tVdQbq2JptoPp4oXGT94kKqF72iV0VKY/cnp7SjL7Ik=',
  '2029': 'DZ7MslaooGub3pS/0O734yeyPTAeZtd0Lrgeswwlt0s=',
  '2028': 'C5QAkA46HD9pK0m7293V2CzEVlJeSUXgwmxBAQVj+xU='
}
```


### cascadeOnDestroy

Whether or not to _always_ act like you set `cascade: true` any time you call `.destroy()` using this model.

```
cascadeOnDestroy: true
```

| Type        | Example                 | Default       |
| ----------- |:------------------------|:--------------|
| ((boolean)) | `true`                  | `false`

This is disabled by default, for performance reasons.  You can enable it with this model setting, or on a per-query basis using [`.meta({cascade: true})`](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).



### dontUseObjectIds

> ##### _**This feature is for use with the [`sails-mongo` adapter](https://sailsjs.com/documentation/concepts/extending-sails/adapters/available-adapters#?sailsmongo) only.**_

If set to `true`, the model will _not_ use an auto-generated MongoDB ObjectID object as its primary key.  This allows you to create models using the `sails-mongo` adapter with primary keys that are arbitrary strings or numbers, not just big long UUID-looking things.  Note that setting this to `true` means that you will have to provide a value for `id` in every call to [`.create()`](https://sailsjs.com/documentation/reference/waterline-orm/models/create) or [`.createEach()`](https://sailsjs.com/documentation/reference/waterline-orm/models/create-each).


| Type        | Example                 | Default       |
| ----------- |:------------------------|:--------------|
| ((boolean)) | `true`                  | `false`

This is disabled by default, for performance reasons.  You can enable it with this model setting, or on a per-query basis using [`.meta({dontUseObjectIds: true})`](https://sailsjs.com/documentation/reference/waterline-orm/queries/meta).



### Seldom-used settings

The following low-level settings are included in the spirit of completeness, but in practice, they should rarely (if ever) be changed.


##### primaryKey

The name of a model's primary key attribute.

> **You should never need to change this setting.  Instead, if you need to use a custom primary key, set a custom `columnName` on the "id" attribute.**

```javascript
primaryKey: 'id'
```

| Type       | Example       | Default       |
| ---------- |:--------------|:--------------|
| ((string)) | `'id'`        | `'id'`        |

Conventionally this is "id", a default attribute that is included for you automatically in the `config/models.js` file of new apps generated as of Sails v1.0.  The best way to change the primary key for your model is simply to customize the `columnName` of that default attribute.

For example, imagine you have a User model that needs to integrate with a table in a pre-existing MySQL database.  That table might have a column named something other than "id" (like "email_address") as its primary key.  To make your model respect that primary key, you'd specify an override for your `id` attribute in the model definition; like this:

```js
id: {
  type: 'string',
  columnName: 'email_address',
  required: true
}
```

Then, in your app's code, you'll be able to look up users by primary key, while the mapping to `email_address` in all generated SQL queries is taken care of for you automatically:

```js
await User.find({ id: req.param('emailAddress' });
```

> All caveats aside, lets say you're an avid user of MongoDB.  In your new Sails app, you'll start off by setting `columnName: '_id'` on your default "id" attribute in `config/models.js`.  Then you can use Sails and Waterline just like normal, and everything will work just fine.
>
> But what if you find yourself wishing that you could change the actual name of the "id" attribute itself for the sake of familiarity?  That way, when you call built-in model methods in your code, instead of the usual "id", you would use syntax like `.destroy({ _id: 'ba8319abd-13810-ab31815' })`.
>
> That's where this model setting might become useful.  All you'd have to do is edit `config/models.js` so that it contains `primaryKey: '_id'`, and then rename the default "id" attribute to "_id".  But there are some [good reasons to reconsider](https://gist.github.com/mikermcneil/9247a420488d86f09be342038e114a08) this course of action.

##### identity

The lowercase, unique identifier for a model.

> **A model's `identity` is read-only.  It is automatically derived, and should never be set by hand.**

```
Something.identity;
```

| Type       | Example       |
| ---------- |:--------------|
| ((string)) | `'purchase'`  |


In Sails, a model's `identity` is inferred automatically by lowercasing its filename and stripping off the file extension.  For example, the identity of `api/models/Purchase.js` would be `purchase`.  It would be accessible as `sails.models.purchase`, and if blueprint routes were enabled, you'd be able to reach it with requests like `GET /purchase` and `PATCH /purchase/1`.

```javascript
assert(Purchase.identity === 'purchase');
assert(sails.models.purchase.identity === 'purchase');
assert(Purchase === sails.models.purchase);
```



##### globalId

The unique global identifier for a model, which also determines the name of its corresponding global variable (if relevant).

> **A model's `globalId` is read-only.  It is automatically derived, and should never be set by hand.**

```
Something.globalId;
```

| Type       | Example       |
| ---------- |:--------------|
| ((string)) | `'Purchase'`  |

The primary purpose of a model's globalId is to determine the name of the global variable that Sails automatically exposes on its behalf&mdash;that is, unless globalization of models has been [disabled](https://sailsjs.com/documentation/concepts/globals?q=disabling-globals).  In Sails, a model's `globalId` is inferred automatically from its filename.  For example, the globalId of `api/models/Purchase.js` would be `Purchase`.

```javascript
assert(Purchase.globalId === 'Purchase');
assert(sails.models.purchase.globalId === 'Purchase');
if (sails.config.globals.models) {
  assert(sails.models.purchase === Purchase);
}
else {
  assert(typeof Purchase === 'undefined');
}
```


<docmeta name="displayName" value="Model settings">

---

--- METRICS ---
- Files Extracted: 134
- Estimated Token Budget: ~127641 tokens
- Canonical Reference: https://codewiki.google/github.com/balderdashy/sails
