Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/saintedlama/restify-mongoose
Restify-Mongoose provides a resource abstraction to expose mongoose models as REST resources.
https://github.com/saintedlama/restify-mongoose
javascript mongoose rest-api restify
Last synced: 7 days ago
JSON representation
Restify-Mongoose provides a resource abstraction to expose mongoose models as REST resources.
- Host: GitHub
- URL: https://github.com/saintedlama/restify-mongoose
- Owner: saintedlama
- License: bsd-2-clause
- Created: 2014-01-23T21:15:54.000Z (almost 11 years ago)
- Default Branch: master
- Last Pushed: 2024-09-06T07:39:39.000Z (4 months ago)
- Last Synced: 2024-10-12T12:25:40.853Z (2 months ago)
- Topics: javascript, mongoose, rest-api, restify
- Language: JavaScript
- Size: 1.78 MB
- Stars: 110
- Watchers: 8
- Forks: 34
- Open Issues: 50
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: contributing.md
- License: LICENSE
Awesome Lists containing this project
README
# Restify-Mongoose
[![NPM](https://nodei.co/npm/restify-mongoose.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/restify-mongoose/)[![Build Status](https://travis-ci.org/saintedlama/restify-mongoose.png?branch=master)](https://travis-ci.org/saintedlama/restify-mongoose)
[![Coverage Status](https://coveralls.io/repos/saintedlama/restify-mongoose/badge.png?branch=master)](https://coveralls.io/r/saintedlama/restify-mongoose?branch=master)
[![Dependencies Status](https://david-dm.org/saintedlama/restify-mongoose.svg)](https://david-dm.org/saintedlama/restify-mongoose)
[![devDependency Status](https://david-dm.org/saintedlama/restify-mongoose/dev-status.svg)](https://david-dm.org/saintedlama/restify-mongoose#info=devDependencies)Restify-Mongoose provides a resource abstraction for [restify](http://mcavage.me/node-restify/) to expose mongoose models as REST resources.
## Getting started
First you'll need to install restify-mongoose via npmnpm install restify-mongoose
Second step is to wire up mongoose and restify using restify-mongoose
```javascript
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.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser());
server.use(restify.plugins.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:```javascript
// 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.```javascript
// 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__
```javascript
// 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` functionYou can also pass an options object to the `serve` method to attach handlers before and after the request.
For example, to use [restify-jwt](https://github.com/auth0/express-jwt):```javascript
// Serve resource notes with quick mapping with JWT auth
restifyMongoose(models.Note).serve('/api/notes', server, { before: jwt({secret: 'some-secret'}) } );
```## Queries
Query parameters are passed by query string parameter __q__.Query parameters are parsed as JSON objects and passed to [mongoose where query function](http://mongoosejs.com/docs/api.html#query_Query-where).
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) by adding it to the options.```javascript
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
An additional restriction to page sizes can be made with `maxPageSize` option (default value is 100) that defines the
maximum allowed page size to avoid unbound queries.### Link Header
The pagination info is included in [the Link header](http://tools.ietf.org/html/rfc5988). It is important to follow
these Link header values instead of constructing your own URLs.link:
; rel="first",
; rel="prev",
; rel="next",
; rel="last"_Linebreak is included for readability._
You can set the `baseUrl` by adding it to the options.
```javascript
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 can be separated by comma or space. They will be passed directly to [mongoose sort query function](http://mongoosejs.com/docs/api.html#query_Query-sort).
To sort a notes resource by title descending append the __sort__ query parameter to the URL:
http://localhost:3000/notes?sort=-title
You can also define a default sort in the options object. This option will by ignored if a __sort__ query parameter exists.
Using in the constructor:
```javascript
var notes = restifyMongoose(Note, {sort: '-title'});
notes.serve('/notes', restifyServer);
```Using for query or detail methods:
```javascript
var notes = restifyMongoose(Note);
note.query({sort: '-title'});## Select Fields
To restrict selected columns you can pass a query string parameter __select__.Select fields can be separated by comma or space. They will be passed to [mongoose select query function](http://mongoosejs.com/docs/api.html#query_Query-select).
To select only title and date the fields of a notes resource append the __select__ query parameter to the URL:
http://localhost:3000/notes?select=title,date
You can also define select fields in the options object. This will make the the __select__ query parameter be ignored.
Using in the constructor:
```javascript
var notes = restifyMongoose(Note, {select: 'title'});
notes.serve('/notes', restifyServer);
```Using for query or detail methods:
```javascript
var notes = restifyMongoose(Note);
note.detail({select: 'title,date,tags'});
note.query({select: 'title 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](http://mongoosejs.com/docs/api.html#query_Query-where).
For instance, you can use a filter to display only results for a particular user:
```javascript
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:
```javascript
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.
```javascript
// 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`
```javascript
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);```javascript
users.detail({projection: userProjection});
users.query({projection: userProjection});
```
## Output formatThe output format can be changed to a more compatible one with the [json-api](http://jsonapi.org/format/) standard to use the API with frameworks like Ember.
```javascript
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);
```## Populating referenced documents
The returned results can use mongoose's "populate" query modifier to populated referenced documents within models.
Referenced documents can be populated in three ways:
#### query parameter
Adding `populate=[referenced_field]` to the query string will populate the `referenced_field`, if it exists.#### Resource option
```javascript
// e.g.
var notes = restifyMongoose(Note, {populate: 'author'});
```#### query / detail method options
```javascript
// e.g.
server.get('/notes', notes.query({populate: 'author'}))
server.get('/notes/:id', notes.detail({populate: 'author'}))
```### Populating multiple fields
Multiple referenced documents can be populated by using a comma-delimited list of the desired fields in any of the three methods above.
```javascript
// e.g.
var notes = restifyMongoose(Note, {populate: 'author,contributors'});
```# Contribute
Contribution welcome! Read the [contribution guideline](contributing.md) first.