Easily construct HATEOAS HAL (templated) links with zero deps
npm install --save @hateoas/linker
import { link, origin, param, paramValue, segment } from '@hateoas/linker'
// consider request on /users
getUser(request, response) {
// ...
const selfLink = link(req, param('active')) // http://example.com/users{?active}
// ...
}
// consider request on /users/31
getUser(request, response) {
// ...
const selfLink = link(req) // http://example.com/users/31
const activateLink = link(selfLink, 'activate') // http://example.com/users/31/activate
// ...
}
The linker API is made to reuse outputs of link
calls, so you can build link
on top of link. The link itself is a class and it can be turned into string by
calling .toString()
, .toJSON
or just using default JavaScript JSON/string
conversion.
Creates link various properties passed as arguments
link('foo')
// "/foo"
By passing origin
, the linker will construct absolute URL.
link(origin('https://example.com'), 'foo')
// "https://example.com/foo"
Passing HTTPRequest
or IncomingMessage
instance into the API will
automatically set the link origin
link(req, 'foo')
// "http://example.com/foo"
By passing param
, the linker will construct templated URL with optional query
string parameters.
link('users', param('active'))
// { href: "/users{?active}", templated: true }
Multiple params can be passed
link('users', param('active', 'funny'))
// { href: "/users{?active,funny}", templated: true }
By passing paramValue
, the linker will construct URL with query
string parameter values.
link('users', paramValue({ active: true })
// "/users?active=true"
You can combine this with other param
s, making templated URL.
link('users', paramValue({ active: true }), param('funny'))
// { href: "/users?active=true{&funny}", templated: true }
By passing segment
, the linker will construct templated URL with variable
path segments, allowing to link to specific path by template.
link('users', segment('userId'))
// { href: "/users/{userId}", templated: true }
const base = link(req, 'users')
// "http://example.com/users"
const selfLink = link(base, param('active', 'funny'))
// "http://example.com/users{?active,funny}"
const entityLink = link(base, segment('userId'))
// "http://example.com/users/{userId}"
const activateLink = link(entityLink, 'activate')
// "http://example.com/users/{userId}/activate"
Use linkObject
method, to conveniently inject links into objects.
import { link, linkObject } from '@hateoas/linker'
const user = {
name: 'foo',
email: '[email protected]',
}
// Assume `request` is HTTPRequest instance
const self = link(request, 'users', user.name)
const activate = link(self, 'activate')
linkObject(user, { self, activate })
/*
{
name: 'foo',
email: '[email protected]',
_links: {
self: 'http://example.com/users/foo',
activate: 'http://example.com/users/foo/activate',
},
*/
})
Use linkCollection
method to conventiently inject links into collections.
import { link, linkCollection } from '@hateoas/linker'
// Assume `request` is HTTPRequest instance
// Assume, there are two already linked users
const self = link(request, 'users', param('active', 'funny'))
linkCollection(users, { self })
/*
{
name: 'foo',
email: '[email protected]',
_links: {
self: {
href: 'http://example.com/users{?active,funny}',
templated: true,
},
},
*/
})