UNPKG

logitar-js

Version:

Helper functions distributed by Logitar.

464 lines (463 loc) 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UrlBuilder = exports.Credentials = void 0; const stringUtils_1 = require("./stringUtils"); /** * Represents credentials to be used in an authentication system. */ class Credentials { /** * Returns the identifier of the credentials, typically an username. * @returns The identifier of the credentials. */ getIdentifier() { return this.identifier; } /** * Sets the identifier of the credentials, typically an username. * @param identifier The identifier to set. */ setIdentifier(identifier) { this.identifier = identifier; } /** * Returns the secret of the credentials, typically a password. * @returns The secret of the credentials. */ getSecret() { return this.secret; } /** * Sets the secret of the credentials, typically a password. * @param secret The secret to set. */ setSecret(secret) { this.secret = secret; } /** * Creates a new instance of the `Credentials` class. * @param identifier The identifier of the credentials, typically an username. * @param secret The secret of the credentials, typically a password. */ constructor(identifier = "", secret = "") { this.identifier = identifier; this.secret = secret; } /** * Parses the specified credentials using the `{identifier}:{secret}` format into a new instance of the `Credentials` class. * @param credentials * @returns The created instance. */ static parse(credentials) { credentials = (0, stringUtils_1.cleanTrim)(credentials); if (typeof credentials !== "string") { return undefined; } const index = credentials.indexOf(":"); if (index < 0) { return new Credentials(credentials); } return new Credentials(credentials.substring(0, index), credentials.substring(index + 1)); } } exports.Credentials = Credentials; /** * Represents a builder class used to build URLs. */ class UrlBuilder { /** * Returns the list of supported URL schemes. * @returns The supported URL schemes. */ static getSupportedSchemes() { return [...UrlBuilder.supportedSchemes]; } /** * Returns a value indicating whether or not the specified scheme is supported. * @param scheme The scheme to check. * @returns True if the scheme is supported, or false otherwise. */ static isSchemeSupported(scheme) { return UrlBuilder.supportedSchemes.has(scheme.trim().toLowerCase()); } /** * Returns the scheme of the URL. * @returns The scheme of the URL. */ getScheme() { return this.scheme; } /** * Sets the scheme of the URL. * @param scheme The scheme to set. * @param inferPort If true, the port will be inferred from the scheme. * @returns The instance of the builder. * @throws {Error} The scheme is not supported. */ setScheme(scheme, inferPort) { if (!UrlBuilder.isSchemeSupported(scheme)) { throw new Error(`The scheme '${scheme}' is not supported.`); } this.scheme = scheme.trim().toLowerCase(); if (inferPort) { this.port = UrlBuilder.inferPort(scheme); } return this; } /** * Returns the credentials of the URL. * @returns The credentials of the URL. */ getCredentials() { return this.credentials; } /** * Sets the credentials of the URL. * @param credentials The credentials to set. * @returns The instance of the builder. */ setCredentials(credentials) { this.credentials = credentials; return this; } /** * Returns the host of the URL. * @returns The host of the URL. */ getHost() { return this.host; } /** * Sets the host of the URL. The default host will be set if the specified host is empty. * @param host The host of the URL. * @returns The instance of the builder. */ setHost(host) { var _a; this.host = (_a = (0, stringUtils_1.cleanTrim)(host)) !== null && _a !== void 0 ? _a : UrlBuilder.DEFAULT_HOST; return this; } /** * Returns the port of the URL. * @returns The port of the URL. */ getPort() { return this.port; } /** * Sets the portal of the URL. * @param port The port of the URL. * @returns The instance of the builder. * @throws {Error} The port is not a number or not within port ranges (0-65535). */ setPort(port) { if (isNaN(port) || port < 0 || port > 65535) { throw new Error(`The port '${port}' must be a value between 0 and 65535.`); } this.port = port; return this; } /** * Returns the authority of the URL. * @returns The authority of the URL. */ getAuthority() { let authority = ""; if (this.credentials) { authority += `${this.credentials.getIdentifier()}:${this.credentials.getSecret()}@`; } authority += `${this.host}:${this.port}`; return authority; } /** * Sets the authority of the URL. * @param authority The authority of the URL. * @returns The instance of the builder. * @throws {Error} The value is not a valid URL authority. */ setAuthority(authority) { const parts = authority.split("@"); if (parts.length > 2) { throw new Error(`The value '${authority}' is not a valid URL authority.`); } else if (parts.length === 2) { this.setCredentials(Credentials.parse(parts[0])); } const endPoint = parts[parts.length - 1]; const index = endPoint.indexOf(":"); if (index < 0) { this.setHost(endPoint); } else { this.setHost(endPoint.substring(0, index)); this.setPort(Number(endPoint.substring(index + 1))); } return this; } /** * Returns the list of segments of the URL path. * @returns The segments of the URL. */ getSegments() { return [...this.segments]; } /** * Sets the segments of the URL path. Empty segments will be discarded. * @param segments The segments of the URL. * @returns The instance of the builder. */ setSegments(segments) { this.segments.length = 0; segments.forEach((segment) => { if (!(0, stringUtils_1.isNullOrWhiteSpace)(segment)) { this.segments.push(segment.trim()); } }); return this; } /** * Returns the path of the URL. * @returns The path of the URL. */ getPath() { return this.segments.length === 0 ? undefined : `/${this.segments.join("/")}`; } /** * Sets the path of the URL. * @param path The path of the URL. * @returns The instance of the builder. */ setPath(path) { var _a; this.setSegments((_a = path === null || path === void 0 ? void 0 : path.split("/")) !== null && _a !== void 0 ? _a : []); return this; } /** * Returns the query parameters of the URL. * @returns The query parameters of the URL. */ getQuery() { return new Map(this.query); } /** * Returns the query string of the URL. * @returns The query string of the URL. */ getQueryString() { if (this.query.size === 0) { return undefined; } const parameters = []; this.query.forEach((values, key) => values.forEach((value) => parameters.push([key, value].join("=")))); return `?${parameters.join("&")}`; } /** * Adds a query parameter to the URL. The specified values will be appended to existing values associated to this key. Empty keys and values will be discarded. * @param key The key of the parameter. * @param values The value or the values of the parameter. * @returns The instance of the builder. */ addQuery(key, values) { var _a; if (typeof values === "string") { return this.addQuery(key, [values]); } if (!(0, stringUtils_1.isNullOrWhiteSpace)(key)) { key = key.trim(); const existingValues = (_a = this.query.get(key)) !== null && _a !== void 0 ? _a : []; values.forEach((value) => { if (!(0, stringUtils_1.isNullOrWhiteSpace)(value)) { existingValues.push(value.trim()); } }); this.setQuery(key, existingValues); } return this; } /** * Sets a query parameter to the URL. The specified values will replace the existing values associated to this key. Empty keys and values will be discarded. * @param key The key of the parameter. * @param values The value or the values of the parameter. * @returns The instance of the builder. */ setQuery(key, values) { if (typeof values === "string") { return this.setQuery(key, [values]); } if (!(0, stringUtils_1.isNullOrWhiteSpace)(key)) { key = key.trim(); const newValues = []; values.forEach((value) => { if (!(0, stringUtils_1.isNullOrWhiteSpace)(value)) { newValues.push(value.trim()); } }); if (newValues.length > 0) { this.query.set(key, newValues); } else { this.query.delete(key); } } return this; } /** * Sets the query string of the URL. Empty keys and values will be discarded. * @param queryString The query string of the URL. * @returns The instance of the builder. */ setQueryString(queryString) { var _a; queryString = (0, stringUtils_1.cleanTrim)((0, stringUtils_1.trimStart)((_a = queryString === null || queryString === void 0 ? void 0 : queryString.trim()) !== null && _a !== void 0 ? _a : "", "?")); this.query.clear(); if (typeof queryString === "string") { const parameters = queryString.split("&"); parameters.forEach((parameter) => { const index = parameter.indexOf("="); if (index >= 0) { this.addQuery(parameter.substring(0, index), parameter.substring(index + 1)); } }); } return this; } /** * Returns the fragment of the URL. * @returns The fragment of the URL. */ getFragment() { return this.fragment; } /** * Sets the fragment of the URL. * @param fragment The fragment of the URL. * @returns The instance of the builder. */ setFragment(fragment) { var _a; fragment = (0, stringUtils_1.cleanTrim)((0, stringUtils_1.trimStart)((_a = fragment === null || fragment === void 0 ? void 0 : fragment.trim()) !== null && _a !== void 0 ? _a : "", "#")); this.fragment = typeof fragment !== "string" ? undefined : `#${fragment}`; return this; } /** * Returns the parameters of the URL. Parameters are tokens that replace values in built URLs. * @returns The parameters of the URL. */ getParameters() { return new Map(this.parameters); } /** * Sets a parameter of the URL. Parameters are tokens that replace values in built URLs. * @param key The key of the parameter. * @param value The value of the parameter. * @returns The instance of the builder. * @throws {Error} The key is empty. */ setParameter(key, value) { if ((0, stringUtils_1.isNullOrWhiteSpace)(key)) { throw new Error("The parameter key is required."); } key = key.trim(); if ((0, stringUtils_1.isNullOrWhiteSpace)(value)) { this.parameters.delete(key); } else if (value) { this.parameters.set(key, value.trim()); } return this; } /** * Creates a new instance of the `UrlBuilder` class. * @param options The initialization options. */ constructor(options) { this.scheme = UrlBuilder.DEFAULT_SCHEME; this.host = UrlBuilder.DEFAULT_HOST; this.port = 80; this.segments = []; this.query = new Map(); this.parameters = new Map(); options = options !== null && options !== void 0 ? options : {}; if (options.scheme) { this.setScheme(options.scheme, true); } if (options.host) { this.setHost(options.host); } if (options.port) { this.setPort(options.port); } if (options.path) { this.setPath(options.path); } if (options.queryString) { this.setQueryString(options.queryString); } if (options.fragment) { this.setFragment(options.fragment); } if (options.credentials) { this.setCredentials(options.credentials); } } /** * Builds an URL of the specified kind. * @param kind The URL kind (defaults to `Absolute`). * @returns The built URL. */ build(kind = "Absolute") { let url = ""; if (kind === "Absolute") { url += `${this.scheme}://${this.getAuthority()}`; } const path = this.getPath(); if (typeof path === "string") { url += path; } const queryString = this.getQueryString(); if (typeof queryString === "string") { url += queryString; } const fragment = this.getFragment(); if (typeof fragment === "string") { url += fragment; } this.parameters.forEach((value, key) => { const pattern = `\\{${key}\\}`; url = url.replace(new RegExp(pattern, "g"), value); }); return url; } /** * Builds an absolute URL. * @returns The built URL. */ buildAbsolute() { return this.build("Absolute"); } /** * Builds a relative URL. * @returns The built URL. */ buildRelative() { return this.build("Relative"); } static inferPort(scheme) { switch (scheme.trim().toLowerCase()) { case "https": return 443; default: return 80; } } } exports.UrlBuilder = UrlBuilder; /** * The default URL scheme. */ UrlBuilder.DEFAULT_SCHEME = "http"; /** * The default URL host. */ UrlBuilder.DEFAULT_HOST = "localhost"; UrlBuilder.supportedSchemes = new Set(["http", "https"]);