Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

siren-writer

dominicbarnes749MIT0.5.0

A Siren Hypermedia Object Generator

siren, hypermedia, generator

readme

node-siren-writer

A generator for siren hypermedia API responses.

npm version npm dependencies npm dev dependencies build status

Example

var writer = require('siren-writer');
var siren = writer('http://api.x.io');

var entity = siren({
  class: 'order',
  properties: {
    orderNumber: 42,
    itemCount: 3,
    status: 'pending'
  },
  entities: [
    {
      class: [ 'items', 'collection' ],
      rel: 'http://x.io/rels/order-items',
      href: 'orders/42/items'
    },
    {
      class: [ 'info', 'customer' ],
      rel: 'http://x.io/rels/customer',
      properties: {
        customerId: 'pj123',
        name: 'Peter Joseph'
      },
      links: {
        rel: 'self',
        href: 'customers/pj123'
      }
    }
  ],
  actions: {
    name: 'add-item',
    title: 'Add Item',
    method: 'POST',
    href: 'orders/42/items',
    type: 'application/x-www-form-urlencoded',
    fields: [
      { name: 'orderNumber', type: 'hidden', value: '42' },
      { name: 'productCode', type: 'text' },
      { name: 'quantity', type: 'number' }
    ]
  },
  links: [
    {
      rel: 'self',
      href: 'orders/42'
    },
    {
      rel: 'previous',
      href: 'orders/41'
    },
    {
      rel: 'next',
      href: 'orders/43'
    }
  ]
});

console.log(entity);

will produce the example from the Siren homepage:

{
  "class": [ "order" ],
  "properties": {
      "orderNumber": 42,
      "itemCount": 3,
      "status": "pending"
  },
  "entities": [
    {
      "class": [ "items", "collection" ],
      "rel": [ "http://x.io/rels/order-items" ],
      "href": "http://api.x.io/orders/42/items"
    },
    {
      "class": [ "info", "customer" ],
      "rel": [ "http://x.io/rels/customer" ],
      "properties": {
        "customerId": "pj123",
        "name": "Peter Joseph"
      },
      "links": [
        { "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" }
      ]
    }
  ],
  "actions": [
    {
      "name": "add-item",
      "title": "Add Item",
      "method": "POST",
      "href": "http://api.x.io/orders/42/items",
      "type": "application/x-www-form-urlencoded",
      "fields": [
        { "name": "orderNumber", "type": "hidden", "value": "42" },
        { "name": "productCode", "type": "text" },
        { "name": "quantity", "type": "number" }
      ]
    }
  ],
  "links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]
}

API

writer(base)

Creates a new siren writer with the given base as the base URL for things like rel and href throughout an entity.

siren(options)

The returned function is the entire API. It returns an object that can be serialized as a JSON response.

// express
res.json(siren(/* options */));

// koa
this.body = siren(/* options */);

Generally-speaking, this API avoids performing magic. It wants you to be explicit, only accepting objects instead of positional arguments. However, there are a few ways that this API improves upon generating the response entirely from scratch:

  • ensures that single values are converted into arrays where they're required (eg: class, rel, etc)
  • flattens nested arrays into a single array, particularly for things like entities where you could be merging several different types for a single response
  • automatically resolves URLs relative to the base URL (eg: href and any rel values that aren't defined by IANA)
  • throws errors when you are missing things that are explicitly required, such as the href or rel for a link

The keys in options include everything in the spec, so use that as a reference when building your configuration options. Additional properties will be included, but their behavior with clients cannot be guaranteed. Some other things to be aware of:

  • as mentioned before, don't be too concerned with arrays if you're only setting a single value
  • don't be afraid to nest arrays, they will be flattened
  • include the trailing / in your base, especially when using a pathname
  • avoid using a leading / in your relative URLs, as it will behave unexpectedly if your base has a pathname as part of it. (ie: http://example.com/api/)
  • this library will throw exceptions in the cases mentioned previously

changelog

0.5.0 / 2016-07-23

  • filter out falsy values from arrays

0.4.1 / 2016-01-10

  • updating readme

0.4.0 / 2016-01-10

  • removing strictness from action.method and field.type, as the spec is more permissible

0.3.0 / 2015-12-28

  • supporting arrays of properties objects

0.2.1 / 2015-11-16

  • meta updates

0.2.0 / 2015-10-23

  • fix #4: allowing extra properties to be passed through

0.1.2 / 2015-10-23

  • fix #3: allowing rels with hyphens in the name

0.1.1 / 2015-08-17

  • docs: updating readme

0.1.0 / 2015-08-16

  • huge internal rewrite

0.0.1 / 2013-08-21

:sparkles: