Skip to content

Commit

Permalink
Merge pull request #8 from feathersjs/es6
Browse files Browse the repository at this point in the history
Migration to new service tests and ES6
  • Loading branch information
ekryski committed Jan 6, 2016
2 parents 8879278 + 63a5c8e commit 677501f
Show file tree
Hide file tree
Showing 11 changed files with 517 additions and 299 deletions.
5 changes: 5 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

{
"plugins": ["add-module-exports"],
"presets": [ "es2015" ]
}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ Session.vim
# *.sublime-project

# === Webstorm ===
.idea
.idea

lib/
5 changes: 5 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.babelrc
.idea/
src/
test/
!lib/
204 changes: 160 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ npm install feathers-nedb --save
Creating an NeDB service is this simple:

```js
var nedb = require('feathers-nedb');
var service = require('feathers-nedb');
var nedb = require('nedb');


app.use('todos', nedb('todos', options));
```

This will create a `todos` datastore file in the `db-data` directory and automatically load it. If you delete that file, the data will be deleted.
This will create a `todos` datastore file in the `db-data` directory and automatically load it. If you delete that file, the data will be deleted.


### Complete Example
Expand All @@ -32,9 +35,15 @@ Here's an example of a Feathers server with a `todos` nedb-service.

```js
// server.js
var feathers = require('feathers'),
bodyParser = require('body-parser'),
nedb = require('feathers-nedb');
var NeDB = require('nedb');
var feathers = require('feathers');
var bodyParser = require('body-parser');
var service = require('feathers-nedb');

var db = new NeDB({
filename: './data/todos.db',
autoload: true
});

// Create a feathers instance.
var app = feathers()
Expand All @@ -47,80 +56,180 @@ var app = feathers()
// Turn on JSON parser for REST services
.use(bodyParser.json())
// Turn on URL-encoded parser for REST services
.use(bodyParser.urlencoded({extended: true}))
.use(bodyParser.urlencoded({extended: true}));

// Connect to the db, create and register a Feathers service.
app.use('todos', nedb('todos'));
app.use('todos', service({
Model: db,
paginate: {
default: 2,
max: 4
}
}));

// Start the server.
var port = 8080;
var port = 3030;
app.listen(port, function() {
console.log('Feathers server listening on port ' + port);
});
```

