ketting
Version:
Opiniated HATEAOS / Rest client.
169 lines • 5.61 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseState = exports.BaseHeadState = void 0;
const link_1 = require("../link");
const action_1 = require("../action");
const uri_1 = require("../util/uri");
const uri_template_1 = require("../util/uri-template");
const util_1 = require("../http/util");
/**
* Implements a State object for HEAD responses
*/
class BaseHeadState {
constructor(init) {
this.client = init.client;
this.uri = init.uri;
this.headers = init.headers;
this.timestamp = Date.now();
this.links = init.links;
}
/**
* Follows a relationship, based on its reltype. For example, this might be
* 'alternate', 'item', 'edit' or a custom url-based one.
*
* This function can also follow templated uris. You can specify uri
* variables in the optional variables argument.
*/
follow(rel, variables) {
const link = this.links.get(rel);
if (!link)
throw new link_1.LinkNotFound(`Link with rel ${rel} on ${this.uri} not found`);
let href;
if (link.templated) {
href = (0, uri_template_1.expand)(link, variables || {});
}
else {
href = (0, uri_1.resolve)(link);
}
if (link.hints?.status === 'deprecated') {
/* eslint-disable-next-line no-console */
console.warn(`[ketting] The ${link.rel} link on ${this.uri} is marked deprecated.`, link);
}
return this.client.go(href);
}
/**
* Follows a relationship based on its reltype. This function returns a
* Promise that resolves to an array of Resource objects.
*
* If no resources were found, the array will be empty.
*/
followAll(rel) {
return this.links.getMany(rel).map(link => {
if (link.hints?.status === 'deprecated') {
/* eslint-disable-next-line no-console */
console.warn(`[ketting] The ${link.rel} link on ${this.uri} is marked deprecated.`, link);
}
const href = (0, uri_1.resolve)(link);
return this.client.go(href);
});
}
/**
* Content-headers are a subset of HTTP headers that related directly
* to the content. The obvious ones are Content-Type.
*
* This set of headers will be sent by the server along with a GET
* response, but will also be sent back to the server in a PUT
* request.
*/
contentHeaders() {
const result = {};
for (const contentHeader of util_1.entityHeaderNames) {
if (this.headers.has(contentHeader)) {
result[contentHeader] = this.headers.get(contentHeader);
}
}
return new Headers(result);
}
}
exports.BaseHeadState = BaseHeadState;
/**
* The Base State provides a convenient way to implement a new State type.
*/
class BaseState extends BaseHeadState {
constructor(init) {
super(init);
this.data = init.data;
this.actionInfo = init.actions || [];
this.embedded = init.embedded || [];
}
/**
* Return an action by name.
*
* If no name is given, the first action is returned. This is useful for
* formats that only supply 1 action, and no name.
*/
action(name) {
if (!this.actionInfo.length) {
throw new action_1.ActionNotFound('This State does not define any actions');
}
if (name === undefined) {
return new action_1.SimpleAction(this.client, this.actionInfo[0]);
}
for (const action of this.actionInfo) {
if (action.name === name) {
return new action_1.SimpleAction(this.client, action);
}
}
throw new action_1.ActionNotFound('This State defines no action');
}
/**
* Returns all actions
*/
actions() {
return this.actionInfo.map(action => new action_1.SimpleAction(this.client, action));
}
/**
* Checks if the specified action exists.
*
* If no name is given, checks if _any_ action exists.
*/
hasAction(name) {
if (name === undefined)
return this.actionInfo.length > 0;
for (const action of this.actionInfo) {
if (name === action.name) {
return true;
}
}
return false;
}
/**
* Returns a serialization of the state that can be used in a HTTP
* response.
*
* For example, a JSON object might simply serialize using
* JSON.serialize().
*/
serializeBody() {
if ((global.Buffer && this.data instanceof Buffer) ||
(global.Blob && this.data instanceof Blob) ||
typeof this.data === 'string') {
return this.data;
}
return JSON.stringify(this.data);
}
/**
* Certain formats can embed other resources, identified by their
* own URI.
*
* When a format has embedded resources, we will use these to warm
* the cache.
*
* This method returns every embedded resource.
*/
getEmbedded() {
return this.embedded;
}
clone() {
return new BaseState({
client: this.client,
uri: this.uri,
data: this.data,
headers: new Headers(this.headers),
links: new link_1.Links(this.links.defaultContext, this.links.getAll()),
actions: this.actionInfo,
});
}
}
exports.BaseState = BaseState;
//# sourceMappingURL=base-state.js.map