foxx_generator

0.5.1 • Public • Published

FoxxGenerator

FoxxGenerator is a declarative JavaScript framework that allows developers to describe the API in terms of the domain using statecharts. This declarative approach is based upon a combination of Richardson and Amundsen's design approach described in their book RESTful Web APIs, Eric Evans' ideas from his book domain driven design and the Harel's statecharts introduced in his paper Statecharts: A Visual Formalism For Complex Systems.

To create an API with FoxxGenerator, first draw a statechart that represents your API. In this statechart, your states can have one of the following types:

  • Entity: This state represents something that has an identity and an arbitrary number of (optionally nested) attributes.
  • Repository: A repository can store entities.
  • Service: A service can do something. What it can do is defined via a JavaScript function that you can define. A service does not have a state.

Connect these states with transitions. When you have modeled your statechart in a way that it can fulfill all your use cases, it is time to classify your transitions. For every transition you have to decide which of the following type it follows:

  • follow: This is a transition that you can just follow from one state to the next.
  • connect: This is a point of extension where you can create a transition at runtime. In order to be able to follow this transition, you have to add a follow transition as well.
  • disconnect: With this transition you can remove a transition created with connect.
  • modify: This is a transition that can only be created from an entity to itself. It is used to modify the state of this entity.

You can now translate this annotated statechart into the DSL of FoxxGenerator to create your API.

Setting up a Foxx application with FoxxGenerator.

First, create a Foxx application as described in Foxx's manual. In the folder of your Foxx app, you can now install FoxxGenerator with npm install foxx_generator. In the same way you would add a controller to your Foxx application, you can now add a FoxxGenerator to your application: In the file that would normally contain your FoxxController, add the following:

var FoxxGenerator = require('foxx_generator').Generator,
  Joi = require('joi'),
  generator;
 
generator = new FoxxGenerator('name_of_your_app', {
  // To learn more about media types, see below
  mediaType: 'application/vnd.siren+json',
  applicationContext: applicationContext,
});
 
// Insert transition definitions here
 
// Insert states here
 
generator.generate();

For more information on how to choose a media type, see the section about Media types. Now you can define the transitions you used in your statechart and then add the states and the transitions between them.

Defining the transitions

Every transition needs the following attributes:

  • A name for the transition that you can use when you want to add a transition of this type.
  • type: One of the types described above.
  • to: Is the target of this transition one or more states? For a connect transition this for example determines if you can only connect one state to it or more than that. Acceptable values are one and many.

You can also add a documentation block (a JavaScript comment starting with /**) that will be used for the documentation. The first line should be a short summary, all other lines will be used for a long description. An example for that would be the following transition definition:

/** Show details for a particular item
 * 
 * Show all information about this particular item.
 */
generator.defineTransition('showDetail', {
  type: 'follow',
  to: 'one'
});

For a connect and disconnect transition you additionally have to determine which follow transition can be used to follow the created transition. This is done with as and the name of the transition.

You can also add parameters to the transition, if in the transition process you need additional information from the user of the API. Each of the parameters needs to be a value object defined with Joi. For example:

/** Modify the title of the entity
 *
 */
generator.defineTransition('changeTitle', {
  type: 'modify',
  to: 'one',
 
  parameters: {
    title: Joi.string()
  }
});

You can also define a condition for a transition. This is a JavaScript function that takes the parameters of the HTTP request as its argument and returns either true or false. If it is true, the transition can be executed. If it is false, the transition can not be executed and the link to execute it will be hidden from the representation. This can for example be used for user authorization.

Adding states and transitions

Now you can add states and transitions to your API. Every state has a name, a type and a number of outgoing transitions. The type is one of the above described ones – either entity, repository or service. Every transition needs information about where it leads to and via which transition type. The transition type needs to be defined as described above. Simple example:

generator.addState('ideas', {
  type: 'repository',
  contains: 'idea',
 
  transitions: [
    { to: 'idea', via: 'showDetail' }
  ]
});

Some states take additional information: Entities need to know which repository they are contained in (via containedIn) and repositories need to know which entities they contain (via contains).

States can also have a superstate. This can be done by providing superstate with the name of the state that should be the superstate as a string. The superstate is provided to the service via a third parameter in its action. It is an object that has a key called superstate where the value depends on the superstate's type:

  • If the superstate is an entity, it has a key entity where the value is the entity and a key repository which is the Foxx.Repository in which the entity is saved.
  • If the superstate is a repository, it has a key repository which contains the Foxx.Repository.

Entity

An entity can be parameterized (by setting its attribute parameterized to true) which means that there is not only one state of that type, but there can be an arbitrary amount – each of them is identified by a parameter. This is usually the case with entities that are stored in a repository.

It also takes an object of attributes which describe the representation of the entity. Each of the attributes needs to be a value object defined with Joi.

Example for an entity:

generator.addState('idea', {
  type: 'entity',
  parameterized: true,
  containedIn: 'ideas',
 
  attributes: {
    description: Joi.string().required(),
    title: Joi.string().required()
  },
 
  transitions: [
    { to: 'idea', via: 'relatedIdea' }
  ]
});

Service

A service needs to describe what it does, this is done with an action which is a function that takes a request and a response in the same way that a FoxxController route does. The default HTTP verb for a service is a post, it can be changed by setting the verb. Example:

generator.addState('title', {
  type: 'service',
  verb: 'get',
 
  action: function (req, res) {
    var entity = req.params('entity');
    res.json({ title: entity.get('title') });
  }
});

Media types

FoxxGenerator currently only supports siren which is a media type without application semantics. Use the media type application/vnd.siren+json. We plan to support HAL with an extension for forms in the near future.

Interactive Documentation

During your development, FoxxGenerator will generate an interactive documentation alongside the API. You can use this in an iterative development style to check after each step if the API is as you expected it to be. The documentation allows you to try out each of the generated endpoints. The API documentation can be found in the admin interface of ArangoDB and looks a little like this:

Overview

If you click on one of the routes, you can try it out:

Try it out

Examples

  • An example for a Siren API generated with FoxxGenerator can be found here

Linting

To check the project for linting errors, run npm run jshint.

/foxx_generator/

    Package Sidebar

    Install

    npm i foxx_generator

    Weekly Downloads

    2

    Version

    0.5.1

    License

    Apache License Version 2.0

    Last publish

    Collaborators

    • moonglum