UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

112 lines (111 loc) 6.28 kB
import type { AnyCaller } from "./function.js"; import type { Nullish } from "./null.js"; import type { AbsolutePath } from "./path.js"; import type { ImmutableURI } from "./uri.js"; /** * A URL string has a protocol and a `//`. * - The `//` at the start of a URL indicates that it has a hierarchical path component, so this makes it a URL. * - URLs have a concept of "absolute" or "relative" URLs, since they have a path. */ export type URLString = `${string}://${string}`; /** * Construct a correctly-typed `URL` object. * - This is a more correctly typed version of the builtin Javascript `URL` constructor. * - Requires a URL string, URL object, or path as input, and optionally a base URL. * - If a path is provided as input, a base URL _must_ also be provided. * - The returned type is */ export interface ImmutableURLConstructor { new (input: URLString | ImmutableURL, base?: URLString | ImmutableURL): ImmutableURL; new (input: URLString | ImmutableURL | string, base: URLString | ImmutableURL): ImmutableURL; } /** * Object that describes a valid URL, e.g. `http://example.com/path/to/resource` * - Improves the builtin Javascript `URL` class to more accurately type its properties. * * URI and URL differences: * - According to RFC 3986, URLs are a subset of URIs that have a hierarchical path component, e.g. `http://example.com/path`. * - The `//` at the start of a URL indicates that it has a hierarchical path component, so this makes it a URL. * - The absence of `//` indicates a non-hierarchical URI. * - URLs can be considered as "hierarchical URIs". * - All URLs are also URIs, but not all URIs are URLs. * * Javascript URL problems: * - Javascript `URL` instance can actually represent any kind of URI (not just URLs). * - It's more "correct" terminology to use `URI` to refer to what the Javascript `URL` class represents. * - You can tell the difference because a URL will have a non-empty `host` property, whereas URIs will never have a `host` (it will be `""` empty string). * - Javascript URLs are mutable which can lead to subtle bugs. */ export interface ImmutableURL extends ImmutableURI { readonly href: URLString; readonly origin: URLString; readonly pathname: AbsolutePath; } export declare const ImmutableURL: ImmutableURLConstructor; /** Values that can be converted to a URL instance. */ export type PossibleURL = string | URL; /** * Is an unknown value a URL object? * - Must be a `URL` instance and its origin must start with `scheme://` */ export declare function isURL(value: unknown): value is ImmutableURL; /** Assert that an unknown value is a URL object. */ export declare function assertURL(value: unknown, caller?: AnyCaller): asserts value is ImmutableURL; /** * Resolve a possible URI relative to a base, or return `undefined` if conversion fails. * - Returns any kind of URI — not just hierarchical `scheme://host` URLs. Use `getURL()` when a true URL is specifically required. * - A `URL` instance is returned as-is (already absolute, base ignored). * * Note: the base is normalised with `getBaseURL()`, so it is always treated as if it ends in a slash. * - e.g. if `base` is `http://p.com/a/b/c` the path resolves relative to `c/` as if a trailing slash was present. * - This differs from the default behaviour of `new URL()`, but is the more natural expected result. */ export declare function getBasedURI(input: Nullish<PossibleURL>, base?: PossibleURL): ImmutableURI | undefined; /** * Resolve a possible URL relative to a base URL, or return `undefined` if conversion fails. * - Like `getBasedURI()` but only succeeds for true `scheme://host` URLs — other URIs (e.g. `mailto:`) return `undefined`. */ export declare function getURL(target: Nullish<PossibleURL>, base?: PossibleURL): ImmutableURL | undefined; /** Convert a possible URL to a URL, or throw `RequiredError` if conversion fails. */ export declare function requireURL(target: PossibleURL, base?: PossibleURL, caller?: AnyCaller): ImmutableURL; /** * Resolve and match a target URL/path against a base URL and return the remaining path. * * - Need to be valid _URLs_ not just _URIs_, i.e. needs to have `protocol://` at the start. * - Origins need to match, i.e. `http://localhost` !== `http://localhost:4020` * - Relative targets are resolved against the normalized base URL. * * @param target URL to match against `base` — if this is a relative path it will be resolved against `base` * * @returns Absolute path starting with `/`, or `undefined` for origin mismatches or non-matching paths. */ export declare function matchURLPrefix(target: PossibleURL | undefined, base: PossibleURL | undefined, caller?: AnyCaller): AbsolutePath | undefined; /** * Is a target URL active relative to a base URL? * - Active means `target` and `base` resolve to the exact same URL (same origin, same path). * - Origin mismatches return `false`. * * @param target URL whose status to test — relative paths resolve against `base`. * @param base Base URL to test against. */ export declare function isURLActive(target: PossibleURL | undefined, base: PossibleURL | undefined, caller?: AnyCaller): boolean; /** * Is a target URL proud relative to a base URL? * - Proud means `target` is `base` or a descendant of `base` — i.e. `base` is at or above `target` in the URL hierarchy. * - Useful for marking a menu item as "current branch" when the user is somewhere deeper in its sub-tree. * - Origin mismatches return `false`. * * @param target URL whose status to test — relative paths resolve against `base`. * @param base Base URL to test against. */ export declare function isURLProud(target: PossibleURL | undefined, base: PossibleURL | undefined, caller?: AnyCaller): boolean; /** BaseURL is a URL with a guaranteed trailing slash on pathname. */ export interface BaseURL extends ImmutableURL { readonly pathname: `/` | `/${string}/`; } /** Is an unknown value a valid Base URL. */ export declare function isBaseURL(value: PossibleURL): value is BaseURL; /** Get a Base URL. */ export declare function getBaseURL(input: Nullish<PossibleURL>): BaseURL | undefined; /** Require a Base URL. */ export declare function requireBaseURL(value: PossibleURL, caller: AnyCaller): BaseURL;