import * as plugins from './smarturl.plugins.js'; export interface IUrlObject { href: string; origin: string; protocol: string; username: string; password: string; host: string; hostname: string; port: string; path: string; pathname: string; search: string; searchParams: ISearchParams; hash: string; } export interface ISearchParams { [key: string]: string; } export class Smarturl implements IUrlObject { public static createFromUrl( urlArg: string, optionsArg?: { searchParams?: ISearchParams; } ): Smarturl { const parsedUrlInstance = new URL(urlArg); const searchParams: ISearchParams = {}; // enrichment const searchParamPairs: { key: string; value: string; }[] = []; if (parsedUrlInstance.search) { parsedUrlInstance.search .replace('?', '') .split('&') .map((searchParamPair) => { searchParamPairs.push({ key: searchParamPair.split('=')[0], value: searchParamPair.split('=')[1], }); }); } for (const searchParamPair of searchParamPairs) { searchParams[searchParamPair.key] = searchParamPair.value; } if (optionsArg?.searchParams) { for (const key of Object.keys(optionsArg.searchParams)) { searchParams[key] = optionsArg.searchParams[key]; } } let path = parsedUrlInstance.pathname || ''; if (Object.keys(searchParams).length > 0) { path += '?'; let first = true; for (const key of Object.keys(searchParams)) { if (first) { first = false; } else { path += '&'; } path += `${key}=${searchParams[key]}`; } } const parsedUrl: IUrlObject = { ...parsedUrlInstance, href: parsedUrlInstance.href, origin: parsedUrlInstance.origin, protocol: parsedUrlInstance.protocol, username: parsedUrlInstance.username, password: parsedUrlInstance.password, host: parsedUrlInstance.host, hostname: parsedUrlInstance.hostname, port: parsedUrlInstance.port, path, pathname: parsedUrlInstance.pathname, search: parsedUrlInstance.search, searchParams, hash: parsedUrlInstance.hash, }; if (!parsedUrl.port && parsedUrl.protocol === 'https:') { // console.log(`inferring port 443 for "https:"`); parsedUrl.port = '443'; } if (!parsedUrl.port && parsedUrl.protocol === 'http:') { // console.log(`inferring port 80 for "http:"`); parsedUrl.port = '80'; } const returnSmarturl = new Smarturl(); Object.assign(returnSmarturl, parsedUrl); return returnSmarturl; } public static createFromParsedUrl(parsedUrlArg: IUrlObject) { const returnSmarturl = new Smarturl(); Object.assign(returnSmarturl, parsedUrlArg); return returnSmarturl; } // INSTANCE href: string; origin: string; protocol: string; username: string; password: string; host: string; hostname: string; port: string; path: string; pathname: string; search: string; searchParams: ISearchParams; hash: string; constructor() { this.searchParams = {}; } clone(): Smarturl { const clonedInstance = new Smarturl(); Object.assign(clonedInstance, this); clonedInstance.searchParams = { ...this.searchParams }; return clonedInstance; } toString() { let userpart = ``; if (this.username && !this.password) { userpart = `${this.username}@`; } if (this.username && this.password) { userpart = `${this.username}:${this.password}@`; } return `${this.protocol}//${userpart}${this.hostname}:${this.port}${this.path}`; } }