Skip to content
A minimalist real-time JavaScript framework for tomorrow's apps.
JavaScript
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
lib
test
.gitignore
.jshintrc
.travis.yml
Gruntfile.js
license.md
package.json
readme.md

readme.md

Feathers

Let your web app fly.

Build Status

Feathers is a light weight web application framework that rides on top of Express. It makes it easy to create RESTful web services and real-time applications using socket.io.

The core focus of Feathers is your data. We believe that ultimately your app's purpose is to manage data in some fashion and so that's all you should really need to deal with. Managing your data.

Install

As with any NodeJS module, just install it as a dependency in your application:

npm install feathers --save

Getting Started Is Easy

Like we said, services are just simple modules that expose certain methods to the providers. This makes it easy to initialize a service that say... provides a single TODO:

var feathers = require('feathers');

var todoService = {
  get: function(name, params, callback) {
    callback(null, {
      id: name,
      description: "You have to do " + name + "!"
    });
  }
};

feathers()
    .configure(feathers.socketio())
    .use('todo', todoService)
    .listen(8000);

That's all there really is to building an app with Feathers.

REST

You can access the REST service by going to http://localhost:8000/todo/dishes in your browser and will see:

{
  "id": "dishes",
  "description": "You have to do dishes!"
}

Note: Query parameters like http://localhost:8000/todo/dishes?type=dirty will be passed as params.query

SocketIO

Since we configured our app with feathers.socketio(), you can also connect to your service via SocketIO. Create an HTML page and insert the following code to see the response data logged on the console:

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:8000/');
  socket.emit('todo::get', 'laundry', {}, function(error, data) {
    console.log(data); // -> { id: 'laundry', description: 'You have to do laundry!' }
  });
</script>

Services

A service can be any JavaScript object that offers one or more of the find, get, create, update, destroy and setup service methods:

var myService = {
  find: function(params, callback) {},
  get: function(id, params, callback) {},
  create: function(data, params, callback) {},
  update: function(id, data, params, callback) {},
  destroy: function(id, params, callback) {},
  setup: function(app) {}
}

All callbacks follow the function(error, data) NodeJS convention. params can contain any additional parameters, for example the currently authenticated user. REST service calls set params.query with the query parameters (e.g. a query string like ?status=active&type=user becomes { status: "active", type: "user" }).

find(params, callback)

Retrieves a list of all resources from the service. Ideally use params.query for things like filtering and paging so that REST calls like todo?status=completed&user=10 work right out of the box.

REST

GET todo?status=completed&user=10

SocketIO

socket.emit('todo::find', {
  status: 'completed'
  user: 10
}, function(error, data) {
});

get(id, params, callback)

Retrieves a single resource with the given id from the service.

REST

GET todo/1

SocketIO

socket.emit('todo::get', 1, {}, function(error, data) {

});

create(data, params, callback)

Creates a new resource with data. The callback should be called with that resource (and the id initialized).

REST

POST todo { "description": "I really have to iron" }

By default the body can be eihter JSON or form encoded as long as the content type is set accordingly.

SocketIO

socket.emit('todo::create', {
  description: 'I really have to iron'
}, function(error, data) {
});

update(id, data, params, callback)

Updates the resource identified by id using data.

REST

PUT todo/2 { "description": "I really have to do laundry" }

SocketIO

socket.emit('todo::update', 2, {
  description: 'I really have to do laundry'
}, {}, function(error, data) {
  // data -> { id: 2, description: "I really have to do laundry" }
});

remove(id, params, callback)

Remove the resource with id.

REST

DELETE todo/2

SocketIO

socket.emit('todo::delete', 2, {}, function(error, data) {
});

setup(app)

Initializes the service passing an instance of the Feathers application. app can do everything a normal Express application does and additionally provides app.lookup(path) to retrieve another service by its path. setup is a great way to connect services:

var todoService = {
  get: function(name, params, callback) {
    callback(null, {
      id: name,
      description: 'You have to ' + name + '!'
    });
  }
};

var myService = {
  setup: function(app) {
    this.todo = app.lookup('todo');
  },

  get: function(name, params, callback) {
    this.todo.get('take out trash', {}, function(error, todo) {
      callback(null, {
        name: name,
        todo: todo
      });
    });
  }
}

feathers()
    .use('todo', todoService)
    .use('my', myService)
    .listen(8000);

You can see the combination when going to http://localhost:8000/my/test.

Getting Real, Time

The secret ingredient to create real time applications using Feathers and SocketIO is the created, updated and removed events every Feathers service automatically emits. Here is another simple Todo service, that just passes the data through create:

var feathers = require('feathers');

var todoService = {
  create: function(data, params, callback) {
    callback(null, data);
  }
};

var app = feathers()
    .configure(feathers.socketio())
    .use('todo', todoService)
    .listen(8000);

Lets make an HTML file that creates a new Todo using SocketIO every two seconds:

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:8000/');
  var counter = 0;

  // Create a new Todo every two seconds
  setInterval(function() {
    counter++;

    socket.emit('todo::create', {
      description: 'I have ' + counter + ' things to do!'
    }, {}, function(error, data) {
      console.log('Created: ', data);
    });
  }, 2000);
</script>

In another file we just listen to the todo created event and log it:

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:8000/');

  socket.on('todo created', function(todo) {
    console.log(todo.description);
  });
</script>

When visiting both HTMl files in a browser at the same time you should see a new Todo being logged every two seconds on both pages.

Why Another NodeJS Framework?

We know... Oh God another bloody NodeJS framework! Yes we are also very tired of seeing all these NodeJS frameworks. All the rails clones are getting a bit boring and really aren't taking advantage of the real strengths of NodeJS. We wanted to take a different approach than every other framework we have seen, because we believe that data is core to the web and should be the core focus of web applications.

We also think that your data resources can and should be encapsulated in such a way that they can be ultra scalable and self contained. The MVC pattern works well but it is becoming antiquated in today's web. Frankly you don't need it and they tend to become bloated.

With that being said there are some amazing frameworks already out there and we wanted to leverage the ideas that have been put into them, which is why Feathers is built on top of Express and is inspired in part by Sails, Flatiron and Derby.

Something went wrong with that request. Please try again.