moeralib
Version:
Library to interact with Moera decentralized social network
244 lines (243 loc) • 7.25 kB
JavaScript
"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;