UNPKG

@prass/botpress-native

Version:

A simple and powerful SDK for integrating Botpress Chat API with React Native,

116 lines (114 loc) 4.57 kB
/** * Utility class for constructing safe and consistent URLs. * Ensures correct handling of leading/trailing slashes and prevents duplicate base URLs. */ class PrepareUrl { /** * Constructs a PrepareUrl instance. * * @param initialParts - Array of URL segments to form the base URL. * @throws {Error} If initialParts is not an array. * @throws {Error} If initialParts contain invalid URL structure. */ constructor(initialParts = []) { this.baseUrl = null; if (!Array.isArray(initialParts)) { throw new TypeError("Initial parts must be an array of strings."); } if (initialParts.length > 0) { this.baseUrl = this.cleanAndJoin(initialParts); this.validateBaseUrl(); } } /** * Cleans and joins URL parts by removing unnecessary slashes. * * @param parts - Array of URL segments. * @returns A properly formatted URL string. */ cleanAndJoin(parts) { return parts .map((part) => { if (typeof part !== "string") { throw new TypeError("URL segments must be strings."); } return part.replace(/^\/+|\/+$/g, ""); // Remove leading/trailing slashes }) .filter((part) => part !== "") // Remove empty segments .join("/"); } /** * Validates that the base URL has a proper protocol (http or https). * * @throws {Error} If the base URL is invalid. */ validateBaseUrl() { if (this.baseUrl && !/^https?:\/\//i.test(this.baseUrl)) { throw new Error("Base URL must start with 'http://' or 'https://'."); } } /** * Generates a complete and safe URL with optional query parameters. * * If the base URL is not set, it initializes dynamically from the first `getUrl()` call. * Prevents duplicate base URLs when segments include the base URL again. * * @param segments - Additional URL segments. * @param queryParams - Optional query parameters object. * @returns A well-formed URL string with query parameters (if provided). * @throws {Error} If no base URL is set and segments do not form a valid URL. */ getUrl(segments, queryParams) { // If no segments are provided, return the current base URL if (!segments || segments.length === 0) { return this.baseUrl || ""; } // Validate segments if (!Array.isArray(segments)) { throw new TypeError("Segments must be an array of strings or numbers."); } const cleanedSegments = this.cleanAndJoin(segments.map(String)); // If baseUrl is not set, initialize it dynamically if (!this.baseUrl) { this.baseUrl = cleanedSegments; this.validateBaseUrl(); return this.appendQueryParams(this.baseUrl, queryParams); } // Prevent duplicate base URLs const baseParts = this.baseUrl.split("/"); const segmentParts = cleanedSegments.split("/"); let startIndex = 0; while (startIndex < segmentParts.length && startIndex < baseParts.length && segmentParts[startIndex] === baseParts[startIndex]) { startIndex++; } const uniquePath = segmentParts.slice(startIndex).join("/"); // Generate the final URL const finalUrl = uniquePath ? `${this.baseUrl}/${uniquePath}` : this.baseUrl; return this.appendQueryParams(finalUrl, queryParams); } /** * Appends query parameters to a URL if provided. * Supports array values by repeating keys in the query string. * * @param url - The base URL to append query parameters to. * @param queryParams - An object of key-value pairs to convert to query parameters. * @returns The URL with query parameters appended. */ appendQueryParams(url, queryParams) { if (queryParams && Object.keys(queryParams).length > 0) { const queryString = Object.entries(queryParams) .flatMap(([key, value]) => Array.isArray(value) ? value.map((v) => v && `${encodeURIComponent(key)}=${encodeURIComponent(v)}`) : value && `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) .join("&"); return `${url}${queryString ? `?${queryString}` : ""}`; } return url; } } export { PrepareUrl }; //# sourceMappingURL=prepareUrl.js.map