uri.js

/**
 *@module Uri
*/

/**
 * @typedef {object} UriObj
 * @property {string} scheme
 * @property {string} host
 * @property {string} port
 * @property {string} userInfo
 * @property {string} authority
 * @property {string} path
 * @property {string} query
 * @property {string} fragment
*/

const isEqualWith = require('lodash.isequalwith');
const querystring = require('querystring');
const uri = require('./_uri');
let CTX = '';
let SVC_CTX_PREFIX = '';
let UI_CTX_PREFIX = '';
// eslint-disable-next-line no-undef
const DEFAULT_THAT = typeof window != 'undefined' ? window.document.URL : /* istanbul ignore next */ '';

// function fromWindow(){} NOT PORTED
// function navigate(){} NOT PORTED

function config(conf) {
    // NTH: assert not null, or fallback from CTX to others..
    ({ CTX, UI_CTX_PREFIX, SVC_CTX_PREFIX } = conf);
}

// paramString window.document.URL instead use '' (or try use '/', or...)
function equalsQueryStr(query1, query2) {
    function simpleCompare(a, b) {
        return (a < b ? -1 : (a > b ? 1 : 0));
    }

    function customizer(a, b) {
        if (a instanceof Array && b instanceof Array) {
            // order is not important, so just sort them before comparing
            a.sort(simpleCompare);
            b.sort(simpleCompare);
        }
        return undefined; // isEqualWith will do the job if we return undef
    }

    if (!query1 || !query2) {
        return query1 === query2;
    }
    const q1 = uri.parseQuery(query1);
    const q2 = uri.parseQuery(query2);

    return isEqualWith(q1, q2, customizer);
}

function clone(uriArr) {
    return Object.assign({}, uriArr);
}

function param(that) {
    that != null || (that = DEFAULT_THAT); // let '' continue
    return (typeof that == 'string') ? uri.decomposeComponents(that) : clone(that);
}
function _resolve(base, ref) {
    // less strict version of uri.resolve, scheme is not required
    const scheme = base.scheme;
    if (!scheme) {
        base.scheme = 'http';
    }
    const s = uri.resolve(base, ref);
    if (!scheme) {
        delete s.scheme;
    }
    return s;
}

/**
* @summary Use to set multiple URI parts at once.
* @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
* @param {UriObj} obj Available properties: `scheme`, `authority`, `userInfo`, `host`, `port`, `path`, `query`, `fragment`.
* @memberof module:Uri
* @returns {string} Modified copy of `that`.
*/
function mixin(that, { authority, userInfo, host, port, scheme, path, query, fragment }) {
    const u = param(that);

    /* 'app/_base/rql' */
    if (authority !== undefined) {
        u.authority = authority;
        if (u.authority) {
            ({ userInfo, host, port } = uri.decomposeComponents(`//${u.authority}`));
            Object.assign(u, { userInfo, host, port });
        } else {
            u.userInfo = u.host = u.port = undefined;
        }
    } else {
        userInfo && (u.userInfo = userInfo);
        host && (u.host = host);
        port && (u.port = port);
        u.host && (u.authority = uri.recomposeAuthorityComponents(u.userInfo, u.host, u.port));
    }
    scheme && (u.scheme = scheme);
    path && (u.path = path);
    query && (u.query = query && typeof query != 'string' ? querystring.stringify(query) : query);
    fragment && (u.fragment = fragment && typeof fragment != 'string' ? querystring.stringify(fragment) : fragment);
    return uri.recomposeComponents(u);
}

function isSubPath(baseStr, refStr) {
    const bs = uri.decodeSegments(baseStr);
    const rs = uri.decodeSegments(refStr);
    if (bs.length > rs.length) {
        return false;
    }
    if (bs[bs.length - 1] === '') { // dont compare with void segment
        bs.pop();
    }
    return bs.reverse().every((item, i) => item === rs[bs.length - 1 - i]);
}

