UNPKG

@barchart/common-js

Version:
347 lines (275 loc) 12.3 kB
import * as assert from './../../../lang/assert.js'; import CredentialsBuilder from './CredentialsBuilder.js'; import ParametersBuilder from './ParametersBuilder.js'; import Endpoint from './../definitions/Endpoint.js'; import ProtocolType from './../definitions/ProtocolType.js'; import VerbType from './../definitions/VerbType.js'; import CompositeErrorInterceptor from './../interceptors/CompositeErrorInterceptor.js'; import CompositeResponseInterceptor from './../interceptors/CompositeResponseInterceptor.js'; import CompositeRequestInterceptor from './../interceptors/CompositeRequestInterceptor.js'; import ErrorInterceptor from './../interceptors/ErrorInterceptor.js'; import ResponseInterceptor from './../interceptors/ResponseInterceptor.js'; import RequestInterceptor from './../interceptors/RequestInterceptor.js'; /** * Fluent interface for building a {@link Endpoint}. * * @public */ export default class EndpointBuilder { #endpoint; /** * @param {string} name * @param {string=} description */ constructor(name, description) { assert.argumentIsRequired(name, 'name', String); assert.argumentIsOptional(description, 'description', String); this.#endpoint = new Endpoint(name, description); } /** * The {@link Endpoint}, given all the information provided thus far. * * @public * @returns {Endpoint} */ get endpoint() { return this.#endpoint; } /** * Sets the verb. * * @public * @param {VerbType} verb * @returns {EndpointBuilder} */ withVerb(verb) { assert.argumentIsRequired(verb, 'verb', VerbType, 'VerbType'); this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Sets the host. * * @public * @param {ProtocolType} protocol * @returns {EndpointBuilder} */ withProtocol(protocol) { assert.argumentIsRequired(protocol, 'protocol', ProtocolType, 'ProtocolType'); this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Sets the host. * * @public * @param {string} host * @returns {EndpointBuilder} */ withHost(host) { assert.argumentIsRequired(host, 'host', String); this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Sets the port. * * @public * @param {number} port * @returns {EndpointBuilder} */ withPort(port) { assert.argumentIsRequired(port, 'port', Number); this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link Parameters} collection, describing the request headers, using a callback. * * @public * @param {parametersBuilderCallback} callback * @returns {EndpointBuilder} */ withHeadersBuilder(callback) { assert.argumentIsRequired(callback, 'callback', Function); const builder = new ParametersBuilder(); callback(builder); const headers = builder.parameters; this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link Parameters} collection, describing the request path, using a callback. * * @public * @param {parametersBuilderCallback} callback * @returns {EndpointBuilder} */ withPathBuilder(callback) { assert.argumentIsRequired(callback, 'callback', Function); const builder = new ParametersBuilder(true); callback(builder); const path = builder.parameters; this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link Parameters} collection, describing the request querystring, using a callback. * * @public * @param {parametersBuilderCallback} callback * @returns {EndpointBuilder} */ withQueryBuilder(callback) { assert.argumentIsRequired(callback, 'callback', Function); const builder = new ParametersBuilder(); callback(builder); const query = builder.parameters; this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link Parameters} collection, describing the request body, using a callback. * * @public * @param {parametersBuilderCallback} callback * @returns {EndpointBuilder} */ withBodyBuilder(callback) { assert.argumentIsRequired(callback, 'callback', Function); const builder = new ParametersBuilder(); callback(builder); const body = builder.parameters; this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a body to the request. * * @public * @param {string=} description - The human-readable description of the request body. * @returns {EndpointBuilder} */ withBody(description) { assert.argumentIsOptional(description, 'description', String); return this.withBodyBuilder((bodyBuilder) => { bodyBuilder.withDelegateParameter((description || 'request payload'), 'body', x => x); }); } /** * Adds basic authentication to the request. * * @public * @param {string} username * @param {string} password * @returns {EndpointBuilder} */ withBasicAuthentication(username, password) { assert.argumentIsRequired(username, 'username', String); assert.argumentIsRequired(password, 'password', String); return this.withBasicAuthenticationBuilder((credentialsBuilder) => { credentialsBuilder.withLiteralUsername(username); credentialsBuilder.withLiteralPassword(password); }); } /** * Adds basic authentication to the request, using a callback. * * @public * @param {Function} callback * @returns {EndpointBuilder} */ withBasicAuthenticationBuilder(callback) { assert.argumentIsRequired(callback, 'callback', Function); const builder = new CredentialsBuilder(); callback(builder); const credentials = builder.credentials; this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link RequestInterceptor}. * * @public * @param {RequestInterceptor} requestInterceptor * @returns {EndpointBuilder} */ withRequestInterceptor(requestInterceptor) { assert.argumentIsRequired(requestInterceptor, 'requestInterceptor', RequestInterceptor, 'RequestInterceptor'); let existingRequestInterceptor = this.endpoint.requestInterceptor; let updatedRequestInterceptor; if (existingRequestInterceptor && existingRequestInterceptor !== RequestInterceptor.EMPTY) { updatedRequestInterceptor = new CompositeRequestInterceptor(existingRequestInterceptor, requestInterceptor); } else { updatedRequestInterceptor = requestInterceptor; } this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, updatedRequestInterceptor, this.endpoint.responseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link ResponseInterceptor} for successful web service responses. * * @public * @param {ResponseInterceptor} responseInterceptor * @returns {EndpointBuilder} */ withResponseInterceptor(responseInterceptor) { assert.argumentIsRequired(responseInterceptor, 'responseInterceptor', ResponseInterceptor, 'ResponseInterceptor'); let existingResponseInterceptor = this.endpoint.responseInterceptor; let updatedResponseInterceptor; if (existingResponseInterceptor && existingResponseInterceptor !== ResponseInterceptor.EMPTY) { updatedResponseInterceptor = new CompositeResponseInterceptor(existingResponseInterceptor, responseInterceptor); } else { updatedResponseInterceptor = responseInterceptor; } this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, updatedResponseInterceptor, this.endpoint.errorInterceptor); return this; } /** * Adds a {@link ErrorInterceptor} for handling remote web service errors. * * @public * @param {ErrorInterceptor} errorInterceptor * @returns {EndpointBuilder} */ withErrorInterceptor(errorInterceptor) { assert.argumentIsRequired(errorInterceptor, 'errorInterceptor', ErrorInterceptor, 'ErrorInterceptor'); let existingErrorInterceptor = this.endpoint.errorInterceptor; let updatedErrorInterceptor; if (existingErrorInterceptor && existingErrorInterceptor !== ErrorInterceptor.EMPTY) { updatedErrorInterceptor = new CompositeErrorInterceptor(existingErrorInterceptor, errorInterceptor); } else { updatedErrorInterceptor = errorInterceptor; } this.#endpoint = new Endpoint(this.endpoint.name, this.endpoint.description, this.endpoint.verb, this.endpoint.protocol, this.endpoint.host, this.endpoint.port, this.endpoint.path, this.endpoint.query, this.endpoint.headers, this.endpoint.body, this.endpoint.credentials, this.endpoint.requestInterceptor, this.endpoint.responseInterceptor, updatedErrorInterceptor); return this; } /** * Factory function for creating an {@link EndpointBuilder} instance. * * @public * @static * @param {string} name * @param {string=} description * @returns {EndpointBuilder} */ static for(name, description) { return new EndpointBuilder(name, description); } /** * Returns a string representation. * * @public * @returns {string} */ toString() { return '[EndpointBuilder]'; } } /** * A function that returns a {@link ParametersBuilder}. * * @callback parametersBuilderCallback * @param {ParametersBuilder} parameterBuilder * @returns {void} */