UNPKG

ketting

Version:

Opiniated HATEAOS / Rest client.

181 lines 5.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FollowPromiseMany = exports.FollowPromiseOne = void 0; /** * Base interface for both FollowOne and FollowAll */ class FollowPromise { constructor() { this.prefetchEnabled = false; this.preferTranscludeEnabled = false; this.useHeadEnabled = false; } preFetch() { this.prefetchEnabled = true; return this; } preferTransclude() { this.preferTranscludeEnabled = true; return this; } /** * Use a HTTP HEAD request to fetch the links. * * This is useful when interacting with servers that embed links in Link * Headers. */ useHead() { this.useHeadEnabled = true; return this; } } /** * The FollowPromise class is what's being returned from follow() functions. * * It's 'PromiseLike', which means you can treat it like a Promise, and it * can be awaited. When used as a Promise, it resolves to the Resource object * that was followed. * * In addition to being a Promise<Resource> stand-in, it also exposes other * functions, namely: * * * `follow()` to allow a user to chain several follow() functions to do * several 'hops' all at once. * * `followAll()`, allowing a user to call `followAll()` at the end of a * chain. */ class FollowPromiseOne extends FollowPromise { constructor(resource, rel, variables) { super(); this.resource = resource; this.rel = rel; this.variables = variables; } /** * This 'then' function behaves like a Promise then() function. * * This method signature is pretty crazy, but trust that it's pretty much * like any then() method on a promise. */ then(onfulfilled, onrejected) { return this.fetchLinkedResource().then(onfulfilled, onrejected); } /** * This 'catch' function behaves like a Promise catch() function. */ catch(onrejected) { return this.fetchLinkedResource().then(undefined, onrejected); } /** * Implementation of a Promise.finally function */ finally(onfinally) { return this.then(() => onfinally(), () => onfinally()); } /** * Follow another link immediately after following this link. * * This allows you to follow several hops of links in one go. * * For example: resource.follow('foo').follow('bar'); */ follow(rel, variables) { return new FollowPromiseOne(this.fetchLinkedResource(), rel, variables); } /** * Follows a set of links immediately after following this link. * * For example: resource.follow('foo').followAll('item'); */ followAll(rel) { return new FollowPromiseMany(this.fetchLinkedResource(), rel); } /** * This function does the actual fetching of the linked * resource. */ async fetchLinkedResource() { const resource = await this.resource; const headers = {}; if (!this.useHeadEnabled && this.preferTranscludeEnabled) { headers.Prefer = 'transclude=' + this.rel; } let state; if (this.useHeadEnabled) { state = await resource.head({ headers }); } else { state = await resource.get({ headers }); } const newResource = state.follow(this.rel, this.variables); if (this.prefetchEnabled) { newResource.get().catch((err) => { // eslint-disable-next-line no-console console.warn('Error while prefetching linked resource', err); }); } return newResource; } } exports.FollowPromiseOne = FollowPromiseOne; /** */ class FollowPromiseMany extends FollowPromise { constructor(resource, rel) { super(); this.resource = resource; this.rel = rel; } /** * This 'then' function behaves like a Promise then() function. */ then(onfulfilled, onrejected) { return this.fetchLinkedResources().then(onfulfilled, onrejected); } /** * This 'catch' function behaves like a Promise catch() function. */ catch(onrejected) { return this.fetchLinkedResources().then(undefined, onrejected); } /** * Implementation of a Promise.finally function */ finally(onfinally) { return this.then(() => onfinally(), () => onfinally()); } /** * This function does the actual fetching, to obtained the url * of the linked resource. It returns the Resource object. */ async fetchLinkedResources() { const resource = await this.resource; const headers = {}; if (!this.useHeadEnabled && this.preferTranscludeEnabled) { headers.Prefer = 'transclude=' + this.rel; } let state; if (this.useHeadEnabled) { state = await resource.head({ headers }); } else { state = await resource.get({ headers }); } const result = state.followAll(this.rel); if (this.prefetchEnabled) { result.map(resource => { resource.get().catch(err => { // eslint-disable-next-line no-console console.warn('Error while prefetching linked resource', err); }); }); } return result; } } exports.FollowPromiseMany = FollowPromiseMany; //# sourceMappingURL=follow-promise.js.map