Skip to content

Restify-Mongoose provides a resource abstraction to expose mongoose models as REST resources.

License

Notifications You must be signed in to change notification settings

ismarslomic/restify-mongoose

 
 

Repository files navigation

Restify-Mongoose

NPM

Build Status Coverage Status Dependencies Status devDependency Status

Restify-Mongoose provides a resource abstraction for restify to expose mongoose models as REST resources.

Getting started

First you'll need to install restify-mongoose via npm

npm install restify-mongoose

Second step is to wire up mongoose and restify using restify-mongoose

var restify = require('restify');
var restifyMongoose = require('restify-mongoose');
var mongoose = require('mongoose');

var server = restify.createServer({
    name: 'restify.mongoose.examples.notes',
    version: '1.0.0'
});

server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());

// Create a simple mongoose model 'Note'
var NoteSchema = new mongoose.Schema({
    title : { type : String, required : true },
    date : { type : Date, required : true },
    tags : [String],
    content : { type: String }
});

var Note = mongoose.model('notes', NoteSchema);

// Now create a restify-mongoose resource from 'Note' mongoose model
var notes = restifyMongoose(Note);

// Serve resource notes with fine grained mapping control
server.get('/notes', notes.query());
server.get('/notes/:id', notes.detail());
server.post('/notes', notes.insert());
server.patch('/notes/:id', notes.update());
server.del('/notes/:id', notes.remove());

server.listen(3000, function () {
    console.log('%s listening at %s', server.name, server.url);
});

Resources

To map resources or resource functionality to restify REST endpoints/routes restify-mongoose offers two approaches:

  • 'fine grained mapping' control via list, detail, new, update and delete functions
  • 'quick mapping' via serve method

Fine grained mapping In the above getting started example we used fine grained mapping control. Restify-mongoose defines the functions query, detail, insert, update and remove that return restify route handlers and can be used like this:

 // Serve resource notes with fine grained mapping control
 server.get('/notes', notes.query());
 server.get('/notes/:id', notes.detail());
 server.post('/notes', notes.insert());
 server.patch('/notes/:id', notes.update());
 server.del('/notes/:id', notes.remove());

For every ´id´ dependent function the restify route has to define a :id placeholder to allow restify-mongoose to access id parameters. Id dependent functions are detail, update and delete.

Query String

Setting a queryString will make restify-mongoose use the string as the field name to conduct its searches in the detail update & remove functions. If not set it will use the default behavior of using mongos _id field.

// Now create a restify-mongoose resource from 'Note' mongoose model and set queryString to 'myField'
var notes = restifyMongoose(Note, {queryString: 'myField'});

// these functions will now conduct searches with the field 'myField'. (defaults to '_id')
server.get('/notes/:id', notes.detail());
server.patch('/notes/:id', notes.update());
server.del('/notes/:id', notes.remove());

Quick mapping

// Serve resource notes with quick mapping
restifyMongoose(models.Note).serve('/api/notes', server);

Maps urls

  • GET '/api/notes' to query function
  • GET '/api/notes/:id' to detail function
  • POST '/api/notes' to insert function
  • DELETE '/api/notes/:id' to remove function
  • PATCH '/api/notes/:id' to update function

Queries

Query parameters are passed by query string parameter q.

Query parameters are parsed as JSON objects and passed to mongoose where query function.

To filter a notes resource by title to match term "first" append the q query parameter to the URL:

http://localhost:3000/notes?q={"title":"first"}

Paginate

Requests that return multiple items in query will be paginated to 100 items by default. You can set the pageSize (number min=1, max=100) by adding it to the options.

var options = {
	pageSize: 2
};

var notes = restifyMongoose(Note, options);

or as query string parameter pageSize (which will have the presedence)

http://localhost:3000/notes?pageSize=2

You can specify further pages with the p parameter and a page number.

http://localhost:3000/notes?p=1

Link Header

The pagination info is included in the Link header. It is important to follow these Link header values instead of constructing your own URLs.

link:
<http://example.com/notes?p=0>; rel="first",
<http://example.com/notes?p=1>; rel="prev",
<http://example.com/notes/?p=3>; rel="next",
<http://example.com/notes/?p=4>; rel="last"

Linebreak is included for readability.

You can set the baseUrl by adding it to the options.

var options = {
	baseUrl: 'http://example.com'
};

The possible rel values are:

  • next - Shows the URL of the immediate next page of results.
  • last - Shows the URL of the last page of results.
  • first - Shows the URL of the first page of results.
  • prev - Shows the URL of the immediate previous page of results.

Total Count Header

The total number of results/resources returned in query is sent in the X-Total-Count Header and is not affected by pagination (setting pageSize and p parameter). It does take in account filter and query parameter ( q ).

Sort

Sort parameters are passed by query string parameter sort.

Sort parameters are passed directly to mongoose sort query function.

To sort a notes resource by title descending append the sort query parameter to the URL:

http://localhost:3000/notes?sort=-title

Select Fields

To restrict selected columns you can pass a query string parameter select.

Select fields are passed directly to mongoose select query function.

To select only date the field of a notes resource append the select query parameter to the URL:

http://localhost:3000/notes?select=date

Filter

Results can be filtered with a function, which is set in the options object of the constructor or on the query and detail function.

The function takes two parameters: the request object and the response object. The return value of the function is a query that is passed directly to the mongoose where query function.

For instance, you can use a filter to display only results for a particular user:

var filterUser = function(req, res) {
  return {user: req.user};
}

var notes = restifyMongoose(Note, {filter: filterUser});

Projection

A projection is a function, used by the query and detail operations, which takes the request object, the result model, and a callback. This function should invoke the callback exactly once. This callback takes an error and a model item as it's two parameters. Use null for the error is there is no error.

For instance, the default detail and list projections are as follows:

function (req, item, cb) {
  cb(null, item);
};

A projection is useful if you need to manipulate the result item before returning it in the response. For instance, you may not want to return the passwordHash for a User data model.

// If this is the schema
var UserSchema = new Schema({
  username: String,
  email: String,
  passwordHash: String
});

// This is a projection translating _id to id and not including passwordHash
var userProjection = function(req, item, cb) {
  var user = {
    id: item._id,
    username: item.username,
    email: item.email
  };
  cb(null, user);
};

Projection functions are specified in the options for the resitfy-mongoose contructor, the query function, or the detail function.

For the construtor, the options are listProjection and detailProjection

var users = restifyMongoose(User, {listProjection: userProjection, detailProjection: userProjection});
users.serve('/users', restifyServer);

For both query and detail, the option is projection var users = restifyMongoose(User);

users.detail({projection: userProjection});
users.query({projection: userProjection});

Output format

The output format can be changed to a more compatible one with the json-api standard to use the API with frameworks like Ember.

var users = restifyMongoose(User, {outputFormat: 'json-api'});
users.serve('/users', restifyServer);
``
Also you can specify a custom model name like this:

```javascript
var users = restifyMongoose(User, {outputFormat: 'json-api', modelName: 'admins'});
users.serve('/users', restifyServer);

Contribute

Contribution welcome! Read the contribution guideline first.

About

Restify-Mongoose provides a resource abstraction to expose mongoose models as REST resources.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 90.0%
  • HTML 10.0%