UNPKG

neo4j-driver-core

Version:
297 lines (296 loc) 10.5 kB
"use strict"; /** * Copyright (c) "Neo4j" * Neo4j Sweden AB [https://neo4j.com] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Url = exports.formatIPv6Address = exports.formatIPv4Address = exports.defaultPortForScheme = exports.parseDatabaseUrl = void 0; var util_1 = require("./util"); var DEFAULT_BOLT_PORT = 7687; var DEFAULT_HTTP_PORT = 7474; var DEFAULT_HTTPS_PORT = 7473; var Url = /** @class */ (function () { function Url(scheme, host, port, hostAndPort, query) { /** * Nullable scheme (protocol) of the URL. * Example: 'bolt', 'neo4j', 'http', 'https', etc. * @type {string} */ this.scheme = scheme; /** * Nonnull host name or IP address. IPv6 not wrapped in square brackets. * Example: 'neo4j.com', 'localhost', '127.0.0.1', '192.168.10.15', '::1', '2001:4860:4860::8844', etc. * @type {string} */ this.host = host; /** * Nonnull number representing port. Default port for the given scheme is used if given URL string * does not contain port. Example: 7687 for bolt, 7474 for HTTP and 7473 for HTTPS. * @type {number} */ this.port = port; /** * Nonnull host name or IP address plus port, separated by ':'. IPv6 wrapped in square brackets. * Example: 'neo4j.com', 'neo4j.com:7687', '127.0.0.1', '127.0.0.1:8080', '[2001:4860:4860::8844]', * '[2001:4860:4860::8844]:9090', etc. * @type {string} */ this.hostAndPort = hostAndPort; /** * Nonnull object representing parsed query string key-value pairs. Duplicated keys not supported. * Example: '{}', '{'key1': 'value1', 'key2': 'value2'}', etc. * @type {Object} */ this.query = query; } return Url; }()); exports.Url = Url; function parseDatabaseUrl(url) { var _a; (0, util_1.assertString)(url, 'URL'); var sanitized = sanitizeUrl(url); var parsedUrl = uriJsParse(sanitized.url); var scheme = sanitized.schemeMissing ? null : extractScheme(parsedUrl.scheme); var host = extractHost(parsedUrl.host); // no square brackets for IPv6 var formattedHost = formatHost(host); // has square brackets for IPv6 var port = extractPort(parsedUrl.port, scheme); var hostAndPort = "".concat(formattedHost, ":").concat(port); var query = extractQuery( // @ts-expect-error (_a = parsedUrl.query) !== null && _a !== void 0 ? _a : extractResourceQueryString(parsedUrl.resourceName), url); return new Url(scheme, host, port, hostAndPort, query); } exports.parseDatabaseUrl = parseDatabaseUrl; function extractResourceQueryString(resource) { if (typeof resource !== 'string') { return null; } var _a = __read(resource.split('?'), 2), query = _a[1]; return query; } function sanitizeUrl(url) { url = url.trim(); if (!url.includes('://')) { // url does not contain scheme, add dummy 'none://' to make parser work correctly return { schemeMissing: true, url: "none://".concat(url) }; } return { schemeMissing: false, url: url }; } function extractScheme(scheme) { if (scheme != null) { scheme = scheme.trim(); if (scheme.charAt(scheme.length - 1) === ':') { scheme = scheme.substring(0, scheme.length - 1); } return scheme; } return null; } function extractHost(host, url) { if (host == null) { throw new Error('Unable to extract host from null or undefined URL'); } return host.trim(); } function extractPort(portString, scheme) { var port = typeof portString === 'string' ? parseInt(portString, 10) : portString; return port != null && !isNaN(port) ? port : defaultPortForScheme(scheme); } function extractQuery(queryString, url) { var query = queryString != null ? trimAndSanitizeQuery(queryString) : null; var context = {}; if (query != null) { query.split('&').forEach(function (pair) { var keyValue = pair.split('='); if (keyValue.length !== 2) { throw new Error("Invalid parameters: '".concat(keyValue.toString(), "' in URL '").concat(url, "'.")); } var key = trimAndVerifyQueryElement(keyValue[0], 'key', url); var value = trimAndVerifyQueryElement(keyValue[1], 'value', url); if (context[key] !== undefined) { throw new Error("Duplicated query parameters with key '".concat(key, "' in URL '").concat(url, "'")); } context[key] = value; }); } return context; } function trimAndSanitizeQuery(query) { query = (query !== null && query !== void 0 ? query : '').trim(); if ((query === null || query === void 0 ? void 0 : query.charAt(0)) === '?') { query = query.substring(1, query.length); } return query; } function trimAndVerifyQueryElement(element, name, url) { element = (element !== null && element !== void 0 ? element : '').trim(); if (element === '') { throw new Error("Illegal empty ".concat(name, " in URL query '").concat(url, "'")); } return element; } function escapeIPv6Address(address) { var startsWithSquareBracket = address.charAt(0) === '['; var endsWithSquareBracket = address.charAt(address.length - 1) === ']'; if (!startsWithSquareBracket && !endsWithSquareBracket) { return "[".concat(address, "]"); } else if (startsWithSquareBracket && endsWithSquareBracket) { return address; } else { throw new Error("Illegal IPv6 address ".concat(address)); } } function formatHost(host) { if (host === '' || host == null) { throw new Error("Illegal host ".concat(host)); } var isIPv6Address = host.includes(':'); return isIPv6Address ? escapeIPv6Address(host) : host; } function formatIPv4Address(address, port) { return "".concat(address, ":").concat(port); } exports.formatIPv4Address = formatIPv4Address; function formatIPv6Address(address, port) { var escapedAddress = escapeIPv6Address(address); return "".concat(escapedAddress, ":").concat(port); } exports.formatIPv6Address = formatIPv6Address; function defaultPortForScheme(scheme) { if (scheme === 'http') { return DEFAULT_HTTP_PORT; } else if (scheme === 'https') { return DEFAULT_HTTPS_PORT; } else { return DEFAULT_BOLT_PORT; } } exports.defaultPortForScheme = defaultPortForScheme; function uriJsParse(value) { // JS version of Python partition function function partition(s, delimiter) { var i = s.indexOf(delimiter); if (i >= 0) return [s.substring(0, i), s[i], s.substring(i + 1)]; else return [s, '', '']; } // JS version of Python rpartition function function rpartition(s, delimiter) { var i = s.lastIndexOf(delimiter); if (i >= 0) return [s.substring(0, i), s[i], s.substring(i + 1)]; else return ['', '', s]; } function between(s, ldelimiter, rdelimiter) { var lpartition = partition(s, ldelimiter); var rpartition = partition(lpartition[2], rdelimiter); return [rpartition[0], rpartition[2]]; } // Parse an authority string into an object // with the following keys: // - userInfo (optional, might contain both user name and password) // - host // - port (optional, included only as a string) function parseAuthority(value) { var parsed = {}; var parts; // Parse user info parts = rpartition(value, '@'); if (parts[1] === '@') { parsed.userInfo = decodeURIComponent(parts[0]); value = parts[2]; } // Parse host and port var _a = __read(between(value, '[', ']'), 2), ipv6Host = _a[0], rest = _a[1]; if (ipv6Host !== '') { parsed.host = ipv6Host; parts = partition(rest, ':'); } else { parts = partition(value, ':'); parsed.host = parts[0]; } if (parts[1] === ':') { parsed.port = parts[2]; } return parsed; } var parsed = {}; var parts; // Parse scheme parts = partition(value, ':'); if (parts[1] === ':') { parsed.scheme = decodeURIComponent(parts[0]); value = parts[2]; } // Parse fragment parts = partition(value, '#'); if (parts[1] === '#') { parsed.fragment = decodeURIComponent(parts[2]); value = parts[0]; } // Parse query parts = partition(value, '?'); if (parts[1] === '?') { parsed.query = parts[2]; value = parts[0]; } // Parse authority and path if (value.startsWith('//')) { parts = partition(value.substr(2), '/'); parsed = __assign(__assign({}, parsed), parseAuthority(parts[0])); parsed.path = parts[1] + parts[2]; } else { parsed.path = value; } return parsed; }