summaryrefslogtreecommitdiffstats
path: root/common/src/main/webapp/usageguide/appserver/node_modules/node-restful
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/main/webapp/usageguide/appserver/node_modules/node-restful')
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.npmignore18
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.travis.yml5
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/Makefile29
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/README.md254
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/movies/index.js132
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes.js79
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/index.js25
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/index.js11
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/note.js28
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/user.js13
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/routes/user.js22
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/index.js3
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/handlers.js221
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/model.js479
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/restful.js7
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/LICENSE23
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/README.md22
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/package.json69
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.js6
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.map1
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore.js1548
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/package.json65
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/config.js32
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/data.js101
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/index.jade4
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/show.jade3
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.chainable.js48
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.excludes.js21
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.filters.js191
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.handle.js54
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.hooks.js52
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.js301
-rw-r--r--common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.template.js62
33 files changed, 3929 insertions, 0 deletions
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.npmignore b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.npmignore
new file mode 100644
index 0000000..ecb3771
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.npmignore
@@ -0,0 +1,18 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+npm-debug.log
+
+node_modules/
+
+coverage.html
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.travis.yml b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.travis.yml
new file mode 100644
index 0000000..a055764
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/.travis.yml
@@ -0,0 +1,5 @@
+services: mongodb
+language: node_js
+node_js:
+ - 0.11
+ - 0.10
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/Makefile b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/Makefile
new file mode 100644
index 0000000..2b17262
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/Makefile
@@ -0,0 +1,29 @@
+MOCHA_OPTS=
+REPORTER = dot
+
+check: test
+
+test: test-unit
+
+test-unit:
+ @NODE_ENV=test ./node_modules/.bin/mocha \
+ --reporter $(REPORTER) \
+ $(MOCHA_OPTS)
+
+test-acceptance:
+ @NODE_ENV=test ./node_modules/.bin/mocha \
+ --reporter $(REPORTER) \
+ --bail \
+ test/acceptance/*.js
+
+test-cov: lib-cov
+ @RESTFUL_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
+
+lib-cov:
+ @jscoverage lib lib-cov
+
+clean:
+ rm -f coverage.html
+ rm -rf lib-cov
+
+.PHONY: test test-unit clean
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/README.md b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/README.md
new file mode 100644
index 0000000..ca59376
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/README.md
@@ -0,0 +1,254 @@
+[![build status](https://secure.travis-ci.org/baugarten/node-restful.png?branch=master)](http://travis-ci.org/baugarten/node-restful)
+
+node-restful
+============
+
+Create awesome APIs using express.
+
+Register mongoose resources and default RESTful routes are automatically made
+
+```js
+var express = require('express'),
+ bodyParser = require('body-parser'),
+ methodOverride = require('method-override'),
+ morgan = require('morgan'),
+ restful = require('node-restful'),
+ mongoose = restful.mongoose;
+var app = express();
+
+app.use(morgan('dev'));
+app.use(bodyParser.urlencoded({'extended':'true'}));
+app.use(bodyParser.json());
+app.use(bodyParser.json({type:'application/vnd.api+json'}));
+app.use(methodOverride());
+
+mongoose.connect("mongodb://localhost/resources");
+
+var Resource = app.resource = restful.model('resource', mongoose.Schema({
+ title: String,
+ year: Number,
+ }))
+ .methods(['get', 'post', 'put', 'delete']);
+
+Resource.register(app, '/resources');
+
+app.listen(3000);
+```
+
+Registers the following routes:
+
+ GET /resources
+ GET /resources/:id
+ POST /resources
+ PUT /resources/:id
+ DELETE /resources/:id
+
+which do exactly what you think they do!
+
+The best part is that `restful.model` returns a Mongoose model, so you can interact with it the same way that you're already accustomed to! (i.e. `new Resource`, `Resource.findById`, etc.)
+
+## Support
+
+This library is currently supported through complaint driven development, so if you see something, have a feature request, open an issue and if it seems to jive with the mission of the library, I'll prioritize it.
+
+## Install
+
+```
+npm install node-restful
+```
+
+## Usage
+
+There is a good example application under examples/movies.
+
+I will also show some features and use cases for them, how to set up routes, etc.
+
+### API
+
+There are a few functions that are available after we register the mongoose schema. The first one we already saw.
+
+`.methods([...])` takes a list of methods that should be available on the resource. Future calls to methods will override previously set values
+To disallow `delete` operations, simply run
+
+```js
+Resource.methods(['get', 'post', 'put'])
+```
+
+We can also run custom routes. We can add custom routes by calling `.route(path, handler)`
+
+```js
+Resource.route('recommend', function(req, res, next) {
+ res.send('I have a recommendation for you!');
+});
+```
+
+This will set up a route at `/resources/recommend`, which will be called on all HTTP methods. We can also restrict the HTTP method by adding it to the path:
+
+```js
+Resource.route('recommend.get', function(req, res, next) {
+ res.send('GET a recommendation');
+});
+Resource.route('recommend', ['get', 'put', 'delete'], function(req, res, next) { ... });
+```
+
+Or do some combination of HTTP methods.
+
+Now. Lets say we have to run arbitrary code before or after a route. Lets say we need to hash a password before a POST or PUT operation. Well, easy.
+
+```js
+Resource.before('post', hash_password)
+ .before('put', hash_password);
+
+function hash_password(req, res, next) {
+ req.body.password = hash(req.body.password);
+ next();
+}
+```
+
+Boy. That was easy. What about doing stuff after request, but before its sent back to the user? Restful stores the bundle of data to be returned in `res.locals` (see [express docs](http://expressjs.com/api.html#res.locals)). `res.locals.status_code` is the returned status code and `res.locals.bundle` is the bundle of data. In every before and after call, you are free to modify these are you see fit!
+
+```js
+Resource.after('get', function(req, res, next) {
+ var tmp = res.locals.bundle.title; // Lets swap the title and year fields because we're funny!
+ res.locals.bundle.title = res.locals.bundle.year;
+ res.locals.bundle.year = tmp;
+ next(); // Don't forget to call next!
+});
+
+Resource.after('recommend', do_something); // Runs after all HTTP verbs
+```
+
+Now, this is all great. But up until now we've really only talked about defining list routes, those at `/resources/route_name`. We can also define detail routes. Those look like this
+
+```js
+Resource.route('moreinfo', {
+ detail: true,
+ handler: function(req, res, next) {
+ // req.params.id holds the resource's id
+ res.send("I'm at /resources/:id/moreinfo!")
+ }
+});
+```
+I don't think this is the prettiest, and I'd be open to suggestions on how to beautify detail route definition...
+
+And that's everything for now!
+
+### Built-in Filters
+
+Node-restful accepts many options to manipulate the list results. These options can be added to your request either via the querystring or the POST body. They are passed into the mongoose query to filter your resultset.
+
+#### Selecting the entity-properties you need
+
+If you only need a few properties instead of the entire model, you can ask the service to only give just the properties you need:
+
+A `GET` request to `/users/?select=name%20email` will result in:
+
+```json
+[
+ {
+ "_id": "543adb9c7a0f149e3ac29438",
+ "name": "user1",
+ "email": "user1@test.com"
+ },
+ {
+ "_id": "543adb9c7a0f149e3ac2943b",
+ "name": "user2",
+ "email": "user2@test.com"
+ }
+]
+```
+
+#### Limiting the number and skipping items
+
+When implementing pagination you might want to use `skip` and `limit` filters. Both do exactly what their name says and just skip given amount of items or limit to a set amount of items.
+
+`/users/?limit=5` will give you the first 5 items
+`/users/?skip=5` will skip the first 5 and give you the rest
+`/users/?limit=5&skip=5` will skip the first 5 and then give you the second 5
+
+#### Sorting the result
+
+Getting a sorted list is as easy as adding a `sort` querystring parameter with the property you want to sort on. `/users/?sort=name` will give you a list sorted on the name property, with an ascending sort order.
+
+Changing the sort order uses the same rules as the string notation of [mongoose's sort filter](http://mongoosejs.com/docs/api.html#query_Query-sort). `/users/?sort=-name` will return the same list as before with a descending sort order.
+
+#### Filtering the results
+
+Sometimes you just want to get all people older than 18, or you are want to get all people living in a certain city. Then you would want to
+use filters for that. You can ask the service for equality, or values greater or less than, give it an array of values it should match to, or even a regex.
+
+| Filter | Query | Example | Description |
+|------------------------------|--------|------------------------------------------------------|---------------------------------|
+| **equal** | `equals` | `/users?gender=male` or `/users?gender__equals=male` | both return all male users |
+| **not equal** | `ne` | `/users?gender__ne=male` | returns all users who are not male (`female` and `x`) |
+| **greater than** | `gt` | `/users?age__gt=18` | returns all users older than 18 |
+| **greater than or equal to** | `gte` | `/users?age__gte=18` | returns all users 18 and older (age should be a number property) |
+| **less than** | `lt` | `/users?age__lt=30` | returns all users age 29 and younger |
+| **less than or equal to** | `lte` | `/users?age__lte=30` | returns all users age 30 and younger |
+| **in** | `in` | `/users?gender__in=female,male` | returns all female and male users |
+| **nin** | `nin` | `/users?age__nin=18,30` | returns all users with age other than 18 or 30 |
+| **Regex** | `regex` | `/users?username__regex=/^baugarten/i` | returns all users with a username starting with baugarten |
+
+### Populating a sub-entity
+
+When you have setup a mongoose Schema with properties referencing other entities, you can ask the service to populate them for you.
+
+A `GET` request to `/users/542edff9fffc55dd29d99346` will result in:
+
+```json
+{
+ "_id": "542edff9fffc55dd29d99346",
+ "name": "the employee",
+ "email": "employee@company.com",
+ "boss": "542edff9fffc55dd29d99343",
+ "__v": 0
+}
+```
+A `GET` request to `/users/542edff9fffc55dd29d99346?populate=boss` will result in:
+
+```json
+{
+ "_id": "542edff9fffc55dd29d99346",
+ "name": "the employee",
+ "email": "employee@company.com",
+ "boss": {
+ "_id": "542edff9fffc55dd29d99343",
+ "name": "the boss",
+ "email": "boss@company.com",
+ "__v": 0
+ },
+ "__v": 0
+}
+```
+
+
+
+---
+
+## Contributing
+
+You can view the issue list for what I'm working on, or contact me to help!
+
+Just reach out to [me](https://github.com/baugarten)
+
+## MIT License
+Copyright (c) 2012 by Ben Augarten
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/movies/index.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/movies/index.js
new file mode 100644
index 0000000..c3140fa
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/movies/index.js
@@ -0,0 +1,132 @@
+var express = require('express'),
+ bodyParser = require('body-parser'),
+ methodOverride = require('method-override'),
+ mongoose = require('mongoose'),
+ morgan = require('morgan'),
+ restful = require('../../');
+var app = module.exports = express();
+
+app.use(morgan('dev'));
+app.use(bodyParser.urlencoded({'extended':'true'}));
+app.use(bodyParser.json());
+app.use(bodyParser.json({type:'application/vnd.api+json'}));
+app.use(methodOverride());
+app.set('view engine', 'jade');
+
+app.mongoose = mongoose; // used for testing
+
+mongoose.connect("mongodb://localhost/movies_test");
+
+var user = app.user = restful.model('users', mongoose.Schema({
+ username: { type: 'string', required: true },
+ pass_hash: { type: 'number', required: true }
+ }))
+ .methods(['get', 'post', 'put', 'delete'])
+ .before('get', function(req, res, next) {
+ req.body.limit = 1;
+ next()
+ })
+ .removeOptions({
+ sort: 'field -username'
+ })
+ .includeSchema(false);
+
+
+var movie = app.movie = restful.model("movies", mongoose.Schema({
+ title: { type: 'string', required: true },
+ year: { type: 'number', required: true },
+ creator: {type: 'ObjectId', ref: 'users' },
+ genre: {type: 'ObjectId', ref: 'genres'},
+ comments: [{
+ body: {type: 'String'},
+ date: {type: 'Date'},
+ author: { type: 'ObjectId', ref: 'users' }
+ }],
+ meta: {
+ productionco: 'string',
+ director: { type: 'ObjectId', ref: 'users' }
+ },
+ secret: { type: 'string', select: false }
+ }));
+
+movie.methods([
+ {
+ method: 'get',
+ before: noop,
+ after: noop
+ },
+ 'post',
+ 'put',
+ 'delete'])
+ .updateOptions({ new: true })
+ .route('recommend', function(req, res, next) {
+ res.locals.status_code = 200;
+ res.locals.bundle.recommend = 'called';
+ next();
+ })
+ .route('anotherroute', function(req, res, next) {
+ res.writeHead(200, {'Content-Type': 'application/json' });
+ res.write(JSON.stringify({
+ anotherroute: "called"
+ }));
+ res.end(); // This ends the request and prevents any after filters from executing
+ })
+ .route('athirdroute', {
+ handler: function(req, res, next) {
+ res.locals.status_code = 200; // Store response status code
+ res.locals.bundle = {
+ athirdroute: "called" // And response data
+ };
+ next(); // Call *after* filters and then return the response
+ },
+ methods: ['get', 'post'],
+ detail: true // Will mount the route at the detail endpoint /movies/:id/athirdroute
+ })
+ .route('pshh', {
+ handler: [function(req, res, next) {
+ next();
+ }, function(req, res, next) {
+ next();
+ }, function(req, res, next) {
+ res.locals.status_code = 200;
+ res.locals.bundle = {
+ pshh: "called"
+ };
+ next();
+ }],
+ methods: ['get', 'post']
+ })
+ .before('post', noop) // before a POST, execute noop
+ .after('post', noop)
+ .before('put', noop)
+ .after('put', noop)
+ .after('recommend', after)
+ .after('athirdroute', after);
+
+var genre = app.genre = restful.model("genres", mongoose.Schema({
+ name: { type: 'string', required: true }
+ }));
+genre.methods(['get', 'put', 'delete']);
+genre.shouldUseAtomicUpdate = false;
+
+var review = app.genre = restful.model("reviews", mongoose.Schema({
+ body: { type: 'string', required: true },
+ length: { type: Number, min: 0, required: true} // https://github.com/baugarten/node-restful/issues/116
+ }));
+review.methods(['get', 'put', 'delete']);
+
+user.register(app, '/users');
+movie.register(app, '/api/movies');
+genre.register(app, '/api/genres');
+review.register(app, '/api/reviews');
+
+if (!module.parent) {
+ app.listen(3000);
+}
+
+function noop(req, res, next) { next(); }
+function after(req, res, next) {
+ res.locals.bundle.after = 'called';
+ next();
+}
+
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes.js
new file mode 100644
index 0000000..57efc5b
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes.js
@@ -0,0 +1,79 @@
+var express = require('express'),
+ bodyParser = require('body-parser'),
+ methodOverride = require('method-override'),
+ mongoose = require('mongoose'),
+ morgan = require('morgan'),
+ restful = require('../');
+// Make a new Express app
+var app = module.exports = express();
+
+// Connect to mongodb
+mongoose.connect("mongodb://localhost/restful");
+
+// Use middleware to parse POST data and use custom HTTP methods
+app.use(morgan('dev'));
+app.use(bodyParser.urlencoded({'extended':'true'}));
+app.use(bodyParser.json());
+app.use(bodyParser.json({type:'application/vnd.api+json'}));
+app.use(methodOverride());
+
+var hashPassword = function(req, res, next) {
+ if (!req.body.password)
+ return next({ status: 400, err: "No password!" }); // We can also throw an error from a before route
+ req.body.password = bcrypt.hashSync(req.body.password, 10); // Using bcrypt
+ return next(); // Call the handler
+}
+
+var sendEmail = function(req, res, next) {
+ // We can get the user from res.bundle and status code from res.status and
+ // trigger an error by calling next(err) or populate information that would otherwise be miggins
+ next(); // I'll just pass though
+}
+
+var User = restful.model( "users", mongoose.Schema({
+ username: 'string',
+ password_hash: 'string',
+ }))
+ .methods(['get', 'put', 'delete', {
+ method: 'post',
+ before: hashPassword, // Before we make run the default POST to create a user, we want to hash the password (implementation omitted)
+ after: sendEmail, // After we register them, we will send them a confirmation email
+ }]);
+
+User.register(app, '/user'); // Register the user model at the localhost:3000/user
+
+var validateUser = function(req, res, next) {
+ if (!req.body.creator) {
+ return next({ status: 400, err: "Notes need a creator" });
+ }
+ User.Model.findById(req.body.creator, function(err, model) {
+ if (!model) return next(restful.objectNotFound());
+ return next();
+ });
+}
+
+var Note = restful.model("note", mongoose.Schema({
+ title: { type: 'string', required: true},
+ body: { type: 'string', required: true},
+ creator: { type: 'ObjectId', ref: 'user', require: true},
+ }))
+ .methods(['get', 'delete', { method: 'post', before: validateUser }, { method: 'put', before: validateUser }]);
+
+Note.register(app, '/note');
+
+User.route("notes", {
+ handler: function(req, res, next, err, model) { // we get err and model parameters on detail routes (model being the one model that was found)
+ Note.Model.find({ creator: model._id }, function(err, list) {
+ if (err) return next({ status: 500, err: "Something went wrong" });
+ //res.status is the status code
+ res.status = 200;
+
+ // res.bundle is what is returned, serialized to JSON
+ res.bundle = list;
+ return next();
+ });
+ },
+ detail: true, // detail routes operate on a single instance, i.e. /user/:id
+ methods: ['get'], // only respond to GET requests
+});
+app.listen(3000);
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/index.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/index.js
new file mode 100644
index 0000000..6299c33
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/index.js
@@ -0,0 +1,25 @@
+var express = require('express'),
+ bodyParser = require('body-parser'),
+ methodOverride = require('method-override'),
+ mongoose = require('mongoose'),
+ morgan = require('morgan'),
+ restful = require('../');
+var app = module.exports = express();
+
+// Connect to mongodb -- used to store the models
+mongoose.connect("mongodb://localhost/expressmvc");
+
+app.use(morgan('dev'));
+app.use(bodyParser.urlencoded({'extended':'true'}));
+app.use(bodyParser.json());
+app.use(bodyParser.json({type:'application/vnd.api+json'}));
+app.use(methodOverride());
+
+// expose a list of models to register
+var models = require('./models/index');
+models.forEach(function(model) {
+ console.log("Register " + model.resourceName);
+ model.register(app, '/' + model.resourceName);
+});
+
+app.listen(3000);
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/index.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/index.js
new file mode 100644
index 0000000..203375e
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/index.js
@@ -0,0 +1,11 @@
+var User = require('./user'),
+ Notes = require('./note'),
+ userroutes = require('../routes/user');
+
+console.log(userroutes);
+for (var route in userroutes) {
+ User.userroute(route, userroutes[route]);
+}
+
+exports = module.exports = [User, Notes];
+
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/note.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/note.js
new file mode 100644
index 0000000..b62861a
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/note.js
@@ -0,0 +1,28 @@
+var restful = require('../../../'),
+ mongoose = require('mongoose'),
+ User = require('./user');
+
+var validateUser = function(req, res, next) {
+ console.log("Add User");
+ if (req.body.creator) {
+ User.Obj.findById(req.body.creator, function(err, model) {
+ if (!model) {
+ return next(restful.objectNotFound());
+ }
+ next();
+ });
+ }
+ next(); // Required, so error later
+}
+
+var Note = new restful.Model({
+ title: "note",
+ methods: ['get', 'delete', { type: 'post', before: validateUser }, { type: 'put', before: validateUser }],
+ schema: mongoose.Schema({
+ title: { type: 'string', required: true},
+ body: { type: 'string', required: true},
+ creator: { type: 'ObjectId', ref: 'user', require: true},
+ }),
+});
+
+exports = module.exports = Note;
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/user.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/user.js
new file mode 100644
index 0000000..384e318
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/models/user.js
@@ -0,0 +1,13 @@
+var restful = require('../../..'),
+ mongoose = require('mongoose');
+
+var User = new restful.Model({
+ title: 'user',
+ methods: ['get', 'post', 'put', 'delete'],
+ schema: mongoose.Schema({
+ username: 'string',
+ password: 'string',
+ }),
+});
+
+exports = module.exports = User;
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/routes/user.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/routes/user.js
new file mode 100644
index 0000000..f9ad33e
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/examples/notes/routes/user.js
@@ -0,0 +1,22 @@
+var User = require('../models/user'),
+ Note = require('../models/note');
+
+// Here we can add custom route endpoints
+exports = module.exports = {
+ // an endpoint called notes
+ notes: {
+ handler: function(req, res, next, err, model) {
+ Note.Obj.find({ creator: model._id }, function(err, list) {
+ if (err) next({ status: 404 }); // Error handling
+ //res.status is the status code
+ res.status = 200;
+
+ // res.bundle is what is returned
+ res.bundle = list;
+ next();
+ });
+ },
+ detail: true, // detail makes sure we have one model to work on i.e. /user/:id/note is the uri
+ methods: ['get'], // only respond to GET requests
+ },
+}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/index.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/index.js
new file mode 100644
index 0000000..08a6795
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/index.js
@@ -0,0 +1,3 @@
+module.exports = process.env.RESTFUL_COV
+ ? require('./lib-cov/restful')
+ : require('./lib/restful');
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/handlers.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/handlers.js
new file mode 100644
index 0000000..8423310
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/handlers.js
@@ -0,0 +1,221 @@
+var _ = require('underscore');
+
+/*
+ * The last handler to be called in the chain of middleware
+ * This figures out what response format it should be in and sends it
+ */
+exports.last = function(req, res, next) {
+ if (res.locals.bundle) {
+ if (req.body.format === 'js') {
+ return res.send(res.locals.bundle);
+ } else if (req.body.format === 'html' || req.query.format === 'html') {
+ return res.render(this.templateRoot + '/' + req.templatePath, res.locals.bundle);
+ } else {
+ return res.status(res.locals.status_code).json(res.locals.bundle);
+ }
+ }
+ res.send();
+};
+
+exports.schema = function(req, res, next) {
+ // We can mount a model to multiple apps, so we need to get the base url from the request url
+ var baseuri = req.url.split('/');
+ baseuri = baseuri.slice(0, baseuri.length - 1).join('/');
+ var detailuri = baseuri + '/:id';
+ exports.respond(res, 200, {
+ resource: this.modelName,
+ allowed_methods: Object.keys(this.allowed_methods),
+ list_uri: baseuri,
+ detail_uri: detailuri,
+ fields: keep(this.schema.paths, ['regExp', 'path', 'instance', 'isRequired'])
+ });
+ next();
+};
+
+exports.get = function(req, res, next) {
+ req.quer.exec(function(err, list) {
+ if (err) {
+ exports.respond(res, 500, err);
+ } else if (req.params.id) {
+ exports.respondOrErr(res, 404, !list && exports.objectNotFound(), 200, (list && _.isArray(list)) ? list[0] : list);
+ } else {
+ exports.respondOrErr(res, 500, err, 200, list);
+ }
+ next();
+ });
+};
+
+exports.getDetail = function(req, res, next) {
+ req.quer.exec(function(err, one) {
+ exports.respondOrErr(res, 500, err, 200, one);
+ next();
+ });
+};
+
+/**
+ * Generates a handler that returns the object at @param pathName
+ * where pathName is the path to an objectId field
+ */
+exports.getPath = function(pathName) {
+ return function(req, res, next) {
+ req.quer = req.quer.populate(pathName);
+ req.quer.exec(function(err, one) {
+ var errStatus = ((err && err.status) ? err.status : 500);
+ exports.respondOrErr(res, errStatus, err, 200, (one && one.get(pathName)) || {});
+ next();
+ });
+ };
+};
+
+exports.post = function(req, res, next) {
+ var obj = new this(req.body);
+ obj.save(function(err) {
+ exports.respondOrErr(res, 400, err, 201, obj);
+ next();
+ });
+};
+
+exports.put = function(req, res, next) {
+ // Remove immutable ObjectId from update attributes to prevent request failure
+ if (req.body._id && req.body._id === req.params.id) {
+ delete req.body._id;
+ }
+
+ // Update in 1 atomic operation on the database if not specified otherwise
+ if (this.shouldUseAtomicUpdate) {
+ req.quer.findOneAndUpdate({}, req.body, this.update_options, function(err, newObj) {
+ if (err) {
+ exports.respond(res, 500, err);
+ } else if (!newObj) {
+ exports.respond(res, 404, exports.objectNotFound());
+ } else {
+ exports.respond(res, 200, newObj);
+ }
+ next();
+ });
+ } else {
+ // Preform the update in two operations allowing mongoose to fire its schema update hook
+ req.quer.findOne({"_id": req.params.id}, function(err, docToUpdate) {
+ if (err) {
+ exports.respond(res, 500, err);
+ }
+ var objNotFound = !docToUpdate && exports.objectNotFound();
+ if (objNotFound) {
+ exports.respond(res, 404, objNotFound);
+ return next();
+ }
+
+ docToUpdate.set(req.body);
+ docToUpdate.save(function (err, obj) {
+ exports.respondOrErr(res, 400, err, 200, obj);
+ next();
+ });
+ });
+ }
+};
+
+exports.delete = function(req, res, next) {
+ // Delete in 1 atomic operation on the database if not specified otherwise
+ if (this.shouldUseAtomicUpdate) {
+ req.quer.findOneAndRemove({}, this.delete_options, function(err, obj) {
+ if (err) {
+ exports.respond(res, 500, err);
+ }
+ exports.respondOrErr(res, 404, !obj && exports.objectNotFound(), 204, {});
+ next();
+ });
+ } else {
+ // Preform the remove in two steps allowing mongoose to fire its schema update hook
+ req.quer.findOne({"_id": req.params.id}, function(err, docToRemove) {
+ if (err) {
+ exports.respond(res, 500, err);
+ }
+ var objNotFound = !docToRemove && exports.objectNotFound();
+ if (objNotFound) {
+ exports.respond(res, 404, objNotFound);
+ return next();
+ }
+
+ docToRemove.remove(function (err, obj) {
+ exports.respondOrErr(res, 400, err, 204, {});
+ next();
+ });
+ });
+ }
+};
+
+// I'm going to leave these here because it might be nice to have standardized
+// error messages for common failures
+
+exports.objectNotFound = function() {
+ return {
+ status: 404,
+ message: 'Object not found',
+ name: 'ObjectNotFound',
+ errors: {
+ _id: {
+ message: "Could not find object with specified attributes"
+ }
+ }
+ };
+};
+exports.respond404 = function() {
+ return {
+ status: 404,
+ message: 'Page Not Found',
+ name: "PageNotFound",
+ errors: 'Endpoint not found for model ' + this.modelName
+ };
+};
+exports.authFailure = function() {
+ return {
+ status: 401,
+ message: 'Unauthorized',
+ name: "Unauthorized",
+ errors: 'Operation not authorzed on ' + this.modelName
+ };
+};
+exports.badRequest = function(errobj) {
+ return {
+ status: 400,
+ message: 'Bad Request',
+ name: "BadRequest",
+ errors: errobj || "Your request was invalid"
+ };
+};
+
+/**
+ * Takes a response, error, success statusCode and success payload
+ *
+ * If there is an error, it returns a 400 with the error as the payload
+ * If there is no error, it returns statusCode with the specified payload
+ *
+ */
+exports.respondOrErr = function(res, errStatusCode, err, statusCode, content) {
+ if (err) {
+ exports.respond(res, errStatusCode, err);
+ } else {
+ exports.respond(res, statusCode, content);
+ }
+};
+
+exports.respond = function(res, statusCode, content) {
+ res.locals.status_code = statusCode;
+ res.locals.bundle = content;
+};
+
+function keep(obj, keepers) {
+ var result = {};
+ for (var key in obj) {
+ result[key] = {};
+ for (var key2 in obj[key]) {
+ if (keepers.indexOf(key2) > -1) {
+ result[key][key2] = obj[key][key2];
+ }
+ if ('schema' === key2) {
+ result[key][key2] = keep(obj[key][key2].paths, keepers);
+ }
+ }
+ }
+ return result;
+}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/model.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/model.js
new file mode 100644
index 0000000..1531498
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/model.js
@@ -0,0 +1,479 @@
+var mongoose = require('mongoose'),
+ _ = require('underscore'),
+ Model = mongoose.Model,
+ handlers = require('./handlers');
+
+exports = module.exports = model;
+
+var methods = ['get', 'post', 'put', 'delete'], // All HTTP methods, PATCH not currently supported
+ endpoints = ['get', 'post', 'put', 'delete', 'getDetail'],
+ defaultroutes = ['schema'],
+ lookup = {
+ 'get': 'index',
+ 'getDetail': 'show',
+ 'put': 'updated',
+ 'post': 'created',
+ 'delete': 'deleted'
+ },
+ valid_alterables = filterable({
+ 'populate': query('populate'),
+ }, {});
+ valid_filters = filterable({
+ 'limit': query('limit'),
+ 'skip': query('skip'),
+ 'offset': query('offset'),
+ 'select': query('select'),
+ 'sort': query('sort'),
+ }, {
+ 'equals': query('equals'),
+ 'gte': query('gte'),
+ 'gt': query('gt'),
+ 'lt': query('lt'),
+ 'lte': query('lte'),
+ 'ne': query('ne'),
+ 'regex': function(val, query) {
+ var regParts = val.match(/^\/(.*?)\/([gim]*)$/);
+ if (regParts) {
+ // the parsed pattern had delimiters and modifiers. handle them.
+ val = new RegExp(regParts[1], regParts[2]);
+ } else {
+ // we got pattern string without delimiters
+ val = new RegExp(val);
+ }
+
+ return query.regex(val);
+ },
+ 'in': query('in'),
+ 'nin': query('nin'),
+ });
+ defaults = function() {
+ return {
+ routes: {},
+ allowed_methods: {
+ get: { detail: false }
+ },
+ update_options: {},
+ remove_options: {},
+ templateRoot: '',
+ shouldIncludeSchema: true,
+ shouldUseAtomicUpdate: true
+ };
+ };
+
+/**
+ * Returns the model associated with the given name or
+ * registers the model with mongoose
+ */
+function model() {
+ var result = mongoose.model.apply(mongoose, arguments),
+ default_properties = defaults();
+ if (1 === arguments.length) return result;
+
+ for (var key in default_properties) {
+ result[key] = default_properties[key];
+ }
+
+ return result;
+}
+
+Model.includeSchema = function(shouldIncludeSchema) {
+ this.shouldIncludeSchema = shouldIncludeSchema;
+ return this;
+};
+
+Model.methods = function(newmethods) {
+ var self = this,
+ get = contains(newmethods, 'get');
+
+ methods.forEach(function(method) {
+ delete self.routes[method];
+ });
+
+ this.allowed_methods = [];
+ if (!Array.isArray(newmethods)) {
+ newmethods = [newmethods];
+ }
+ if (get && !contains(newmethods, 'getDetail')) {
+ newmethods.push({
+ method: 'getDetail',
+ before: (typeof get !== 'string') ? get.before : null,
+ after: (typeof get !== 'string') ? get.after : null
+ });
+ }
+ newmethods.forEach(function(meth) {
+ var method = meth.method;
+ if ('string' === typeof meth) {
+ method = meth;
+ meth = {};
+ }
+ if (!method) throw new Error("Method object must have a method property");
+ self.allowed_methods.push(method);
+
+ meth.handler = handlers[method];
+ meth.detail = (method !== 'get' && method !== 'post');
+ self.route(method, meth);
+ });
+ return this;
+};
+
+Model.updateOptions = function(options) {
+ this['update_options'] = options;
+ return this;
+};
+
+Model.removeOptions = function(options) {
+ this['remove_options'] = options;
+ return this;
+};
+
+Model.template = function(templatePath) {
+ if (templatePath.substr(-1) == '/') {
+ templatePath = templatePath.substr(0, templatePath.length - 1);
+ }
+ this.templateRoot = templatePath;
+ return this;
+};
+
+/**
+ * Adds the default routes for the HTTP methods and one to get the schema
+ */
+Model.addDefaultRoutes = function() {
+ if (this.shouldIncludeSchema) {
+ this.route('schema', handlers.schema);
+ }
+ this.addSchemaRoutes();
+};
+
+Model.addSchemaRoutes = function() {
+ var self = this;
+ this.schema.eachPath(function(pathName, schemaType) {
+ if (pathName.indexOf('_id') === -1 && schemaType.instance === 'ObjectID') {
+ // Right now, getting nested models is the only operation supported
+ ['get'].forEach(function(method) {
+ self.route(pathName, method , {
+ handler: handlers[method + 'Path'].call(self, pathName),
+ detail: true
+ });
+ });
+ }
+ });
+};
+
+/**
+ * Adds an internal route for a path and method or methods to a function
+ *
+ * @param {String|Object} path: absolute path (including method) or object of routes
+ * @param {String|Function} method: the method to route to or the handler function
+ * @param {Function} fn: The handler function
+ * @return {Model} for chaining
+ * @api public
+ */
+Model.route = function(path, method, fn) {
+ var route = getRoute(this.routes, path),
+ meths = methods, // Default to all methods
+ lastPath = path.substr(path.lastIndexOf('.') + 1);
+
+ if (2 === arguments.length) {
+ fn = method;
+ if (!fn.methods && endpoints.indexOf(lastPath) > -1) {
+ meths = [lastPath];
+ } else if (fn.methods) {
+ meths = fn.methods;
+ }
+ } else {
+ meths = [method];
+ }
+
+ if (fn) {
+ fn = normalizeHandler(fn);
+
+ meths.forEach(function(meth) {
+ route[meth] = merge(route[meth], fn);
+ });
+ }
+ return this;
+};
+
+Model.before = function(path, method, fn) {
+ if (2 == arguments.length) {
+ arguments[1] = { before: arguments[1] };
+ }
+ return this.route.apply(this, arguments);
+};
+
+Model.after = function(path, method, fn) {
+ if (2 == arguments.length) {
+ arguments[1] = { after: arguments[1] };
+ }
+ return this.route.apply(this, arguments);
+};
+
+/**
+ * Registers all of the routes in routeObj to the given app
+ *
+ * TODO(baugarten): refactor to make less ugly
+ *
+ * if (isEndpoint(routeObj, path)) { handleRegistration(app, prefix, path, routeObj); }
+ * else {
+ * for (var key in routeObj) { recurse }
+ * }
+ */
+Model.registerRoutes = function(app, prefix, path, routeObj) {
+ var self = this;
+ for (var key in routeObj) {
+ if (isEndpoint(routeObj, key)) {
+ var route = routeObj[key];
+ var routehandlers = _.isArray(route.handler) ? route.handler : [route.handler];
+ routehandlers = _.map(routehandlers, function(handler) { return handler.bind(self); });
+ var detailGet = !route.detail && !path && key === 'get',
+ handlerlist = route.before.concat(
+ [preprocess.bind(self)],
+ routehandlers,
+ route.after,
+ [handlers.last]
+ );
+ /**
+ * TODO(baugarten): Add an enum type-thing to specify detail route, detail optional or list
+ * aka prettify this
+ */
+ if (route.detail) {
+ app[key](prefix + '/:id([0-9a-fA-F]{0,24})' + path , handlerlist);
+ } else if (detailGet) {
+ app[key](prefix + '/:id([0-9a-fA-F]{0,24}$)?', handlerlist);
+ } else {
+ app[key](prefix + path, handlerlist);
+ }
+ } else {
+ this.registerRoutes(app, prefix, path + '/' + key, routeObj[key]);
+ }
+ }
+};
+
+/**
+ * Registers this model to the given app
+ *
+ * This includes registering endpoints for all the methods desired
+ * in the model definition
+ *
+ */
+Model.register = function(app, url) {
+ this.addDefaultRoutes();
+ app.getDetail = app.get;
+ this.registerRoutes(app, url, '', this.routes);
+};
+
+// Will I still support handle()? I think maybe for default routes it might be nice, but
+// exposed via model.get, model.post, etc.
+/*Model.prototype.handle = function(route, filters, data, callback) {
+ if (arguments.length === 3) {
+ callback = data;
+ data = {};
+ } else if (arguments.length === 2) {
+ callback = filters;
+ filters = [];
+ data = {};
+ }
+ route = route.replace(/\//g, /\./);
+ data.format = 'js';
+ var req = {
+ url: route,
+ filters: filters,
+ body: data,
+ format: 'js',
+ }
+ var res = {
+ writeHeader: function() { },
+ write: function(ret) { callback(ret); },
+ send: function() {},
+ };
+ this.send(route.split(/\./), req, res);
+}
+
+Model.prototype.send = function(routes, req, res, next) {
+ var handler = this.routes;
+ req.quer = this.filter(req.filters, req.body, req.query, this.Model.find({}));
+ req.templatePath = this.template(routes, req.filters);
+ routes.forEach(function(route) {
+ if (route in handler) handler = handler[route];
+ else if (!('all' in handler)) {
+ handlers.respond(res, 404, handlers.respond404());
+ handlers.last(req, res);
+ }
+ });
+ if ('all' in handler) handler = handler.all;
+
+ if ('function' === typeof handler) {
+ return handler.call(this, req, res, next);
+ }
+
+ handlers.respond(res, 404, handlers.respond404());
+ handlers.last(req, res);
+}*/
+
+/**
+ * Returns a query filtered by the data in the request
+ * Looks in req.body and req.query to get the filterable data
+ * Filters the query based on functions in valid_filters
+ */
+Model.filter = function(req, quer) {
+ var detail = false; // detail route
+ // filter by id
+ if (req.params.id) {
+ quer = this.findById(req.params.id);
+ detail = true
+ }
+
+ [req.body, req.query, req.headers].forEach(function(alterableResponse) {
+ Object.keys(alterableResponse).filter(function(potential) {
+ return valid_alterables.contains(potential, quer);
+ }).forEach(function(valid_key) {
+ query = valid_alterables.filter(valid_key, alterableResponse[valid_key], quer);
+ });
+ });
+
+ if (!detail) {
+ [req.body, req.query, req.headers].forEach(function(filterableData) {
+ Object.keys(filterableData).filter(function(potential_filter) {
+ return valid_filters.contains(potential_filter, quer);
+ }).forEach(function(valid_key) {
+ quer = valid_filters.filter(valid_key, filterableData[valid_key], quer);
+ });
+ });
+ }
+ return quer;
+}
+
+function preprocess(req, res, next) {
+ req.body = req.body || {};
+ req.query = req.query || {};
+ req.quer = this.filter(req, this.find({}));
+ if (!('locals' in res)) {
+ res.locals = {};
+ }
+ res.locals.bundle = {};
+
+ req.templatePath = resolveTemplate(req);
+ next();
+}
+
+function query(key) {
+ return function(val, query) {
+ return query[key](val);
+ };
+}
+
+function haveOneModel(req) {
+ return !!req.params.id;
+}
+
+function resolveTemplate(req) {
+ var method = req.method.toLowerCase(),
+ tmplName;
+ if (methods.indexOf(method) > -1) {
+ if (haveOneModel(req) && method === 'get') {
+ method += 'Detail';
+ }
+ tmplName = lookup[method];
+ }
+ return tmplName;
+}
+
+/**
+ * Merges a route with another function object
+ * fn.before is called after the old before
+ * fn.after is called before the old after
+ * If fn.handler is specified, then route.handler is overwritten
+ */
+function merge(route, fn) {
+ if (!route) return fn;
+
+ route.before = route.before.concat(fn.before);
+ route.handler = fn.handler || route.handler;
+ route.after = fn.after.concat(route.after);
+ return route;
+}
+
+function getRoute(routes, path) {
+ path = path.replace(/\//g, /\./).split(/\./);
+ if (1 === path.length && '' === path[0]) { // we got the empty string
+ path = [];
+ }
+ if (endpoints.indexOf(path[path.length - 1]) > -1) {
+ path.splice(path.length - 1, 1);
+ }
+ path.forEach(function(sub, i) {
+ if (!routes[sub]) routes[sub] = {};
+ routes = routes[sub];
+ });
+ return routes;
+}
+
+function normalizeHandler(fn) {
+ var result = {};
+ result.handler = fn.handler;
+ result.detail = fn.detail;
+ if ({}.toString.call(fn) == '[object Function]') {
+ result = {
+ handler: fn
+ };
+ }
+ ['before', 'after'].forEach(function(hook) {
+ result[hook] = fn[hook] || [];
+ if (!Array.isArray(result[hook])) {
+ result[hook] = [ result[hook] ];
+ }
+ });
+ return result;
+}
+
+function isEndpoint(route, method) {
+ return endpoints.indexOf(method) > -1 && route[method].handler;
+}
+
+function contains(arr, key) {
+ if (arr.indexOf(key) > -1) return true;
+ for (var obj in arr) {
+ if (obj.method === key) {
+ return true;
+ }
+ }
+ return false;
+};
+
+function coerceData(filter_func, data) {
+ // Assume data is a string
+ if (data && data.toLowerCase && data.toLowerCase() === 'true') {
+ return true;
+ } else if (data && data.toLowerCase && data.toLowerCase() === 'false') {
+ return false;
+ } else if (filter_func === 'limit' || filter_func === 'skip') {
+ return parseInt(data);
+ }
+ return data;
+};
+
+function filterable(props, subfilters) {
+ return {
+ filter: function(key, val, quer) {
+ if (props[key]) {
+ return props[key](val, quer);
+ }
+ var field = key.split('__'),
+ filter_func = field[1] || 'equals',
+ data = coerceData(filter_func, val);
+
+ // Turn data into array for $in and $nin clause
+ if (filter_func === 'in' || filter_func === 'nin') {
+ data = data.split(',');
+ }
+
+ return subfilters[filter_func](data, quer.where(field[0]));
+ },
+ contains: function(key, quer) {
+ if (key in props) return true;
+ var field = key.split('__');
+ var filter_func = field[1] || 'equals';
+ return field[0] in quer.model.schema.paths && filter_func in subfilters;
+ }
+ }
+}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/restful.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/restful.js
new file mode 100644
index 0000000..0194a5b
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/lib/restful.js
@@ -0,0 +1,7 @@
+var model = require('./model'),
+ handlers = require('./handlers'),
+ mongoose = require('mongoose');
+
+exports = module.exports = handlers;
+exports.model = model;
+exports.mongoose = mongoose;
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/LICENSE b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/LICENSE
new file mode 100644
index 0000000..ad0e71b
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative
+Reporters & Editors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/README.md b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/README.md
new file mode 100644
index 0000000..c2ba259
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/README.md
@@ -0,0 +1,22 @@
+ __
+ /\ \ __
+ __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
+ /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
+ \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
+ \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
+ \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
+ \ \____/
+ \/___/
+
+Underscore.js is a utility-belt library for JavaScript that provides
+support for the usual functional suspects (each, map, reduce, filter...)
+without extending any core JavaScript objects.
+
+For Docs, License, Tests, and pre-packed downloads, see:
+http://underscorejs.org
+
+Underscore is an open-sourced component of DocumentCloud:
+https://github.com/documentcloud
+
+Many thanks to our contributors:
+https://github.com/jashkenas/underscore/contributors
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/package.json b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/package.json
new file mode 100644
index 0000000..b4f3bda
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/package.json
@@ -0,0 +1,69 @@
+{
+ "name": "underscore",
+ "description": "JavaScript's functional programming helper library.",
+ "homepage": "http://underscorejs.org",
+ "keywords": [
+ "util",
+ "functional",
+ "server",
+ "client",
+ "browser"
+ ],
+ "author": {
+ "name": "Jeremy Ashkenas",
+ "email": "jeremy@documentcloud.org"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/jashkenas/underscore.git"
+ },
+ "main": "underscore.js",
+ "version": "1.8.3",
+ "devDependencies": {
+ "docco": "*",
+ "eslint": "0.6.x",
+ "karma": "~0.12.31",
+ "karma-qunit": "~0.1.4",
+ "qunit-cli": "~0.2.0",
+ "uglify-js": "2.4.x"
+ },
+ "scripts": {
+ "test": "npm run test-node && npm run lint",
+ "lint": "eslint underscore.js test/*.js",
+ "test-node": "qunit-cli test/*.js",
+ "test-browser": "npm i karma-phantomjs-launcher && ./node_modules/karma/bin/karma start",
+ "build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js",
+ "doc": "docco underscore.js"
+ },
+ "license": "MIT",
+ "files": [
+ "underscore.js",
+ "underscore-min.js",
+ "underscore-min.map",
+ "LICENSE"
+ ],
+ "gitHead": "e4743ab712b8ab42ad4ccb48b155034d02394e4d",
+ "bugs": {
+ "url": "https://github.com/jashkenas/underscore/issues"
+ },
+ "_id": "underscore@1.8.3",
+ "_shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022",
+ "_from": "underscore@1.8.3",
+ "_npmVersion": "1.4.28",
+ "_npmUser": {
+ "name": "jashkenas",
+ "email": "jashkenas@gmail.com"
+ },
+ "maintainers": [
+ {
+ "name": "jashkenas",
+ "email": "jashkenas@gmail.com"
+ }
+ ],
+ "dist": {
+ "shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022",
+ "tarball": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
+}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.js
new file mode 100644
index 0000000..f01025b
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.js
@@ -0,0 +1,6 @@
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
+//# sourceMappingURL=underscore-min.map \ No newline at end of file
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.map b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.map
new file mode 100644
index 0000000..cf356bf
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore-min.map
@@ -0,0 +1 @@
+{"version":3,"file":"underscore-min.js","sources":["underscore.js"],"names":["createReduce","dir","iterator","obj","iteratee","memo","keys","index","length","currentKey","context","optimizeCb","isArrayLike","_","arguments","createPredicateIndexFinder","array","predicate","cb","getLength","createIndexFinder","predicateFind","sortedIndex","item","idx","i","Math","max","min","slice","call","isNaN","collectNonEnumProps","nonEnumIdx","nonEnumerableProps","constructor","proto","isFunction","prototype","ObjProto","prop","has","contains","push","root","this","previousUnderscore","ArrayProto","Array","Object","FuncProto","Function","toString","hasOwnProperty","nativeIsArray","isArray","nativeKeys","nativeBind","bind","nativeCreate","create","Ctor","_wrapped","exports","module","VERSION","func","argCount","value","other","collection","accumulator","apply","identity","isObject","matcher","property","Infinity","createAssigner","keysFunc","undefinedOnly","source","l","key","baseCreate","result","MAX_ARRAY_INDEX","pow","each","forEach","map","collect","results","reduce","foldl","inject","reduceRight","foldr","find","detect","findIndex","findKey","filter","select","list","reject","negate","every","all","some","any","includes","include","fromIndex","guard","values","indexOf","invoke","method","args","isFunc","pluck","where","attrs","findWhere","computed","lastComputed","shuffle","rand","set","shuffled","random","sample","n","sortBy","criteria","sort","left","right","a","b","group","behavior","groupBy","indexBy","countBy","toArray","size","partition","pass","fail","first","head","take","initial","last","rest","tail","drop","compact","flatten","input","shallow","strict","startIndex","output","isArguments","j","len","without","difference","uniq","unique","isSorted","isBoolean","seen","union","intersection","argsLength","zip","unzip","object","findLastIndex","low","high","mid","floor","lastIndexOf","range","start","stop","step","ceil","executeBound","sourceFunc","boundFunc","callingContext","self","TypeError","bound","concat","partial","boundArgs","position","bindAll","Error","memoize","hasher","cache","address","delay","wait","setTimeout","defer","throttle","options","timeout","previous","later","leading","now","remaining","clearTimeout","trailing","debounce","immediate","timestamp","callNow","wrap","wrapper","compose","after","times","before","once","hasEnumBug","propertyIsEnumerable","allKeys","mapObject","pairs","invert","functions","methods","names","extend","extendOwn","assign","pick","oiteratee","omit","String","defaults","props","clone","tap","interceptor","isMatch","eq","aStack","bStack","className","areArrays","aCtor","bCtor","pop","isEqual","isEmpty","isString","isElement","nodeType","type","name","Int8Array","isFinite","parseFloat","isNumber","isNull","isUndefined","noConflict","constant","noop","propertyOf","matches","accum","Date","getTime","escapeMap","&","<",">","\"","'","`","unescapeMap","createEscaper","escaper","match","join","testRegexp","RegExp","replaceRegexp","string","test","replace","escape","unescape","fallback","idCounter","uniqueId","prefix","id","templateSettings","evaluate","interpolate","noMatch","escapes","\\","\r","\n","
","
","escapeChar","template","text","settings","oldSettings","offset","variable","render","e","data","argument","chain","instance","_chain","mixin","valueOf","toJSON","define","amd"],"mappings":"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"} \ No newline at end of file
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore.js
new file mode 100644
index 0000000..b29332f
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/node_modules/underscore/underscore.js
@@ -0,0 +1,1548 @@
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#x27;',
+ '`': '&#x60;'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/package.json b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/package.json
new file mode 100644
index 0000000..1361d30
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "node-restful",
+ "description": "A library for making REST API's in node.js with express",
+ "version": "0.2.5",
+ "peerDependencies": {
+ "mongoose": "~4"
+ },
+ "devDependencies": {
+ "express": "4.12.4",
+ "body-parser": "1.12.4",
+ "method-override": "2.3.3",
+ "mongodb": "2.0.33",
+ "jade": "1.11.0",
+ "mocha": "2.2.5",
+ "mongoose": "~4",
+ "should": "6.0.3",
+ "supertest": "1.0.1",
+ "sinon": "1.15.3",
+ "pow-mongodb-fixtures": "git+https://github.com/riyadhalnur/pow-mongodb-fixtures.git#upgrade-mongodb-drivers",
+ "morgan": "1.5.3"
+ },
+ "keywords": [
+ "node-restful",
+ "restful",
+ "framework",
+ "rest",
+ "api"
+ ],
+ "scripts": {
+ "test": "make test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/baugarten/node-restful"
+ },
+ "main": "index.js",
+ "dependencies": {
+ "underscore": "1.8.3"
+ },
+ "gitHead": "d5277ae484cfb43ddb71dd97580a6989ca281e76",
+ "bugs": {
+ "url": "https://github.com/baugarten/node-restful/issues"
+ },
+ "homepage": "https://github.com/baugarten/node-restful",
+ "_id": "node-restful@0.2.5",
+ "_shasum": "8cfe2ff4b7d769e58e319a50ab15a694107eda53",
+ "_from": "node-restful@latest",
+ "_npmVersion": "1.4.16",
+ "_npmUser": {
+ "name": "baugarten",
+ "email": "baugarten@gmail.com"
+ },
+ "maintainers": [
+ {
+ "name": "baugarten",
+ "email": "baugarten@gmail.com"
+ }
+ ],
+ "dist": {
+ "shasum": "8cfe2ff4b7d769e58e319a50ab15a694107eda53",
+ "tarball": "https://registry.npmjs.org/node-restful/-/node-restful-0.2.5.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/node-restful/-/node-restful-0.2.5.tgz"
+}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/config.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/config.js
new file mode 100644
index 0000000..bdb1208
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/config.js
@@ -0,0 +1,32 @@
+var express = require('express'),
+ fixtures = require('pow-mongodb-fixtures'),
+ app = require('../../examples/movies/'),
+ data = require('./data'),
+ done = false,
+ mongoose,
+ callback;
+
+
+exports.app = app;
+exports.movie = app.movie;
+exports.user = app.user;
+exports.review = app.review
+mongoose = app.mongoose;
+fixtures = fixtures.connect(mongoose.connection.name);
+
+fixtures.load(data, function(err) {
+ exports.users = data.users;
+ exports.movies = data.movies;
+ exports.reviews = data.reviews;
+ done = true;
+ if (callback) return callback();
+});
+
+exports.movies = data.movies;
+exports.users = data.users;
+exports.reviews = data.reviews;
+
+exports.ready = function(cb) {
+ callback = cb;
+ if (done) callback();
+};
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/data.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/data.js
new file mode 100644
index 0000000..7beafd9
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/data.js
@@ -0,0 +1,101 @@
+var ObjectId = require('mongodb').ObjectID;
+
+exports.users = [
+ {
+ _id: new ObjectId(),
+ username: "test",
+ pass_hash: 12374238719845134515,
+ },
+ {
+ _id: new ObjectId(),
+ username: "test2",
+ pass_hash: 1237987381263189273123,
+ }
+];
+
+exports.movies = [
+ {
+ _id: new ObjectId(),
+ title: "Title1",
+ year: 2012,
+ meta: {
+ productionco: "idk",
+ director: exports.users[1]._id,
+ },
+ creator: exports.users[0]._id,
+ secret: "A SECRET STRING",
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title2",
+ year: 2011
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title3",
+ year: 2013
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title4",
+ year: 2013
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title5",
+ year: 2013
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title6",
+ year: 2010
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title7",
+ year: 2011
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title8",
+ year: 2012
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title9",
+ year: 2010
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title10",
+ year: 2011
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title11",
+ year: 2012
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title12",
+ year: 2010
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title13",
+ year: 2011
+ },
+ {
+ _id: new ObjectId(),
+ title: "Title14",
+ year: 2009
+ }
+];
+
+exports.reviews = [
+ {
+ _id: new ObjectId(),
+ body: "This is a movie review!",
+ length: 127
+ }
+];
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/index.jade b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/index.jade
new file mode 100644
index 0000000..a17ae31
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/index.jade
@@ -0,0 +1,4 @@
+h1 index
+
+each item, i in locals
+ li #{item.title}: #{i}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/show.jade b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/show.jade
new file mode 100644
index 0000000..7cb6b3c
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/fixtures/movies/show.jade
@@ -0,0 +1,3 @@
+h1 show
+
+#{title}
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.chainable.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.chainable.js
new file mode 100644
index 0000000..89b083f
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.chainable.js
@@ -0,0 +1,48 @@
+var should = require('should'),
+ request = require('supertest'),
+ restful = require('../'),
+ mongoose = require('mongoose'),
+ sinon = require('sinon');
+
+describe('Model', function() {
+
+ before(function() {
+ restful.model('posts', mongoose.Schema({ title: 'string' }));
+ });
+ it('should return a mongoose model', function() {
+ var posts = restful.model('posts');
+
+ posts.should.have.property('methods');
+ posts.should.have.property('update');
+ posts.should.have.property('remove');
+ posts.should.have.property('updateOptions');
+ posts.should.have.property('removeOptions');
+ });
+ it('should add methods in a chainable way', function() {
+ var posts = restful.model('posts');
+ posts.allowed_methods.should.have.property('get');
+ posts.methods(['get', 'post', 'put'])
+ .updateOptions({})
+ .removeOptions({})
+ .template('/idk/where/this/goes/');
+ posts.allowed_methods.should.containEql('get');
+ posts.allowed_methods.should.containEql('post');
+ posts.allowed_methods.should.containEql('put');
+ posts.update_options.should.be.an.instanceOf(Object);
+ posts.remove_options.should.be.an.instanceOf(Object);
+ posts.templateRoot.should.eql('/idk/where/this/goes');
+
+ });
+ it('should be updateable', function(done) {
+ var Posts = restful.model('posts');
+ Posts.create({
+ title: "First post"
+ }, function(err, post) {
+ post.title.should.equal('First post');
+ Posts.update({_id: post._id}, { title: "Second post"}, function(err, count, resp) {
+ count.n.should.equal(1);
+ done()
+ });
+ })
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.excludes.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.excludes.js
new file mode 100644
index 0000000..ca5e902
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.excludes.js
@@ -0,0 +1,21 @@
+var config = require('./fixtures/config'),
+ request = require('supertest');
+
+describe('Model', function() {
+ var app, movie, user;
+ before(function() {
+ app = config.app;
+ movie = config.movie;
+ user = config.user;
+ });
+ describe('excludes', function() {
+ it('should exclude the excluded fields', function(done) {
+ request(app)
+ .get('/api/movies/' + config.movies[0]._id + '/')
+ .end(function(err, res) {
+ res.body.should.not.have.property('secret');
+ done();
+ });
+ });
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.filters.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.filters.js
new file mode 100644
index 0000000..5cab60d
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.filters.js
@@ -0,0 +1,191 @@
+var should = require('should'),
+ request = require('supertest'),
+ sinon = require('sinon');
+
+describe('Model', function() {
+ var config,
+ movies,
+ users,
+ app,
+ movie1,
+ movie2,
+ movie3,
+ user1,
+ user2;
+ before(function(done) {
+ config = require('./fixtures/config');
+ config.ready(function() {
+ app = config.app;
+ movies = config.movie;
+ users = config.user;
+ movie1 = config.movies[0];
+ movie2 = config.movies[1];
+ movie3 = config.movies[2];
+ user1 = config.users[0];
+ user2 = config.users[1];
+ done();
+ });
+ });
+ describe('filters', function() {
+ it('should limit GET to 10', function(done) {
+ request(app)
+ .get('/api/movies?limit=10')
+ .end(function(err, res) {
+ res.body.length.should.equal(10);
+ done();
+ });
+ });
+ it('should limit GET to 1', function(done) {
+ request(app)
+ .get('/api/movies?limit=1')
+ .end(function(err, res) {
+ res.body.length.should.equal(1);
+ done();
+ });
+ });
+ it('should skip by 5', function(done) {
+ request(app)
+ .get('/api/movies?limit=1&skip=5')
+ .end(function(err, res) {
+ request(app)
+ .get('/api/movies?limit=6')
+ .end(function(err2, res2) {
+ res.body[0].should.eql(res2.body[res2.body.length-1]);
+ done();
+ });
+ });
+ });
+ it('should select fields', function(done) {
+ request(app)
+ .get('/api/movies?select=year')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.should.not.have.property('title');
+ movie.should.have.property('year');
+ });
+ done();
+ });
+ });
+ it('should sort documents', function(done) {
+ request(app)
+ .get('/api/movies?sort=year')
+ .end(function(err, res) {
+ for(var i = 1; i < res.body.length; i++) {
+ (res.body[i].year >= res.body[i-1].year).should.be.true;
+ }
+ done();
+ });
+ });
+ it('should filter fields using equal', function(done) {
+ request(app)
+ .get('/api/movies?year=2011')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.equal(2011);
+ });
+ done();
+ });
+ });
+ it('should filter fields using gte', function(done) {
+ request(app)
+ .get('/api/movies?year__gte=2012')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.be.above(2011);
+ });
+ done();
+ });
+ });
+ it('should filter fields using gt', function(done) {
+ request(app)
+ .get('/api/movies?year__gt=2011')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.be.above(2011);
+ });
+ done();
+ });
+ });
+ it('should filter fields using lt', function(done) {
+ request(app)
+ .get('/api/movies?year__lt=2013')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.be.below(2013);
+ });
+ done();
+ });
+ });
+ it('should filter fields using lte', function(done) {
+ request(app)
+ .get('/api/movies?year__lte=2012')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.be.below(2013);
+ });
+ done();
+ });
+ });
+ it('should filter fields using ne', function(done) {
+ request(app)
+ .get('/api/movies?year__ne=2013')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.year.should.not.equal(2013);
+ });
+ done();
+ });
+ });
+ it('should filter fields using regex', function(done) {
+ request(app)
+ .get('/api/movies?title__regex=2')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ movie.title.should.containEql('2');
+ });
+ done();
+ });
+ });
+ it('should filter fields using regex with options', function(done) {
+ request(app)
+ .get('/api/movies?title__regex=' + encodeURIComponent("/tITLE/i"))
+ .end(function(err, res) {
+ res.body.length.should.be.above(0);
+ res.body.forEach(function(movie) {
+ movie.title.toLowerCase().should.containEql('title');
+ });
+ done();
+ });
+ });
+ it('should populate an objectId', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '?populate=creator')
+ .end(function(err, res) {
+ res.body.creator.username.should.equal(user1.username);
+ res.body.creator.pass_hash.should.equal(user1.pass_hash);
+ done();
+ });
+ });
+ it('should filter using in', function(done) {
+ request(app)
+ .get('/api/movies?year__in=2010,2011')
+ .end(function(err, res) {
+ res.body.forEach(function(movie) {
+ [2010,2011].indexOf(movie.year).should.be.above(-1);
+ });
+ done();
+ });
+ });
+ it('should filter using nin', function(done) {
+ request(app)
+ .get('/api/movies?year__nin=2012,2013,2014')
+ .end(function(err, res) {
+ res.body.length.should.be.above(0)
+ res.body.forEach(function(movie) {
+ [2012,2013,2014].indexOf(movie.year).should.equal(-1);
+ });
+ done();
+ });
+ });
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.handle.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.handle.js
new file mode 100644
index 0000000..10b0e22
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.handle.js
@@ -0,0 +1,54 @@
+var should = require('should'),
+ request = require('supertest'),
+ config = require('./fixtures/config'),
+ sinon = require('sinon');
+
+describe.skip('Model', function() {
+ var movies,
+ users,
+ app,
+ movie1,
+ movie2,
+ movie3,
+ user1,
+ user2;
+ before(function() {
+ app = config.app;
+ movies = config.movie;
+ users = config.user;
+ movie1 = config.movies[0];
+ movie2 = config.movies[1];
+ movie3 = config.movies[2];
+ user1 = config.users[0];
+ user2 = config.users[1];
+ });
+ describe('.handle', function() {
+ it('should handle a pseudo-get route', function(done) {
+ request(app)
+ .get('/api/movies/fakeget')
+ .end(function(err, res) {
+ request(app)
+ .get('/api/movies')
+ .end(function(err2, res2) {
+ res.body.should.eql(res2.body);
+ done();
+ });
+ });
+ });
+ it('should handle a pseudo-postroute', function(done) {
+ request(app)
+ .post('/api/movies/fakepost')
+ .send({
+ title: "A very stupid movie",
+ })
+ .end(function(err, res) {
+ res.body.title.should.equal('A very stupid movie');
+ res.body._id.should.not.be.empty;
+ movies.Model.findById(res.body._id, function(err, model) {
+ model.title.should.equal('A very stupid movie');
+ done();
+ });
+ });
+ });
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.hooks.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.hooks.js
new file mode 100644
index 0000000..9207cbc
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.hooks.js
@@ -0,0 +1,52 @@
+var config = require('./fixtures/config'),
+ request = require('supertest'),
+ sinon = require('sinon');
+
+describe('Model', function() {
+ var app, movie, user;
+ before(function() {
+ app = config.app;
+ movie = config.movie;
+ user = config.user;
+ });
+ describe('before hook', function() {
+ it('should call the before hook on a GET', function() {
+ movie.routes.get.before.length.should.equal(1);
+ movie.routes.get.after.length.should.equal(1);
+ });
+ it('should call the before hook on a POST', function() {
+ movie.routes.post.before.length.should.equal(1);
+ movie.routes.post.after.length.should.equal(1);
+ });
+ it('should call the before hook on a PUT', function() {
+ movie.routes.put.before.length.should.equal(1);
+ movie.routes.put.after.length.should.equal(1);
+ });
+ it('should call after all hook on user defined all route', function(done) {
+ request(app)
+ .get('/api/movies/recommend')
+ .end(function(err, res) {
+ res.body.recommend.should.equal('called');
+ res.body.after.should.equal('called');
+ done();
+ });
+ });
+ it('should call before all hook on user defined get route', function(done) {
+ request(app)
+ .get('/api/movies/' + config.movies[2]._id + '/athirdroute')
+ .end(function(err, res) {
+ res.body.athirdroute.should.equal('called');
+ res.body.after.should.equal('called');
+ done();
+ });
+ });
+ it('should use the properties set in a before route for filtering', function(done) {
+ request(app)
+ .get('/users')
+ .end(function(err, res) {
+ res.body.should.have.length(1);
+ done(err);
+ });
+ });
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.js
new file mode 100644
index 0000000..a51d6cb
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.js
@@ -0,0 +1,301 @@
+var should = require('should'),
+ request = require('supertest'),
+ config = require('./fixtures/config'),
+ sinon = require('sinon'),
+ checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
+
+var oldA = should.Assertion.prototype.a;
+should.Assertion.prototype.a = function(type, desc) {
+ if (type === '_id') {
+ this.assert(checkForHexRegExp.test(this.obj),
+ function() { return 'expected ' + this.inspect + ' to be a ' + type + (desc ? " | " + desc : ""); },
+ function(){ return 'expected ' + this.inspect + ' not to be a ' + type + (desc ? " | " + desc : ""); });
+ return this;
+ }
+ return oldA.call(this, type, desc);
+};
+
+describe('Model', function() {
+ var movies,
+ users,
+ app,
+ movie1,
+ movie2,
+ movie3,
+ user1,
+ user2,
+ review;
+ before(function(done) {
+ config.ready(function() {
+ app = config.app;
+ movies = config.movie;
+ users = config.user;
+ movie1 = config.movies[0];
+ movie2 = config.movies[1];
+ movie3 = config.movies[2];
+ user1 = config.users[0];
+ user2 = config.users[1];
+ review = config.reviews[0];
+ done();
+ });
+ });
+ describe('handlers', function() {
+ it('should handle schema request', function(done) {
+ request(app)
+ .get('/api/movies/schema')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.body.resource.should.equal('movies');
+ res.body.allowed_methods.should.eql(Object.keys(movies.allowed_methods));
+ res.body.fields.should.be.an.instanceOf(Object);
+ Object.keys(movies.schema.paths).forEach(function(path) {
+ res.body.fields.should.have.property(path);
+ });
+ res.body.list_uri.should.equal('/api/movies');
+ res.body.detail_uri.should.equal('/api/movies/:id');
+ done();
+ });
+ });
+
+ it('should dispatch to GET', function(done) {
+ request(app)
+ .get('/api/movies')
+ .expect('Content-Type', /json/)
+ .expect(200, done);
+ });
+ it('should fail POST with no data', function(done) {
+ request(app)
+ .post('/api/movies')
+ .expect('Content-Type', /json/)
+ .expect(400, done);
+ });
+ it('should POST with data', function(done) {
+ request(app)
+ .post('/api/movies')
+ .send({
+ title: "A very stupid movie",
+ year: "214243"
+ })
+ .expect('Content-Type', /json/)
+ .expect(201 )
+ .end(function(err, res) {
+ res.body.title.should.equal('A very stupid movie');
+ res.body._id.should.type('string');
+ done(err);
+ });
+ });
+ it('should PUT data', function(done) {
+ request(app)
+ .put('/api/movies/' + movie2._id)
+ .send({
+ title: 'I changed the movie title'
+ })
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.body.title.should.equal('I changed the movie title');
+ movies.findById(movie2._id, function(err, movie) {
+ movie.title.should.equal('I changed the movie title');
+ done();
+ });
+ });
+ });
+ it('should fail on GET missing resource', function(done) {
+ request(app)
+ .get('/api/movies/55e8169191ad293c221a6c9d')
+ .expect(404, done);
+ });
+ it('should fail on PUT missing resource (shouldUseAtomicUpdate=false)', function(done) {
+ request(app)
+ .put('/api/genres/55e8169191ad293c221a6c9d')
+ .send({
+ name: "Mysterious genre"
+ })
+ .expect(404, done);
+ });
+ it('should fail on PUT missing resource (shouldUseAtomicUpdate=true)', function(done) {
+ request(app)
+ .put('/api/movies/55e8169191ad293c221a6c9d')
+ .send({
+ title: "Mysterious genre"
+ })
+ .expect(404, done);
+ });
+ it('should fail on DELETE missing resource (shouldUseAtomicUpdate=false)', function(done) {
+ request(app)
+ .del('/api/genres/55e8169191ad293c221a6c9d')
+ .expect(404, done);
+ });
+ it('should fail on PUT without filter on unsortable model', function(done) {
+ request(app)
+ .put('/api/movies')
+ .send({
+ title: "A very stupid movie"
+ })
+ .expect(404, done);
+ });
+ it('should fail on DELETE without a filter', function(done) {
+ request(app)
+ .del('/users')
+ .expect(404, done);
+ });
+ it('should DELETE a movie', function(done) {
+ request(app)
+ .del('/api/movies/' + movie3._id)
+ .expect(200)
+ .expect('Content-Type', /json/)
+ .end(function(err, res) {
+ movies.findById(movie3._id, function(err, movie) {
+ should.not.exist(movie);
+ done();
+ });
+ });
+ });
+ it("shouldn't put data on deleted resource", function(done) {
+ request(app)
+ .del('/api/movies/' + config.movies[5]._id)
+ .end(function(err, res) {
+ request(app)
+ .put('/api/movies/' + config.movies[5]._id)
+ .send({
+ title: 'But I already deleted you'
+ })
+ .expect(404, done);
+ });
+ });
+ it('should 400 deleting a resource twice', function(done) {
+ request(app)
+ .del('/api/movies/' + config.movies[6]._id)
+ .end(function() {
+ request(app)
+ .del('/api/movies/' + config.movies[6]._id)
+ .expect(404, done);
+ });
+ });
+ it('should 404 on undefined route', function(done) {
+ request(app)
+ .del('/api/movies')
+ .expect(404, done);
+ });
+ it('should return a nested model at the generated endpoint creator', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '/creator')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ if (err) return done(err);
+ res.should.be.json;
+ res.body.username.should.equal('test');
+ res.body.pass_hash.should.equal(12374238719845134515);
+ done();
+ });
+ });
+ it('should 404 if we request an object endpoint without a filter', function(done) {
+ request(app)
+ .get('/api/movies/creator')
+ .expect(404, done);
+ });
+ it('should retrieve a deeply nested endpoint', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '/meta/director')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.should.be.json;
+ res.body.username.should.equal('test2');
+ res.body.pass_hash.should.equal(1237987381263189273123);
+ done();
+ });
+
+ });
+ it('should 404 on a nested object', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '/meta')
+ .expect(404, done)
+ });
+ it('should get a user defined route', function(done) {
+ request(app)
+ .get('/api/movies/recommend')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.should.be.json;
+ res.body.recommend.should.equal("called");
+ done();
+ });
+ });
+ it('should get anotheroute (user defined route)', function(done) {
+ request(app)
+ .get('/api/movies/anotherroute')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.should.be.json;
+ res.body.anotherroute.should.equal("called");
+ done();
+ });
+ });
+ it('should get athirdroute (user defined route)', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '/athirdroute')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ res.should.be.json;
+ res.body.athirdroute.should.equal("called");
+ done();
+ });
+ });
+ it('should fail athirdroute (user defined route)', function(done) {
+ request(app)
+ .get('/api/movies/athirdroute')
+ .expect(404, done);
+ });
+ it('should fail athirdroute (user defined route)', function(done) {
+ request(app)
+ .put('/api/movies/' + movie1._id + '/athirdroute')
+ .expect(404, done);
+ });
+ it('should allow put of entire object', function(done) {
+ request(app)
+ .get('/api/movies/' + config.movies[7]._id)
+ .end(function(err, res) {
+ var movie = res.body;
+ movie.title = 'A different title';
+ request(app)
+ .put('/api/movies/' + movie._id)
+ .send(movie)
+ .expect('Content-Type', /json/)
+ .expect(201)
+ .end(function(err, res) {
+ res.body.title.should.equal('A different title');
+ done();
+ });
+ });
+ });
+ it('should allow overriding of schema route', function(done) {
+ request(app)
+ .get('/users/schema')
+ .expect(404, done);
+ });
+ it('should allow multiple handlers to be called on a single route', function(done) {
+ request(app)
+ .get('/api/movies/pshh')
+ .expect(200)
+ .end(function(err, res) {
+ res.body.pshh.should.equal('called');
+ done(err);
+ });
+ });
+ it('should allow get request for model with field named `length`', function(done) {
+ request(app)
+ .get('/api/reviews/' + review._id)
+ .expect(200)
+ .end(function(err, res) {
+ res.body.body.should.equal('This is a movie review!');
+ done(err);
+ });
+ });
+ });
+});
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.template.js b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.template.js
new file mode 100644
index 0000000..8174391
--- /dev/null
+++ b/common/src/main/webapp/usageguide/appserver/node_modules/node-restful/test/model.template.js
@@ -0,0 +1,62 @@
+var should = require('should'),
+ request = require('supertest'),
+ config = require('./fixtures/config'),
+ sinon = require('sinon');
+
+describe.skip('Model', function() {
+ var movies,
+ users,
+ app,
+ movie1,
+ movie2,
+ movie3,
+ user1,
+ user2;
+ before(function() {
+ app = config.app;
+ movies = config.movie;
+ users = config.user;
+ movie1 = config.movies[0];
+ movie2 = config.movies[1];
+ movie3 = config.movies[2];
+ user1 = config.users[0];
+ user2 = config.users[1];
+ });
+ describe('.template(route, filters)', function() {
+ it('should work for get', function() {
+ var template = movies.template(['get'], []);
+ template.should.equal('index');
+ });
+ it('should work for getDetail', function() {
+ var template = movies.template(['get'], [{ key: '_id', value: 'ad' }]);
+ template.should.equal('show');
+ });
+ });
+ describe('format=html', function() {
+ it('should render index', function(done) {
+ request(app)
+ .get('/api/movies?format=html')
+ .expect('Content-Type', /html/)
+ .end(function(err, res) {
+ res.text.should.match(/index/);
+ res.text.should.match(new RegExp(movie1.title));
+ res.text.should.match(new RegExp(movie2.title));
+ res.text.should.match(new RegExp(movie3.title));
+ done();
+ });
+ });
+ it('should render show', function(done) {
+ request(app)
+ .get('/api/movies/' + movie1._id + '/?format=html')
+ .expect('Content-Type', /html/)
+ .end(function(err, res) {
+ res.text.should.match(/show/);
+ res.text.should.match(new RegExp(movie1.title));
+ res.text.should.not.match(new RegExp(movie2.title));
+ res.text.should.not.match(new RegExp(movie3.title));
+ done();
+ });
+
+ });
+ });
+});