shelving
Version:
Toolkit for using data in JavaScript.
131 lines (130 loc) • 4.66 kB
JavaScript
import { getGetter, getSetter } from "../util/class.js";
import { clearURIParams, getURIParam, getURIParams, omitURIParams, requireURIParam, withURIParam, withURIParams, } from "../util/uri.js";
import { getURL, isURLActive, isURLProud, requireURL } from "../util/url.js";
import { BusyStore } from "./BusyStore.js";
/** Store a URL, e.g. `https://top.com/a/b/c` */
export class URLStore extends BusyStore {
base;
// Override to convert possible URL to URL.
constructor(url, base) {
const baseURL = getURL(base);
super(requireURL(url, baseURL, URLStore));
this.base = baseURL;
}
// Override to convert possible URL to URL (relative to `this.base`).
_convert(value, caller) {
return requireURL(value, this.base, caller);
}
// Override for fast equality.
_equal(a, b) {
return a.href === b.href;
}
get href() {
return this.value.href;
}
set href(href) {
this.value = href;
}
get origin() {
return this.value.origin;
}
get protocol() {
return this.value.protocol;
}
get username() {
return this.value.username;
}
get password() {
return this.value.password;
}
get hostname() {
return this.value.hostname;
}
get host() {
return this.value.host;
}
get port() {
return this.value.port;
}
get pathname() {
return this.value.pathname;
}
/** Get the URL params as a string. */
get search() {
return this.value.search;
}
/** Get the URL params as a dictionary. */
get params() {
return getURIParams(this.value.searchParams, getGetter(this, "params"));
}
/** Return a single param in this URL, or `undefined` if it could not be found. */
getParam(key) {
return getURIParam(this.value.searchParams, key);
}
/** Require a single param in this URL, or throw `RequiredError` if it could not be found. */
requireParam(key) {
return requireURIParam(this.value.searchParams, key, getSetter(this, "requireParam"));
}
/** Set all params in this URL (all current params are cleared). */
setParams(params) {
this.value = withURIParams(clearURIParams(this.value, this.setParams), params, this.setParams);
}
/** Set a single named param in this URL. */
setParam(key, value) {
this.value = withURIParam(this.value, key, value, this.setParam);
}
/** Update several params in this URL (merged with current params). */
updateParams(params) {
this.value = withURIParams(this.value, params, this.updateParams);
}
/** Delete one or more params in this URL. */
deleteParam(key, ...keys) {
this.value = omitURIParams(this.value, key, ...keys);
}
/** Delete one or more params in this URL. */
deleteParams(key, ...keys) {
this.value = omitURIParams(this.value, key, ...keys);
}
/** Clear all params from this URL. */
clearParams() {
this.value = clearURIParams(this.value, this.clearParams);
}
/** Return the current URL with an additional param. */
withParam(key, value) {
return withURIParam(this.value, key, value, this.withParam);
}
/** Return the current URL with an additional param. */
withParams(params) {
return withURIParams(this.value, params, this.withParams);
}
/** Return the current URL with an additional param. */
omitParams(...keys) {
return omitURIParams(this.value, ...keys);
}
/** Return the current URL with an additional param. */
omitParam(key) {
return omitURIParams(this.value, key);
}
/**
* Is `target` active relative to this store's URL?
* - Active means `target` resolves to the exact same URL as this store's current value.
*
* @param target URL (or relative path resolved against this store's `base`) to test.
*/
isActive(target) {
return isURLActive(this.value, requireURL(target, this.base, this.isActive));
}
/**
* Is `target` proud relative to this store's URL?
* - Proud means this store's URL is `target` or a descendant of `target` — i.e. `target` sits at or above the current URL in the hierarchy.
* - Useful for marking a menu item as "current branch" when the user is somewhere deeper in its sub-tree.
*
* @param target URL (or relative path resolved against this store's `base`) to test.
*/
isProud(target) {
return isURLProud(this.value, requireURL(target, this.base, this.isProud));
}
toString() {
return this.href;
}
}