function paramString(that) {
    that != null || (that = DEFAULT_THAT);
    return (typeof that === 'string') ? that : uri.recomposeComponents(that);
}

function contains(arr, what) {
    return arr.indexOf(what) !== -1;
}

/**
 * @summary Use to convert uri object to string.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} URI string.
 */
function toString(that) {
    return paramString(that);
}

/**
 * @summary Use to convert uri to uri object.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {UriObj} URI object with properties: `scheme`, `authority`, `userInfo`, `host`, `port`, `path`, `query`, `fragment`.
 */
function toUri(that) {
    return param(that);
}

/**
 * @summary Use to strip some parts of URI.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} toStrip Comma separated values, available are: 'ORIGIN', 'CTX', 'EXTENSION', 'QUERY', 'FRAGMENT'.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 * @example Uri.strip(uriStr, 'QUERY,FRAGMENT');
 */
function strip(that, toStrip) {
    let { scheme, authority, host, port, userInfo, path, query, fragment } = param(that);

    toStrip = toStrip.split(',');

    if (contains(toStrip, 'ORIGIN')) {
        // clear them all to keep object consistent for auth invariant
        scheme = authority = host = port = userInfo = undefined; // orig uses undefined not nulls
    }
    if (contains(toStrip, 'PATH')) {
        path = ''; // dont use undefined, resulting path should be empty ('/')
    } else {
        if (contains(toStrip, 'CTX')) {
            if (!isSubPath(CTX, path)) {
                throw new Error('IllegalArgument, context not present');
            }
            path = path.substring(CTX.length);
        } else if (contains(toStrip, 'CTX_PREFIX')) {
            if (isSubPath(UI_CTX_PREFIX, path)) {
                path = path.substring(UI_CTX_PREFIX.length);
            } else if (isSubPath(SVC_CTX_PREFIX, path)) {
                path = path.substring(SVC_CTX_PREFIX.length);
            } else {
                throw new Error('IllegalArgument, context prefix not present');
            }
        }
        if (contains(toStrip, 'EXTENSION')) {
            const segments = uri.decodeSegments(path);
            const l = segments.length;
            if (l) {
                const last = segments[l - 1];
                const dotIndex = last.indexOf('.');
                if (dotIndex !== -1) {
                    segments[l - 1] = last.substring(0, dotIndex);
                    path = uri.encodeSegments(segments);
                }
            }
        }
    }
    if (contains(toStrip, 'QUERY')) {
        query = undefined;
    }
    if (contains(toStrip, 'FRAGMENT')) {
        fragment = undefined;
    }
    return uri.recomposeComponents({ scheme, authority, host, port, userInfo, path, query, fragment });
}

/**
 * @summary Use to test if URIs are equal. Order of query params is ignored.
 * @param {string|UriObj|null} that1 URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj|null} that2 URI string or URI object. Current window URI used when null or undefined.
 * @param {boolean} ignoreFragment When true, fragment (hash) is ignored when determining equality.\
 * @memberof module:Uri
 * @returns {boolean} True if URIs are equal, false otherwise.
 */
function equals(that1, that2, ignoreFragment) {
    const { scheme, authority, path, query, fragment } = param(that1);
    const { scheme: scheme2, authority: authority2, path: path2, query: query2, fragment: fragment2 } = param(that2);

    return scheme === scheme2 && // return Boolean
        authority === authority2 && path === path2 && this.equalsQueryStr(query, query2) &&
        (ignoreFragment || fragment === fragment2);
}

// basic getters
/**
 * @summary Use instead of location.protocol
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined} String without ':' delimiter.
 */
function getScheme(that) {
    const { scheme } = param(that);
    return scheme;
}

/**
 * @summary Use instead of location.host.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined}
 */
function getAuthority(that) {
    const { authority } = param(that);
    return authority;
}

/**
 * @summary Use to get user info. No equivalent in location.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined}
 */
