import { mergeConfig, mergeOptions, normalizeConfig, normalizeOptions, } from '@/core/config-defaults' import { stringifyUrl } from '@/core/serializer/url-serializer' import { deepClone } from '@/shared/helpers/deep-clone' import type { FLuentUrlPlainObject, FluentUrlConfig, QueriesPlainObject, } from '@/shared/types' export class FluentUrl { private readonly config: FluentUrlConfig private readonly protocol?: string private readonly hostname?: string private readonly paths: string[] private readonly port?: number private readonly fragment?: string private readonly queries: QueriesPlainObject constructor( urlOrOptions?: Partial | string, config?: Partial, ) { this.config = normalizeConfig(config) const { protocol, hostname, paths, port, fragment, queries } = normalizeOptions({ urlOptions: urlOrOptions, parseQuery: this.config.parseQuery, }) this.protocol = protocol this.hostname = hostname this.paths = paths this.port = port this.fragment = fragment this.queries = queries } public toString(): string { return stringifyUrl({ obj: { protocol: this.protocol, hostname: this.hostname, paths: this.paths, port: this.port, fragment: this.fragment, queries: this.queries, }, stringifyQuery: this.config.stringifyQuery, }) } public toJSON(): string { return this.toString() } public valueOf(): string { return this.toString() } public toPlainObject(): FLuentUrlPlainObject { return deepClone({ protocol: this.protocol, hostname: this.hostname, paths: this.paths, port: this.port, fragment: this.fragment, queries: this.queries, }) } public clone( options?: Partial, config?: Partial, ): FluentUrl { return new FluentUrl( mergeOptions( { protocol: this.protocol, hostname: this.hostname, paths: this.paths, port: this.port, fragment: this.fragment, queries: this.queries, }, options, ), mergeConfig(this.config, config), ) } }