-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to Feathers Buzzard (v3) (#224)
* Update to Feathers Buzzard (v3) * Increase timeout
- Loading branch information
Showing
12 changed files
with
806 additions
and
3,824 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ language: node_js | |
services: mongodb | ||
node_js: | ||
- 'node' | ||
- '8' | ||
- '6' |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,247 @@ | ||
feathers-mongoose | ||
================ | ||
# feathers-mongoose | ||
|
||
[![Greenkeeper badge](https://badges.greenkeeper.io/feathersjs/feathers-mongoose.svg)](https://greenkeeper.io/) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/feathersjs-ecosystem/feathers-mongoose.svg)](https://greenkeeper.io/) | ||
|
||
[![Build Status](https://travis-ci.org/feathersjs/feathers-mongoose.png?branch=master)](https://travis-ci.org/feathersjs/feathers-mongoose) | ||
[![Code Climate](https://codeclimate.com/github/feathersjs/feathers-mongoose/badges/gpa.svg)](https://codeclimate.com/github/feathersjs/feathers-mongoose) | ||
[![Test Coverage](https://codeclimate.com/github/feathersjs/feathers-mongoose/badges/coverage.svg)](https://codeclimate.com/github/feathersjs/feathers-mongoose/coverage) | ||
[![Dependency Status](https://img.shields.io/david/feathersjs/feathers-mongoose.svg?style=flat-square)](https://david-dm.org/feathersjs/feathers-mongoose) | ||
[![Build Status](https://travis-ci.org/feathersjs-ecosystem/feathers-mongoose.png?branch=master)](https://travis-ci.org/feathersjs-ecosystem/feathers-mongoose) | ||
[![Dependency Status](https://img.shields.io/david/feathersjs-ecosystem/feathers-mongoose.svg?style=flat-square)](https://david-dm.org/feathersjs-ecosystem/feathers-mongoose) | ||
[![Download Status](https://img.shields.io/npm/dm/feathers-mongoose.svg?style=flat-square)](https://www.npmjs.com/package/feathers-mongoose) | ||
[![Slack Status](http://slack.feathersjs.com/badge.svg)](http://slack.feathersjs.com) | ||
|
||
|
||
> Create a [Mongoose](http://mongoosejs.com/) ORM wrapped service for [FeathersJS](https://github.com/feathersjs). | ||
|
||
## Installation | ||
A [Feathers](https://feathersjs.com) database adapter for [Mongoose](http://mongoosejs.com/), an object modeling tool for [MongoDB](https://www.mongodb.org/). | ||
|
||
```bash | ||
npm install feathers-mongoose --save | ||
$ npm install --save mongoose feathers-mongoose | ||
``` | ||
|
||
## Documentation | ||
> __Important:__ `feathers-mongoose` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html). | ||
Please refer to the [Feathers database adapter documentation](https://docs.feathersjs.com/api/databases/common.html) for more details or directly at: | ||
> This adapter also requires a [running MongoDB](https://docs.mongodb.com/getting-started/shell/#) database server. | ||
- [Mongoose](https://docs.feathersjs.com/api/databases/mongoose.html) - The detailed documentation for this adapter | ||
- [Extending](https://docs.feathersjs.com/api/databases/common.html#extending-adapters) - How to extend a database adapter | ||
- [Pagination](https://docs.feathersjs.com/api/databases/common.html#pagination) - How to use pagination | ||
- [Querying and Sorting](https://docs.feathersjs.com/api/databases/querying.html) - The common adapter querying mechanism and sorting for the database adapter | ||
|
||
## Getting Started | ||
## API | ||
|
||
Creating an Mongoose service is this simple (make sure your MongoDB server is up and running): | ||
### `service(options)` | ||
|
||
Returns a new service instance initialized with the given options. `Model` has to be a Mongoose model. See the [Mongoose Guide](http://mongoosejs.com/docs/guide.html) for more information on defining your model. | ||
|
||
```js | ||
var mongoose = require('mongoose'); | ||
var MongooseModel = require('./models/mymodel') | ||
var mongooseService = require('feathers-mongoose'); | ||
const mongoose = require('mongoose'); | ||
const service = require('feathers-mongoose'); | ||
|
||
// A module that exports your Mongoose model | ||
const Model = require('./models/message'); | ||
|
||
// Make Mongoose use the ES6 promise | ||
mongoose.Promise = global.Promise; | ||
|
||
// Connect to a local database called `feathers` | ||
mongoose.connect('mongodb://localhost:27017/feathers'); | ||
|
||
app.use('/todos', mongooseService({ | ||
Model: MongooseModel | ||
})); | ||
app.use('/messages', service({ Model })); | ||
app.use('/messages', service({ Model, lean, id, events, paginate })); | ||
``` | ||
|
||
__Options:__ | ||
|
||
- `Model` (**required**) - The Mongoose model definition | ||
- `lean` (*optional*, default: `true`) - Runs queries faster by returning plain objects instead of Mongoose models. | ||
- `id` (*optional*, default: `'_id'`) - The name of the id field property. | ||
- `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service | ||
- `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size | ||
- `discriminators` (*optional*) - A list of mongoose models that inherit from `Model`. | ||
|
||
> **Important:** To avoid odd error handling behaviour, always set `mongoose.Promise = global.Promise`. If not available already, Feathers comes with a polyfill for native Promises. | ||
<!-- --> | ||
|
||
> **Important:** When setting `lean` to `false`, Mongoose models will be returned which can not be modified unless they are converted to a regular JavaScript object via `toObject`. | ||
<!-- --> | ||
|
||
> **Note:** You can get access to the Mongoose model via `this.Model` inside a [hook](https://docs.feathersjs.com/api/hooks.html) and use it as usual. See the [Mongoose Guide](http://mongoosejs.com/docs/guide.html) for more information on defining your model. | ||
### params.mongoose | ||
|
||
When making a [service method](https://docs.feathersjs.com/api/services.html) call, `params` can contain a `mongoose` property which allows you to modify the options used to run the Mongoose query. Normally, this will be set in a before [hook](https://docs.feathersjs.com/api/hooks.html): | ||
|
||
```js | ||
app.service('messages').hooks({ | ||
before: { | ||
patch(context) { | ||
// Set some additional Mongoose options | ||
// The adapter tries to use sane defaults | ||
// but they can always be changed here | ||
context.params.mongoose = { | ||
runValidators: true, | ||
setDefaultsOnInsert: true | ||
} | ||
} | ||
} | ||
}); | ||
``` | ||
|
||
See the [Mongoose Guide](http://mongoosejs.com/docs/guide.html) for more information on defining your model. | ||
The `mongoose` property is also useful for performing upserts on a `patch` request. "Upserts" do an update if a matching record is found, or insert a record if there's no existing match. The following example will create a document that matches the `data`, or if there's already a record that matches the `params.query`, that record will be updated. | ||
|
||
```js | ||
const data = { address: '123', identifier: 'my-identifier' } | ||
const params = { | ||
query: { address: '123' }, | ||
mongoose: { upsert: true } | ||
} | ||
app.service('address-meta').patch(null, data, params) | ||
``` | ||
|
||
### Complete Example | ||
|
||
Here's a complete example of a Feathers server with a `message` mongoose-service. | ||
## Example | ||
|
||
Here's a complete example of a Feathers server with a `messages` Mongoose service. | ||
|
||
``` | ||
$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express mongoose feathers-mongoose | ||
``` | ||
|
||
In `message-model.js`: | ||
|
||
```js | ||
const feathers = require('feathers'); | ||
const rest = require('feathers-rest'); | ||
const socketio = require('feathers-socketio'); | ||
const errors = require('feathers-errors'); | ||
const bodyParser = require('body-parser'); | ||
const mongoose = require('mongoose'); | ||
const service = require('feathers-mongoose'); | ||
|
||
// Require your models | ||
const Message = require('./models/message'); | ||
const Schema = mongoose.Schema; | ||
const MessageSchema = new Schema({ | ||
text: { | ||
type: String, | ||
required: true | ||
} | ||
}); | ||
const Model = mongoose.model('Message', MessageSchema); | ||
|
||
// Tell mongoose to use native promises | ||
// See http://mongoosejs.com/docs/promises.html | ||
mongoose.Promise = global.Promise; | ||
module.exports = Model; | ||
``` | ||
|
||
// Connect to your MongoDB instance(s) | ||
mongoose.connect('mongodb://localhost:27017/feathers'); | ||
Then in `app.js`: | ||
|
||
```js | ||
const feathers = require('@feathersjs/feathers'); | ||
const express = require('@feathersjs/express'); | ||
const socketio = require('@feathersjs/socketio'); | ||
|
||
// Create a feathers instance. | ||
const app = feathers() | ||
// Enable Socket.io | ||
.configure(socketio()) | ||
// Enable REST services | ||
.configure(rest()) | ||
// Turn on JSON parser for REST services | ||
.use(bodyParser.json()) | ||
// Turn on URL-encoded parser for REST services | ||
.use(bodyParser.urlencoded({extended: true})); | ||
const mongoose = require('mongoose'); | ||
const service = require('feathers-mongoose'); | ||
|
||
const Model = require('./message-model'); | ||
|
||
mongoose.Promise = global.Promise; | ||
|
||
// Connect to your MongoDB instance(s) | ||
mongoose.connect('mongodb://localhost:27017/feathers', { | ||
useMongoClient: true | ||
}); | ||
|
||
// Create an Express compatible Feathers application instance. | ||
const app = express(feathers()); | ||
|
||
// Turn on JSON parser for REST services | ||
app.use(express.json()); | ||
// Turn on URL-encoded parser for REST services | ||
app.use(express.urlencoded({extended: true})); | ||
// Enable REST services | ||
app.configure(express.rest()); | ||
// Enable Socket.io services | ||
app.configure(socketio()); | ||
// Connect to the db, create and register a Feathers service. | ||
app.use('messages', service({, | ||
Model: Message, | ||
app.use('/messages', service({ | ||
Model, | ||
lean: true, // set to false if you want Mongoose documents returned | ||
paginate: { | ||
default: 2, | ||
max: 4 | ||
} | ||
})); | ||
app.use(express.errorHandler()); | ||
|
||
// Create a dummy Message | ||
app.service('messages').create({ | ||
text: 'Message created on server' | ||
}).then(function(message) { | ||
console.log('Created message', message); | ||
}); | ||
|
||
// Start the server. | ||
const port = 3030; | ||
app.listen(port, () => { | ||
console.log(`Feathers server listening on port ${port}`); | ||
}); | ||
``` | ||
|
||
You can run this example by using `node app` and go to [localhost:3030/messages](http://localhost:3030/messages). | ||
|
||
## Querying, Validation | ||
|
||
Mongoose by default gives you the ability to add [validations at the model level](http://mongoosejs.com/docs/validation.html). Using an error handler like the one that [comes with Feathers](https://github.com/feathersjs/feathers-errors/blob/master/src/error-handler.js) your validation errors will be formatted nicely right out of the box! | ||
|
||
For more information on querying and validation refer to the [Mongoose documentation](http://mongoosejs.com/docs/guide.html). | ||
|
||
## $populate | ||
|
||
For Mongoose, the special `$populate` query parameter can be used to allow [Mongoose query population](http://mongoosejs.com/docs/populate.html). | ||
|
||
// A basic error handler, just like Express | ||
app.use(errors.handler()); | ||
```js | ||
app.service('posts').find({ | ||
query: { $populate: 'user' } | ||
}); | ||
``` | ||
|
||
## Discriminators (Inheritance) | ||
|
||
Instead of strict inheritance, Mongoose uses [discriminators](http://mongoosejs.com/docs/discriminators.html) as their schema inheritance model. | ||
To use them, pass in a `discriminatorKey` option to your schema object and use `Model.discriminator('modelName', schema)` instead of `mongoose.model()` | ||
|
||
Feathers comes with full support for mongoose discriminators, allowing for automatic fetching of inherited types. A typical use case might look like: | ||
|
||
```js | ||
var mongoose = require('mongoose'); | ||
var Schema = mongoose.Schema; | ||
var Post = require('./post'); | ||
var feathers = require('@feathersjs/feathers'); | ||
var app = feathers(); | ||
var service = require('feathers-mongoose'); | ||
|
||
// Discriminator key, we'll use this later to refer to all text posts | ||
var options = { | ||
discriminatorKey: '_type' | ||
}; | ||
|
||
app.listen(3030); | ||
console.log('Feathers Message mongoose service running on 127.0.0.1:3030'); | ||
var TextPostSchema = new Schema({ | ||
text: { type: String, default: null } | ||
}, options); | ||
|
||
TextPostSchema.index({'updatedAt': -1, background: true}); | ||
|
||
// Note the use of `Post.discriminator` rather than `mongoose.discriminator`. | ||
var TextPost = Post.discriminator('text', TextPostSchema); | ||
|
||
// Using the discriminators option, let feathers know about any inherited models you may have | ||
// for that service | ||
app.use('/posts', service({ | ||
Model: Post, | ||
discriminators: [TextPost] | ||
})) | ||
|
||
``` | ||
|
||
Without support for discriminators, when you perform a `.get` on the posts service, you'd only get back `Post` models, not `TextPost` models. | ||
Now in your query, you can specify a value for your discriminatorKey: | ||
|
||
```js | ||
{ | ||
_type: 'text' | ||
} | ||
``` | ||
|
||
You can run this example by using `npm start` and going to [localhost:3030/messages](http://localhost:3030/messages). You should see an empty array. That's because you don't have any messages yet but you now have full CRUD for your new message service, including mongoose validations! | ||
and Feathers will automatically swap in the correct model and execute the query it instead of its parent model. | ||
|
||
## License | ||
|
||
[MIT](LICENSE) | ||
|
||
## Authors | ||
|
||
- [Feathers contributors](https://github.com/feathersjs/feathers-mongoose/graphs/contributors) | ||
- [Feathers contributors](https://github.com/feathersjs-ecosystem/feathers-mongoose/graphs/contributors) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
--recursive test/ | ||
--timeout 5000 | ||
--exit |
Oops, something went wrong.