function getUserInfo(that) {
    const { userInfo } = param(that);
    return userInfo;
}

/**
 * @summary Use instead of location.hostname.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined}
 */
function getHost(that) {
    const { host } = param(that);
    return host;
}

/**
 * @summary Use instead of location.port.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined}
 */
function getPort(that) {
    const { port } = param(that);
    return port;
}

/**
 * @summary Use instead of location.search.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined} String starting by '/'.
 */
function getPath(that) {
    const { path } = param(that);
    return path;
}

/**
 * @summary Use instead of location.search.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {boolean} toObject If `true` query is returned as object.
 * @memberof module:Uri
 * @returns {string|UriObj|undefined} String without '?' delimiter or key-value object.
 */
function getQuery(that, toObject) {
    const { query } = param(that);

    if (toObject) {
        return query === undefined ? undefined : //
            uri.parseQuery(query, true); // '' -> {}
    }
    return query; // 1:1 with small uri.js, undefined, '' or string
}

/**
 * @summary Use instead of location.hash.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string|undefined} String without '#' delimiter.
 */
function getFragment(that) {
    const { fragment } = param(that);
    // NTH: implement toObject
    //			if (toObject && u.fragment != null) {
    //				return ioQuery.queryToObject(u.fragment) || u.fragment;
    //			}
    return fragment;
}

/**
 * @summary Use to get path segments.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {Array<string>} Array of strings, last is '' if path denotes a folder.
 */
function getSegments(that) {
    const { path } = param(that);
    return uri.decodeSegments(path);
}

// basic setters
/**
 * @summary Use to set scheme.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} scheme Scheme.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setScheme(that, scheme) {
    const u = param(that);

    return uri.recomposeComponents({
        ...u,
        scheme
    });
}

/**
 * @summary Use to set authority.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} authority Authority.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setAuthority(that, authority) {
    const u = param(that);

    u.authority = authority;
    if (authority) {
        // NTH: uri.decomposeAuthorityComponents function
        const { userInfo, host, port } = uri.decomposeComponents(`//${authority}`);
        Object.assign(u, { userInfo, host, port });
    } else {
        u.userInfo = u.host = u.port = undefined;
    }
    return uri.recomposeComponents(u);
}

/**
 * @summary Use to set user info.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} userInfo User info.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setUserInfo(that, userInfo) {
    const u = param(that);

    return uri.recomposeComponents({
        ...u,
        userInfo,
        authority: uri.recomposeAuthorityComponents(userInfo, u.host, u.port)
    });
}

/**
 * @summary Use to set host.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} host Host.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setHost(that, host) {
    const u = param(that);
    return uri.recomposeComponents({
        ...u,
        host,
        authority: uri.recomposeAuthorityComponents(u.userInfo, host, u.port)
    });
}

/**
 * @summary Use to set port.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} port Port.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setPort(that, port) {
    const u = param(that);
    return uri.recomposeComponents({
        ...u,
        port,
        authority: uri.recomposeAuthorityComponents(u.userInfo, u.host, port)
    });
}

/**
 * @summary Use to set path.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string} path Encoded path.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setPath(that, path) {
    const u = param(that);
    uri.checkSegmentsEncoding(path, true); // throws error is unencoded

    return uri.recomposeComponents({
        ...u,
        path
    });
}

/**
 * @summary Use to set query.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj} query Encoded string or unencoded key-value object.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setQuery(that, query) {
    const u = param(that);
    query && typeof query != 'string' && (query = querystring.stringify(query));
    uri.checkQueryEncoding(query, true); // throws error is unencoded
    u.query = query;
    return uri.recomposeComponents(u);
}

/**
 * @summary Use to append query.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj} query Encoded string or unencoded key-value object.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function appendQuery(that, query) {
    if (!query) {
        return paramString(that);
    }
    const origQuery = this.getQuery(that);
    typeof query != 'string' && (query = querystring.stringify(query));
    return this.setQuery(that, `${origQuery ? `${origQuery}&` : ''}${query}`);
}

/**
 * @summary Use to set fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj} fragment Encoded string or key-value object.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setFragment(that, fragment) {
    const u = param(that);
    fragment && typeof fragment != 'string' && (fragment = querystring.stringify(fragment));
    uri.checkFragmentEncoding(fragment, true); // throws error is unencoded
    u.fragment = fragment;
    return uri.recomposeComponents(u);
}

/**
 * @summary Use to append fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj} fragment Encoded string or key-value object.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function appendFragment(that, fragment) {
    if (!fragment) {
        return paramString(that);
    }
    const origFragment = this.getFragment(that);
    typeof fragment != 'string' && (fragment = querystring.stringify(fragment));
    return this.setFragment(that, `${origFragment ? `${origFragment}&` : ''}${fragment}`); // return String
}

/**
 * @summary Use to set segments.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {Array<string>} segments Array of unencoded path segments.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function setSegments(that, segments) {
    return this.setPath(that, uri.encodeSegments(segments));
}

/**
 * @summary Use to append path segments.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @param {Array<string>|string} segments Array or multiple arguments of unencoded path segments.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function appendSegments(that, ...appendSegmets) {
    (Array.isArray(appendSegmets[0])) && (appendSegmets = appendSegmets[0]);
    if (!appendSegmets.length) {
        throw new Error('IllegalArgument, segments argument not present');
    }
    const segments = this.getSegments(that);
    !segments[segments.length - 1] && segments.pop(); // isLastSegmentEmpty
    return this.setSegments(that, segments.concat(appendSegmets));
}

// stripping specific parts of URI
/**
 * @summary Use to get path with query and fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripOrigin(that) {
    return this.strip(that, 'ORIGIN');
}

/**
 * @summary Use to get uri without path extension.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 * @example Uri.stripExtension('/samples/ui/test/aam-test.standalone'); // '/samples/ui/test/aam-test'
 */
