Charon
Charon is a little API client factory, created to abstract away some of the nitty gritty aspects of interacting with a ReST API over HTTP. At its core, Charon is a means of organizing an API domain into a single client-namespace with a hierarchical set of services and a consistent interface.
But wait, there's more!
- Charon makes it easy to define common behaviors, such as including authorization headers in requests or unpacking response envelopes, and it allows you to apply those behaviors to all, or just some, endpoints in your REST API.
- Charon translates HTTP error codes into error instances in a consistent way, so your app code doesn't have to.
- Charon uses configurable middleware to parse responses, so you can easily add additional functionality without having to rewrite the whole thing.
- Now with 100% test coverage (as measured by jscoverage).
Don't call it a framework
Charon is a simple library focused on abstracting RESTful service calls.
Service methods have a familiar (data, [options,] callback)
signature, and
callbacks are called with (err, data)
- that's the only interface your
application code should have to deal with.
Charon is designed to produce stateless clients, and data is passed around as plain old JSON-serializable objects with no getter/setter functions or any other monkey business. Because Charon isn't a framework and isn't tied to any framework, you should be able to integrate it into pretty much any app (or your favorite framework) without too many complications.
Assumptions
- all service communication happens over HTTP, or something like it
- all service communications are asynchronous
- all data is JSON-serializable
- all JSON response bodies are objects (or possibly arrays)
- works with node.js only
Todo: Make it better
- documentation
- transparent caching according to response headers
- isomorphic browser / mobile / server execution
- HATEOAS / link integration
Example client definition and usage
// Create a client for our business's REST API.var CandyShop = Charon; // Now let's create a ResourceManager to contain several services which// act on the same resource type.CandyShopLollipop = CandyShop; // We'll declare some basic CRUD services for our ResourceManager// (note, all share the ResourceManager's default URL method)CandyShopLollipop; // Clients can be initialized with dynamic configuration data. This should// only be done once, when your app is starting up (aka "bootstrap" phase).CandyShop; // Service calls accept a ``data`` object param and an ``options`` object// param. ``data`` should generally be limited to stuff that you consider part// of the resource definition, while options should generally be optional.// Following these rough rules of thumb are not required, but will make your// client more consistent.CandyShopLollipop;