You can run this example by using `node examples/basic` and going to [localhost:8080/todos](http://localhost:8080/todos). You should see an empty array. That's because you don't have any Todos yet but you now have full CRUD for your new todos service, including mongoose validations!
You can run this example by using `node examples/app` and going to [localhost:3030/todos](http://localhost:3030/todos). You should see an empty array. That's because you don't have any Todos yet but you now have full CRUD for your new todos service.

## Extending

### Extending
There are several ways to extend the basic CRUD functionality of this service.

You can also extend any of the feathers services to do something custom.
_Keep in mind that calling the original service methods will return a Promise that resolves with the value._

```js
var feathers = require('feathers');
var nedb = require('feathers-nedb');
var app = feathers();
### feathers-hooks

var myUserService = nedb('users').extend({
find: function(params, cb){
// Do something awesome!
The most flexible option is weaving in functionality through [feathers-hooks](https://github.com/feathersjs/feathers-hooks), for example, the
user that made the request could be added like this:

console.log('I am extending the find method');
```js
var feathers = require('feathers');
var hooks = require('feathers-hooks');
var service = require('feathers-nedb');
var NeDB = require('nedb');
var db = new NeDB({
filename: './data/todos.db',
autoload: true
});

this._super.apply(this, arguments);
var app = feathers()
.configure(hooks())
.use('/todos', service({
Model: db,
paginate: {
default: 2,
max: 4
}
}));

app.service('todos').before({
// You can create a single hook like this
create: function(hook, next) {
hook.data.user_id = hook.params.user.id;
next();
}
});

app.configure(feathers.rest())
.use('/users', myUserService)
.listen(8080);
app.listen(3030);
```

### With hooks
### Classes (ES6)

Another option is to weave functionality into your existing services using [feathers-hooks](https://github.com/feathersjs/feathers-hooks), for example the above `createdAt` and `updatedAt` functionality:
The module also exports a Babel transpiled ES6 class as `Service` that can be directly extended like this:

```js
var feathers = require('feathers');
var hooks = require('feathers-hooks');
var nedb = require('feathers-nedb');
import NeDB from 'nedb';
import { Service } from 'feathers-nedb';

// Initialize a MongoDB service with the users collection on a local MongoDB instance
var app = feathers()
.configure(hooks())
.use('/users', nedb('users'));
class MyService extends Service {
create(data, params) {
data.user_id = params.user.id;

app.lookup('users').before({
create: function(hook, next) {
hook.data.createdAt = new Date();
next();
},
return super.create(data, params);
}
}

update: function(hook, next) {
hook.data.updatedAt = new Date();
next();
const db = new NeDB({
filename: './data/todos.db',
autoload: true
});

app.use('/todos', new MyService({
Model: db,
paginate: {
default: 2,
max: 4
}
}));
```

### Uberproto (ES5)

You can also use `.extend` on a service instance (extension is provided by [Uberproto](https://github.com/daffl/uberproto)):

```js
var NeDB = require('nedb');
var db = new NeDB({
filename: './data/todos.db',
autoload: true
});
var myService = service({
Model: db,
paginate: {
default: 2,
max: 4
}
}).extend({
create: function(data, params) {
data.user_id = params.user.id;

app.listen(8080);
return this._super.apply(this, arguments);
}
});

app.use('/todos', myService);
```


## Options

The following options can be passed when creating a new NeDB service:

- `path` - the location of the database file. By default your database will be created inside of `./db-data`.
- `db` - The NeDB database instance
- `id` (default: `_id`) [optional] - The name of the id property
- `paginate` [optional] - A pagination object containing a `default` and `max` page size (see below)


## Pagination

When initializing the service you can set the following pagination options in the `paginate` object:

- `default` - Sets the default number of items
- `max` - Sets the maximum allowed number of items per page (even if the `$limit` query parameter is set higher)

When `paginate.default` is set, `find` will return an object (instead of the normal array) in the following form:

```
{
"total": "<total number of records>",
"limit": "<max number of items per page>",
"skip": "<number of skipped items (offset)>",
"data": [/* data */]
}
```


## Migrating

Version 2 of this adapter no longer brings its own NeDB dependency. This means that you now have to provide your own NeDB data store instance, changing something like

```js
var nedb = require('feathers-nedb');
app.use('todos', nedb('todos', options));
```

To

```js
var nedb = require('nedb');
var service = require('feathers-nedb');

var db = new NeDB({
filename: './data/todos.db',
autoload: true
});

var todoService = service({
db: db
});

app.use('todos', todoService);
```


## Query Parameters
Expand All @@ -129,9 +238,9 @@ The `find` API allows the use of `$limit`, `$skip`, `$sort`, and `$select` in th

```js
// Find all recipes that include salt, limit to 10, only include name field.
{"ingredients":"salt", "$limit":10, "$select": { "name" :1 } } // JSON
{"ingredients":"salt", "$limit":10, "$select": ["name"] } } // JSON

GET /?ingredients=salt&$limit=10&$select[name]=1 // HTTP
GET /?ingredients=salt&$limit=10&$select[]=name // HTTP
```
As a result of allowing these to be put directly into the query string, you won't want to use `$limit`, `$skip`, `$sort`, or `$select` as the name of fields in your document schema.
Expand Down Expand Up @@ -273,6 +382,11 @@ query: {

## Changelog

__2.0.0__

- Remove NeDB dependency
- Migration to ES6 and latest service test suite

__1.2.0__

- Migration to shared service test suite ([#4](https://github.com/feathersjs/feathers-nedb/pull/4))
Expand All @@ -289,12 +403,14 @@ __0.1.0__

- Initial release.


## License

Copyright (c) 2015

Licensed under the [MIT license](LICENSE).


## Author

[Marshall Thompson](https://github.com/marshallswain)
60 changes: 60 additions & 0 deletions examples/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// server.js
var NeDB = require('nedb');
var feathers = require('feathers');
var bodyParser = require('body-parser');
var service = require('../lib');
var db = new NeDB({
filename: './db-data/todos',
autoload: true
});

// NeDB ids do not seem to be generated sequentially but sorted lexigraphically
// if no other sort order is given. This means that items can not be returned in the
// same order they have been created so this counter is used for sorting instead.
var counter = 0;

var todoService = service({
Model: db,
paginate: {
default: 2,
max: 4
}
}).extend({
find(params) {
params.query = params.query || {};
if(!params.query.$sort) {
params.query.$sort = { counter: 1 };
}

return this._super(params);
},

create(data, params) {
data.counter = ++counter;
return this._super(data, params);
}
});

// Create a feathers instance.
var app = feathers()
// Setup the public folder.
.use(feathers.static(__dirname + '/public'))
// Enable Socket.io
.configure(feathers.socketio())
// Enable REST services
.configure(feathers.rest())
// Turn on JSON parser for REST services
.use(bodyParser.json())
// Turn on URL-encoded parser for REST services
.use(bodyParser.urlencoded({extended: true}))
.use('/todos', todoService);

// A basic error handler, just like Express
app.use(function(error, req, res, next){
res.json(error);
});

// Start the server
module.exports = app.listen(3030);

console.log('Feathers Todo NeDB service running on 127.0.0.1:3030');
Loading

0 comments on commit 677501f

Please sign in to comment.