function stripExtension(that) {
    return this.strip(that, 'EXTENSION');
}

/**
 * @summary Use to get path after context with query and fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripCtxPath(that) {
    return this.strip(that, 'ORIGIN,CTX');
}

/**
 * @summary Use to get path after context prefix (UI or svc) with query and fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripCtxPrefix(that) {
    return this.strip(that, 'ORIGIN,CTX_PREFIX');
}

/**
 * @summary Use to get origin, i.e. everything before path.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripPath(that) {
    return this.strip(that, 'PATH,QUERY,FRAGMENT');
}

/**
 * @summary Use to get URI without query.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripQuery(that) {
    return this.strip(that, 'QUERY');
}

/**
 * @summary Use to get URI without fragment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function stripFragment(that) {
    return this.strip(that, 'FRAGMENT');
}

/**
 * @summary Use to get path after context and before extension.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function getScreenPath(that) {
    return this.strip(that, 'ORIGIN,CTX,EXTENSION,QUERY,FRAGMENT');
}

/**
 * @summary Use to get the last path segment.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Empty string when `that` denotes folder, `undefined` if path is empty.
 */
function getLastSegment(that) {
    const { path } = param(that);
    return uri.decodeSegments(path).pop();
}

// NTH: getLastNonVoidSegment ???
/**
 * @summary Use to test if path ends with '/'.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {boolean}
 */
function denotesFolder(that) {
    // will be string so this should be enough
    return this.getLastSegment(that) === '';
}

/**
 * @summary Use to convert URI path to folder.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that` ending with '/'.
 * @example Uri.convertToFolder('/samples/ui/test/aam-test');	// 	'/samples/ui/test/'
 */
