Package Exports
- json-api
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (json-api) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
json-api 
This library creates a JSON API-compliant REST API from your Node app. And it generates API documentation automatically.
It currently integrates with Express apps that use Mongoose models, but it can easily be integrated with other frameworks and databases. If you want to see an integration with another stack, just open an issue!
Heads up: The JSON-API spec isn't quite at version 1.0 yet, nor does this library yet implement the whole spec. In particular, some advanced routes do not work and the library's API is subject to change. That said, all the basic CRUD operations are supported and development is progressing very quickly. The goal is to have the entire spec implemented by the time the final JSON API spec is officially released.
Installation
$ npm install json-api
On Versioning: After the JSON API spec is finalized, this library's major version will be bumped to 3.0.0 and it will use semantic versioning going forward. Until then, the 2.x versions should be considered like this library's second "major version zero"—which is needed only because the 1.0 version of this library was stable and used in production for a while.
Example API
Check out the full, working example repo for all the details on building an API with this library. Or, take a look at the basic example below:
var app = require('express')()
, API = require('json-api');
var models = {
"Person": require('./models/person'),
"Place": require('./models/place')
};
var registry = new API.ResourceTypeRegistry();
var adapter = new API.adapters.Mongoose(models);
registry.type("people", {
adapter: adapter,
urlTemplates: {
"self": "/people/{id}"
}
});
registry.type("places", {
adapter: adapter,
urlTemplates: {"self": "/places/{id}"}
});
// Initialize the automatic documentation.
// Note: don't do this til after you've registered all your resources.
var templatePath = path.resolve(__dirname, './public/views/style-docs.jade')
var DocsController = new API.controllers.Documentation(registry, {name: 'Example API'}, templatePath);
// Set up our controllers
var APIController = new API.controllers.API(registry);
var Front = new API.controllers.Front(APIController, DocsController);
var requestHandler = Front.apiRequest.bind(Front);
// Add routes for basic list, read, create, update, delete operations
app.get("/:type(people|places)", requestHandler);
app.get("/:type(people|places)/:id", requestHandler);
app.post("/:type(people|places)", requestHandler);
app.patch("/:type(people|places)/:id", requestHandler);
app.delete("/:type(people|places)/:id", requestHandler);
// Add routes for adding to, removing from, or updating resource relationships
app.post("/:type(people|places)/:id/links/:relationship", requestHandler);
app.patch("/:type(people|places)/:id/links/:relationship", requestHandler);
app.delete("/:type(people|places)/:id/links/:relationship", requestHandler);
app.listen(3000);Core Concepts
Resource Type Descriptions
The JSON-API spec is built around the idea of typed resource collections. For example, you can have a "people" collection and a "companies" collection. (By convention, type names are plural and lowercase.)
To use this library, you describe the special behavior (if any) that resources of each type should have, and then register that description with a central ResourceTypeRegistry. Then the library takes care of the rest. A resource type description is simply an object with the following properties:
urlTemplates: an object containing url templates used to output the json for resources of the type being described. Currently, the supported keys are: "self", which defines the template used for building resource urls of that type, and "relationhsip", which defines the template that will be used for relationship urls.adapter: the adapter used to find and update these resources. By specifying this for each resource type, different resource types can live in different kinds of databases.beforeRender(optional): a function called on each resource after it's found by the adapter but before it's sent to the client. This lets you do things like hide fields that some users aren't authorized to see.beforeSave(optional): a function called on each resource provided by the client (i.e. in aPOSTorPUTrequest) before it's sent to the adapter for saving. You can transform the data here to make it valid.labelMappers(optional): this lets you create urls (or, in REST terminology, resources) that map to different database items over time. For example, you could have a/events/upcomingresource or a/users/meresource. In those examples, "upcoming" and "me" are called the labels and, in labelMappers, you provide a function that maps each label to the proper database id(s) at any given time. The function can return a Promise if needed.parentType(optional): this allows you to designate one resource type being a sub-type of another (itsparentType). This is often used when you have two resource types that live in the same database table/collection, and their type is determined with a discriminator key. See theschoolstype in the example repository.
Routing, Authentication & Controllers
This library gives you a Front controller (shown in the example) that can handle requests for API results or for the documentation. But the library doesn't prescribe how requests get to this controller. This allows you to use any url scheme, routing layer, or authentication system you already have in place. You just need to make sure that: req.params.type reflects the requested resource type; req.params.id or (if you want to allow labels on a request) req.params.idOrLabel reflects the requested id, if any; and req.params.relationship reflects the relationship name, in the event that the user is requesting a relationship url.
In the example above, routing is handled with Express's built-in app[VERB] methods, and the three parameters are set properly using express's built-in :param syntax. If you're looking for something more robust, you might be interested in Express Simple Router. For authentication, check out Express Simple Firewall.
Adapters
An adapter handles all the interaction with the database. It is responsible for turning requests into standard Resource or Collection objects that the rest of the library will use. See the built-in MongooseAdapter for an example.