Naysayers Promote Misery
    Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »



    Gitter Travis CI codecov Codeclimate


    Install Restocat CLI using following command:

    npm install -g restocat-cli

    Use Restocat CLI to create an empty project like this:

    restocat init


    Each collection is declared as a directory with the collection.json file by default. When Restocat initializes the application it recursively searches for such directories starting with your project root, and then via first-level dependencies in the ./node_modules directory.

    The collection.json file consists of following:

    • name – the name of the collection (optional). By default, this is the name of the directory. Please keep in mind that a parameter's name in a route definition must satisfy the regular expression /^[\w-]+$/i
    • logic – a relative path to the file that exports a class or a constructor function for the collection's logic object (optional). By default, index.js will be used.
    • endpointDefault – a relative path to the file that exports a class or a constructor function for the collection's logic object (optional). By default - true
    • endpoints – map of the relationship between the route and handler (optional). By default:
        "get /": "list",
        "post /": "create",
        "get /:id": "one",
        "put /:id": "update",
        "delete /:id": "delete"

    An example collection.json could look like this:

        "name": "Entities",
        "description": "Some awesome and cool collection",
        "logic": "./Entities.js",
        "endpoints": {
          "delete /:id": false, // don't use this endpoint
          "put /:id": false,
          "post /": false,
          "get /sub-entities/": "subEntities", // custome endpoint
          "get /sub-entities/:id": "subEntity"

    Also, you can set your list of the endpoints by default:

    locator.registerInstance('defaultEndpoints', {
        'get /': 'list',
        'post /': 'create',
        'get /:id': 'one'


    Restocat sets as the property $context for every instance of each collection.

    $context has at least the following properties and methods:

    • this.$context.request - the current request (IncomingMessage)

    • this.$context.response - the current response (ResponseServer)

    • this.$context.location – the current URI object that constains the current location.

    • this.$context.referrer – the current URI object that contains the current referrer.

    • this.$context.locator – the Service Locator of the application.

    • this.$context.forward(collection_name:String, handle_name:String) – forwarding the current request to a other collection. This method is useful for creating a sub-collection flow

    • this.$context.notFound() - correct 404 response from the server

    • this.$context.redirect(uri:String, statusCode:Number) - correct http redirect

    • this.$context.notSend() - a message to restocat what to call the send method is not necessary, we'll do it. Attention! It can not be caused by formatters and errorHandler

    • this.$ - name of current collection

    • this.$ - properties from collection.json for current collection

    • this.$context.handleName - handler name for current endpoint

    • this.$context.state - the keys found in the path


    There are two ways of listening to a Restocat event:

    • Subscribe on it using the Restocat application instance directly like this:
    const Restocat = require('restocat');
    const restocat = new Restocat();
'error', error => {
        // some action
    • Subscribe on it using the this.$context object of a collection using the same on or once methods.
    this.$context.on('error', error => {
        // some action

    Event names and arguments

    Here is a list of Restocat events:

    Event When happens Arguments
    trace Trace message was sent String
    debug Debug message was sent String
    info Information message was sent String
    warn Warning message was sent String
    error Error message was sent String \ Error
    fatal Fatal error message was sent String \ Error
    collectionLoaded each collection is loaded {name: String, properties: Object, constructor: function}
    allCollectionsLoaded all collections are loaded Loaded collections by their names
    incomingMessage Request message IncomingMessage
    responseServer Response server ResponseServer, IncomingMessage

    Content Negotiation

    If you're not using $context.notSend() Restocat will automatically select the content-type to respond with, by finding the first registered formatter defined. Also, note that if a content-type can't be negotiated, the default is application/octet-stream. Of course, you can always explicitly set the content-type:

    $context.response.setHeader('content-type', 'application/vnd.application+json');
    $context.response.send({hello: 'world'});

    Note that there are typically at least three content-types supported by Restocat (json, text and binary). When you override or append to this, the "priority" might change; to ensure that the priority is set to what you want, you should set a q-value on your formatter definitions, which will ensure sorting happens the way you want

    So, if you are using the $context.notSend() and send the data manually, you should independently obtain and to use a formatter:

    const formatterProvider = this._serviceLocator.resolve('formatterProvider');
    const formatter = formatterProvider.getFormatter(this.$context);
    Promise.resolve(() => formatter(this.$context, myContent))
        .then(content => this.$context.resposne.send(content));


    You can add additional formatters to Restocat:

    const Restocat = require('restocat');
    const cat = new Restocat();
    const server = cat.createServer();
    server.register('formatter', {
      // context - current context with request and response; data - data for response
      'text/plain; q=0.3': (context, data) => {
        const string = String(data);
        context.response.setHeader('Content-Length', Buffer.byteLength(string));
        context.response.setHeader('X-FORMATTER', 'CUSTOM');
        return string;

    Not implemented handler (Not found)

    You can add your handler of the situation when the specified url was never found handler:

    const Restocat = require('restocat');
    const cat = new Restocat();
    const server = cat.createServer();
    server.register('notImplementedHandler', $context => {
      const NotFound = $context.locator.resolve('httpErrors').NotFoundError;
      return Promise.reject(new NotFound('Not found handler for current url'));

    Request API (IncomingMessage)

    Wraps all of the node http.IncomingMessage APIs, events and properties, plus the following.

    • accepts(type:String|Array) - checks if the accept header is present and has the value requested
    • acceptsEncoding(type:String|Array) - checks if the request accepts the encoding types
    • getContentLength() - gets the content-length header off the request
    • getContentType() - gets the content-type header
    • getDate() - gets the _date property off the request when created the request
    • getLocation() - the current URI object that constains the current location.
    • getRemoteAddr() - Remote address (the search sequence: x-forwarded-for -> ip -> remoteAddress -> socket.remoteAddress -> socket.socket.removeAddress)
    • getTime() - returns ms since epoch when request was setup
    • getTrailer(trailer:String) - returns any trailer header off the request. also, 'correct' any correctly spelled 'referrer' header to the actual spelling used.
    • getHeader(header:String) - returns any trailer header off the request. also, 'correct' any correctly spelled 'referrer' header to the actual spelling used.
    • getUserAgent() - the user-agent header
    • isChunked() - Check if the incoming request is chunked
    • isContentType(type:String) - Check if the incoming request contains the Content-Type header field, and if it contains the given mime type
    • isKeepAlive() - Check if the incoming request is kept aliv
    • isSecure() - Check if the incoming request is encrypted
    • isUpgradeRequest() - Check if the incoming request has been upgraded
    • isUpload() - Check if the incoming request is an upload verb

    Response API (ServerResponse)

    Wraps all of the node http.ServerResponse APIs, events and properties, plus the following.

    • cache(type:String, options:Object) - sets the cache-control header. type defaults to public, and options currently only takes maxAge.
    • noCache() - turns off all cache related headers.
    • getTime() - returns ms since epoch when request was setup
    • charSet(type:String) - Appends the provided character set to the response's Content-Type
    • getCharSet() - get char set
    • getHeaders() - retrieves all headers off the response
    • setHeader(name:String, value:String) - sets headers on the response
    • json(code:Number, content:Object, headers:Object) - short hand method for: res.contentType = 'json'; res.send({hello: 'world'});
    • setLinkHeader(linkKey:String, rel:String) - sets the link header
    • send(code:Number, content:Object|Error|Buffer) - sends the response object. convenience method that handles: writeHead(), write(), end()
    • setStatus(code:Number) - sets the http status code on the response

    Plugins and useful links


    npm i restocat

    Downloadsweekly downloads







    last publish


    • avatar