4.0.1 • Published 4 years ago

restocat v4.0.1

Weekly downloads
25
License
MIT
Repository
github
Last release
4 years ago

Restocat

Gitter Travis CI codecov Codeclimate

TL;DR

Install Restocat CLI using following command:

npm install -g restocat-cli

Use Restocat CLI to create an empty project like this:

restocat init

Collections

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'
})

Context

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.$context.name - name of current collection

  • this.$context.properties - properties from collection.json for current collection
  • this.$context.handleName - handler name for current endpoint
  • this.$context.state - the keys found in the path

Events

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();

restocat.events.on('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:

EventWhen happensArguments
traceTrace message was sentString
debugDebug message was sentString
infoInformation message was sentString
warnWarning message was sentString
errorError message was sentString \ Error
fatalFatal error message was sentString \ Error
collectionLoadedeach collection is loaded{name: String, properties: Object, constructor: function}
allCollectionsLoadedall collections are loadedLoaded collections by their names
incomingMessageRequest messageIncomingMessage
responseServerResponse serverResponseServer, 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));

Formatters

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

4.0.1

4 years ago

4.0.0

4 years ago

3.0.1

6 years ago

3.0.0

6 years ago

2.2.2

7 years ago

2.2.1

7 years ago

2.2.0

7 years ago

2.1.0

7 years ago

2.0.2

8 years ago

2.0.1

8 years ago

2.0.0

8 years ago

1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago

1.0.0-RC3

8 years ago

1.0.0-RC2

8 years ago

1.0.0-RC

8 years ago

1.0.0-alpha.7

8 years ago

1.0.0-alpha.6

8 years ago

1.0.0-alpha.5

8 years ago

1.0.0-alpha.4

8 years ago

1.0.0-alpha.3

8 years ago

1.0.0-alpha.2

8 years ago

1.0.0-alpha.1

8 years ago