import { AbsoluteURL, ReadonlyURL } from './url/internal'; export { StandardURL, standardize } from './url/internal'; export { ReadonlyURL } from './url/internal'; type Widen = T extends `${infer _}` ? string : T; export class URL implements Readonly { constructor(url: URL.Href | URL.Resource | URL.Origin, base?: string); constructor(url: URLSegment & T, base: T); constructor(url: T, ...base: T extends URLSegment & infer U ? [U] : T extends AbsoluteURL | `${string}:${string}` ? [string?] : T extends `${infer _}` ? [string] : [T]); constructor(source: string, base?: string) { source = source.trim(); base = base?.trim(); this.url = new ReadonlyURL(source, base!); this.params = undefined; this.source = source; this.base = base; assert(this.url.href.endsWith(`${this.port}${this.pathname}${this.query}${this.fragment}`)); assert(this.href === this.url.href); //assert(this.href.startsWith(this.resource)); assert(this.origin === this.url.origin); assert(this.protocol === this.url.protocol); assert(this.host === this.url.host); assert(this.hostname === this.url.hostname); assert(this.port === this.url.port); } private readonly url: ReadonlyURL; private params?: URLSearchParams; public readonly source: string; public readonly base?: string; public get href(): URL.Href { return this.params?.toString().replace(/^(?=.)/, `${this.url.href.slice(0, -this.url.query.length - this.url.fragment.length || this.url.href.length)}?`).concat(this.fragment) ?? this.url.href as any; } public get resource(): URL.Resource { return this.params?.toString().replace(/^(?=.)/, `${this.url.href.slice(0, -this.url.query.length - this.url.fragment.length || this.url.href.length)}?`) ?? this.url.resource as any; } public get origin(): URL.Origin { return this.url.origin as any; } public get scheme(): URL.Scheme { return this.url.scheme as any; } public get protocol(): URL.Protocol { return this.url.protocol as any; } public get username(): URL.Username { return this.url.username as any; } public get password(): URL.Password { return this.url.password as any; } public get host(): URL.Host { return this.url.host as any; } public get hostname(): URL.Hostname { return this.url.hostname as any; } public get port(): URL.Port { return this.url.port as any; } public get path(): URL.Path { return this.params?.toString().replace(/^(?=.)/, `${this.pathname}?`) ?? this.url.path as any; } public get pathname(): URL.Pathname { return this.url.pathname as any; } public get search(): URL.Search { return this.params?.toString().replace(/^(?=.)/, '?') ?? this.url.search as any; } public get query(): URL.Query { return this.params?.toString().replace(/^(?=.)/, '?') ?? this.url.query as any; } public get hash(): URL.Hash { return this.url.hash as any; } public get fragment(): URL.Fragment { return this.url.fragment as any; } public get searchParams(): URLSearchParams { return this.params ??= new URLSearchParams(this.search); } public toString(): string { return this.url.toString(); } public toJSON(): string { return this.url.toJSON(); } } export namespace URL { export type Href = URLSegment<'href'> & Widen; export type Resource = URLSegment<'resource'> & Widen; export type Origin = URLSegment<'origin'> & Widen; export type Scheme = URLSegment<'scheme'> & string; export type Protocol = URLSegment<'protocol'> & string; export type Username = URLSegment<'username'> & string; export type Password = URLSegment<'password'> & string; export type Host = URLSegment<'host'> & Widen; export type Hostname = URLSegment<'hostname'> & Widen; export type Port = URLSegment<'port'> & string; export type Path = URLSegment<'path'> & Widen; export type Pathname = URLSegment<'pathname'> & Widen; export type Search = URLSegment<'search'> & Widen; export type Query = URLSegment<'query'> & Widen; export type Hash = URLSegment<'hash'> & Widen; export type Fragment = URLSegment<'fragment'> & Widen; } declare class URLSegment { private readonly URL: T; }