UNPKG

moeralib

Version:

Library to interact with Moera decentralized social network

244 lines (243 loc) 7.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.redirectTo = exports.redirectToUrl = exports.parse = exports.REDIRECTOR = void 0; const url_1 = require("url"); const naming_1 = require("./naming"); exports.REDIRECTOR = "moera.page"; /** * Represents location part of a universal Moera URL. */ class UniversalLocation { /** * @param {string | null} nodeName - the node name * @param {string | null} scheme - scheme specifier of the node location (``'https'``, if set to `null` or empty) * @param {string | null} authority - authority (host name and optional port) of the node location * @param {string | null} path - virtual path at the node (``'/'``, if set to `null` or empty) * @param {string | null} query - query component of the URL (without ``?``) * @param {string | null} fragment - fragment identifier of the URL (without ``#``) */ constructor(nodeName = null, scheme = null, authority = null, path = null, query = null, fragment = null) { this._nodeName = null; this._scheme = "https"; this._authority = null; this._path = null; this.nodeName = nodeName; this.scheme = scheme; this.authority = authority; this.path = path; this.query = query; this.fragment = fragment; } /** * The node name. * * @return {string | null} */ get nodeName() { return this._nodeName; } /** * The node name. * * @param {string | null} nodeName */ set nodeName(nodeName) { this._nodeName = (0, naming_1.shorten)(nodeName); } /** * Scheme specifier of the node location. * * @return {string | null} */ get scheme() { return this._scheme; } /** * Scheme specifier of the node location. * * @param {string | null} scheme */ set scheme(scheme) { this._scheme = scheme || "https"; } /** * Authority (host name and optional port) of the node location. * * @return {string | null} */ get authority() { return this._authority; } /** * Authority (host name and optional port) of the node location. * * @param {string | null} authority */ set authority(authority) { this._authority = authority || null; } /** * Virtual path at the node. * * @return {string | null} */ get path() { return this._path; } /** * Virtual path at the node. * * @param {string | null} path */ set path(path) { if (path === null || path === void 0 ? void 0 : path.startsWith("/moera")) { path = path.substring(6); } this._path = path || "/"; } /** * Universal Moera location (without query and fragment). * * @return {string | null} */ get location() { let loc = "/@"; if (this._nodeName != null) { loc += encodeURIComponent(this._nodeName); } loc += "/"; if (this._authority != null) { if (this._scheme != null && this._scheme.toLowerCase() !== "https") { loc += this._scheme + ":"; } loc += this._authority; } else { loc += "~"; } loc += this._path; return loc; } toString() { let url = this.location; if (this.query != null) { url += "?" + this.query; } if (this.fragment != null) { url += "#" + this.fragment; } return url; } } function stripFirst(s) { return s != null && s.length > 1 ? s.substring(1) : null; } /** * Parse the location part (including query and fragment) of a universal URL. * * @param {string | null} url - the URL to be parsed * @return {UniversalLocation} the parsed location */ function parse(url) { if (url == null) { return new UniversalLocation(); } const parts = new url_1.URL(url); let path = parts.pathname.replace(/^\/|\/$/g, ""); if (path === "") { return new UniversalLocation(); } const dirs = path.split("/"); if (!dirs[0].startsWith('@')) { return new UniversalLocation(); } let nodeName = null; if (dirs[0].length > 1) { nodeName = decodeURIComponent(dirs[0].substring(1)); } let scheme = null; let authority = null; let host = null; let port = null; if (dirs.length > 1 && dirs[1] !== "~") { const parts = dirs[1].split(":"); let i = 0; if (!parts[i].includes(".")) { scheme = parts[i]; i++; } if (i < parts.length) { host = parts[i]; i++; } if (i < parts.length) { port = parts[i]; } } if (host) { authority = host; if (port) { authority += ":" + port; } } path = ""; dirs.slice(2).forEach(dir => path += `/${dir}`); if (path === "") { path = "/"; } const query = stripFirst(parts.search); const fragment = stripFirst(parts.hash); return new UniversalLocation(nodeName, scheme, authority, path, query, fragment); } exports.parse = parse; /** * Build a universal Moera URL from the direct URL of a page on a node, adding the node name provided. * * @param {string | null} nodeName - the node name * @param {string | null} url - the direct URL * @return {string} the universal URL */ function redirectToUrl(nodeName, url = null) { try { let uni; if (url != null) { const parts = new url_1.URL(url); uni = new UniversalLocation(nodeName, parts.protocol.slice(0, -1), parts.host, parts.pathname, stripFirst(parts.search), stripFirst(parts.hash)); } else { uni = new UniversalLocation(nodeName); } return `https://${exports.REDIRECTOR}${uni}`; } catch (e) { return `https://${exports.REDIRECTOR}`; } } exports.redirectToUrl = redirectToUrl; /** * Build a universal Moera URL from the node name, the Moera root URL of the node, virtual path and other components. * * @param {string | null} nodeName - the node name * @param {string | null} rootUrl - the Moera root URL of the node * @param {string | null} path - virtual path at the node (``'/'``, if set to `null` or empty) * @param {string | null} query - query component of the URL * @param {string | null} fragment - fragment identifier of the URL * @return {string} the universal URL */ function redirectTo(nodeName, rootUrl, path = null, query = null, fragment = null) { try { let uni; if (rootUrl != null) { const parts = new url_1.URL(rootUrl); uni = new UniversalLocation(nodeName, parts.protocol.slice(0, -1), parts.host, path, query, fragment); } else { uni = new UniversalLocation(nodeName, null, null, path, query, fragment); } return `https://${exports.REDIRECTOR}${uni}`; } catch (error) { return `https://${exports.REDIRECTOR}`; } } exports.redirectTo = redirectTo;