function convertToFolder(that) {
    let { path, ...others } = param(that);
    const segments = uri.decodeSegments(path);
    if (segments.length) {
        segments[segments.length - 1] = '';
    } else {
        segments.push('');
    }
    path = uri.encodeSegments(segments);
    return uri.recomposeComponents({ path, ...others });
}

/**
 * @summary Use to test if ref URI is subordiante of base URI.
 * @param {string|UriObj|null} that Base URI. URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj|null} ref Ref URI. URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {boolean} True if `ref` is subordinate of `base`.
 */
function isSubordinate(that, ref) {
    return uri.isSubordinate(param(that), param(ref), true);
}

/**
 * @summary Use to resolve ref URI using base URI.
 * @param {string|UriObj|null} that Base URI. URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj|null} ref Ref URI. URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function resolve(that, ref) {
    const s = _resolve(param(that), param(ref));
    return uri.recomposeComponents(s);
}

/**
 * @summary Use to resolve ref URI as subordinate of base URI.
 * @param {string|UriObj|null} that Base URI. URI string or URI object. Current window URI used when null or undefined.
 * @param {string|UriObj|null} ref Ref URI. URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string} Modified copy of `that`.
 */
function resolveAsSubordinate(that, ref) {
    const u = param(convertToFolder(that));
    const s = _resolve(u, param(ref));
    if (!isSubordinate(u, s)) {
        throw new Error('IllegalArgument, not subordinate');
    }
    return uri.recomposeComponents(s);
}

/**
 * @summary Use to retrieve resource id from RESTful URI.
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {number} Id.
 */
function parseId(that) {
    const id = parseInt(getLastSegment(that), 10);
    if (isNaN(id)) {
        throw new Error('IllegalArgument, numeric id not present');
    }
    return id;
}

function prependCtxPrefix(that, prefix) {
    const u = param(that);
    if (u.authority || u.scheme) {
        throw new Error('IllegalArgument, origin not expected');
    }
    const segments = uri.decodeSegments(u.path);
    const ctxSegments = uri.decodeSegments(prefix);
    const hasPrefix = ctxSegments.every((seg, i) => segments[i] === seg);
    if (!hasPrefix) {
        u.path = uri.encodeSegments(ctxSegments.concat(segments));
    }
    return uri.recomposeComponents(u);
}

/**
 * @summary Prepends SVC CTX PREFIX
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string}
 */
function resolveSvcCtx(that) {
    if (!SVC_CTX_PREFIX) {
        throw new Error('SVC_CTX_PREFIX is not defined, use config() before calling resolveSvcCtx');
    }
    return prependCtxPrefix(that, SVC_CTX_PREFIX);
}

/**
 * @summary Prepends SVC CTX PREFIX
 * @param {string|UriObj|null} that URI string or URI object. Current window URI used when null or undefined.
 * @memberof module:Uri
 * @returns {string}
 */
function resolveUiCtx(that) {
    if (!UI_CTX_PREFIX) {
        throw new Error('UI_CTX_PREFIX is not defined, use config() before calling resolveSvcCtx');
    }
    return prependCtxPrefix(that, UI_CTX_PREFIX);
}

module.exports = {
    appendFragment,
    appendQuery,
    appendSegments,
    config,
    convertToFolder,
    denotesFolder,
    equals,
    equalsQueryStr,
    getAuthority,
    getFragment,
    getHost,
    getLastSegment,
    getPath,
    getPort,
    getQuery,
    getScheme,
    getScreenPath,
    getSegments,
    getUserInfo,
    mixin,
    parseId,
    resolve,
    resolveAsSubordinate,
    resolveSvcCtx,
    resolveUiCtx,
    setAuthority,
    setFragment,
    setHost,
    setPath,
    setPort,
    setQuery,
    setScheme,
    setSegments,
    setUserInfo,
    strip,
    stripCtxPath,
    stripCtxPrefix,
    stripExtension,
    stripFragment,
    stripOrigin,
    stripPath,
    stripQuery,
    toString,
    toUri
};