spica
Version:
Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.
122 lines (117 loc) • 4.61 kB
text/typescript
import { AbsoluteURL, ReadonlyURL } from './url/internal';
export { StandardURL, standardize } from './url/internal';
export { ReadonlyURL } from './url/internal';
type Widen<T> = T extends `${infer _}` ? string : T;
export class URL<T extends string> implements Readonly<global.URL> {
constructor(url: URL.Href<T> | URL.Resource<T> | URL.Origin<T>, base?: string);
constructor(url: URLSegment<string> & T, base: T);
constructor(url: T, ...base:
T extends URLSegment<string> & 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<T> {
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<T> {
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<T> {
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<T> {
return this.url.host as any;
}
public get hostname(): URL.Hostname<T> {
return this.url.hostname as any;
}
public get port(): URL.Port {
return this.url.port as any;
}
public get path(): URL.Path<T> {
return this.params?.toString().replace(/^(?=.)/, `${this.pathname}?`)
?? this.url.path as any;
}
public get pathname(): URL.Pathname<T> {
return this.url.pathname as any;
}
public get search(): URL.Search<T> {
return this.params?.toString().replace(/^(?=.)/, '?')
?? this.url.search as any;
}
public get query(): URL.Query<T> {
return this.params?.toString().replace(/^(?=.)/, '?')
?? this.url.query as any;
}
public get hash(): URL.Hash<T> {
return this.url.hash as any;
}
public get fragment(): URL.Fragment<T> {
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<T extends string> = URLSegment<'href'> & Widen<T>;
export type Resource<T extends string> = URLSegment<'resource'> & Widen<T>;
export type Origin<T extends string> = URLSegment<'origin'> & Widen<T>;
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<T extends string> = URLSegment<'host'> & Widen<T>;
export type Hostname<T extends string> = URLSegment<'hostname'> & Widen<T>;
export type Port = URLSegment<'port'> & string;
export type Path<T extends string> = URLSegment<'path'> & Widen<T>;
export type Pathname<T extends string> = URLSegment<'pathname'> & Widen<T>;
export type Search<T extends string> = URLSegment<'search'> & Widen<T>;
export type Query<T extends string> = URLSegment<'query'> & Widen<T>;
export type Hash<T extends string> = URLSegment<'hash'> & Widen<T>;
export type Fragment<T extends string> = URLSegment<'fragment'> & Widen<T>;
}
declare class URLSegment<T extends string> {
private readonly URL: T;
}