diff --git a/CHANGELOG.md b/CHANGELOG.md index 5078e3e..cc27b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.4.0] - 2020-11-06 ### Added - Custom request handler for DNS service provider +- Docs ### Changed - Service provider data structure diff --git a/dist/doip.js b/dist/doip.js index a99afc4..665bc76 100644 --- a/dist/doip.js +++ b/dist/doip.js @@ -132,842 +132,191 @@ module.exports = mkrequest => (...args) => { },{}],3:[function(require,module,exports){ },{}],4:[function(require,module,exports){ -(function (process){(function (){ -/* @flow */ -/*:: - -type DotenvParseOptions = { - debug?: boolean -} - -// keys and values from src -type DotenvParseOutput = { [string]: string } - -type DotenvConfigOptions = { - path?: string, // path to .env file - encoding?: string, // encoding of .env file - debug?: string // turn on logging for debugging purposes -} - -type DotenvConfigOutput = { - parsed?: DotenvParseOutput, - error?: Error -} - -*/ - -const fs = require('fs') -const path = require('path') - -function log (message /*: string */) { - console.log(`[dotenv][DEBUG] ${message}`) -} - -const NEWLINE = '\n' -const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/ -const RE_NEWLINES = /\\n/g -const NEWLINES_MATCH = /\n|\r|\r\n/ - -// Parses src into an Object -function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ { - const debug = Boolean(options && options.debug) - const obj = {} - - // convert Buffers before splitting into lines and processing - src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) { - // matching "KEY' and 'VAL' in 'KEY=VAL' - const keyValueArr = line.match(RE_INI_KEY_VAL) - // matched? - if (keyValueArr != null) { - const key = keyValueArr[1] - // default undefined or missing values to empty string - let val = (keyValueArr[2] || '') - const end = val.length - 1 - const isDoubleQuoted = val[0] === '"' && val[end] === '"' - const isSingleQuoted = val[0] === "'" && val[end] === "'" - - // if single or double quoted, remove quotes - if (isSingleQuoted || isDoubleQuoted) { - val = val.substring(1, end) - - // if double quoted, expand newlines - if (isDoubleQuoted) { - val = val.replace(RE_NEWLINES, NEWLINE) - } - } else { - // remove surrounding whitespace - val = val.trim() - } - - obj[key] = val - } else if (debug) { - log(`did not match key and value when parsing line ${idx + 1}: ${line}`) - } - }) - - return obj -} - -// Populates process.env from .env file -function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ { - let dotenvPath = path.resolve(process.cwd(), '.env') - let encoding /*: string */ = 'utf8' - let debug = false - - if (options) { - if (options.path != null) { - dotenvPath = options.path - } - if (options.encoding != null) { - encoding = options.encoding - } - if (options.debug != null) { - debug = true - } - } - - try { - // specifying an encoding returns a string instead of a buffer - const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug }) - - Object.keys(parsed).forEach(function (key) { - if (!Object.prototype.hasOwnProperty.call(process.env, key)) { - process.env[key] = parsed[key] - } else if (debug) { - log(`"${key}" is already defined in \`process.env\` and will not be overwritten`) - } - }) - - return { parsed } - } catch (e) { - return { error: e } - } -} - -module.exports.config = config -module.exports.parse = parse - -}).call(this)}).call(this,require('_process')) -},{"_process":6,"fs":3,"path":5}],5:[function(require,module,exports){ -(function (process){(function (){ -// 'path' module extracted from Node.js v8.11.1 (only the posix part) -// transplited with Babel - -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - 'use strict'; -function assertPath(path) { - if (typeof path !== 'string') { - throw new TypeError('Path must be a string. Received ' + JSON.stringify(path)); - } -} +module.exports = value => { + if (Object.prototype.toString.call(value) !== '[object Object]') { + return false; + } -// Resolves . and .. elements in a path with directory names -function normalizeStringPosix(path, allowAboveRoot) { - var res = ''; - var lastSegmentLength = 0; - var lastSlash = -1; - var dots = 0; - var code; - for (var i = 0; i <= path.length; ++i) { - if (i < path.length) - code = path.charCodeAt(i); - else if (code === 47 /*/*/) - break; - else - code = 47 /*/*/; - if (code === 47 /*/*/) { - if (lastSlash === i - 1 || dots === 1) { - // NOOP - } else if (lastSlash !== i - 1 && dots === 2) { - if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) { - if (res.length > 2) { - var lastSlashIndex = res.lastIndexOf('/'); - if (lastSlashIndex !== res.length - 1) { - if (lastSlashIndex === -1) { - res = ''; - lastSegmentLength = 0; - } else { - res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); - } - lastSlash = i; - dots = 0; - continue; - } - } else if (res.length === 2 || res.length === 1) { - res = ''; - lastSegmentLength = 0; - lastSlash = i; - dots = 0; - continue; - } - } - if (allowAboveRoot) { - if (res.length > 0) - res += '/..'; - else - res = '..'; - lastSegmentLength = 2; - } - } else { - if (res.length > 0) - res += '/' + path.slice(lastSlash + 1, i); - else - res = path.slice(lastSlash + 1, i); - lastSegmentLength = i - lastSlash - 1; - } - lastSlash = i; - dots = 0; - } else if (code === 46 /*.*/ && dots !== -1) { - ++dots; - } else { - dots = -1; - } - } - return res; -} - -function _format(sep, pathObject) { - var dir = pathObject.dir || pathObject.root; - var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || ''); - if (!dir) { - return base; - } - if (dir === pathObject.root) { - return dir + base; - } - return dir + sep + base; -} - -var posix = { - // path.resolve([from ...], to) - resolve: function resolve() { - var resolvedPath = ''; - var resolvedAbsolute = false; - var cwd; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path; - if (i >= 0) - path = arguments[i]; - else { - if (cwd === undefined) - cwd = process.cwd(); - path = cwd; - } - - assertPath(path); - - // Skip empty entries - if (path.length === 0) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); - - if (resolvedAbsolute) { - if (resolvedPath.length > 0) - return '/' + resolvedPath; - else - return '/'; - } else if (resolvedPath.length > 0) { - return resolvedPath; - } else { - return '.'; - } - }, - - normalize: function normalize(path) { - assertPath(path); - - if (path.length === 0) return '.'; - - var isAbsolute = path.charCodeAt(0) === 47 /*/*/; - var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/; - - // Normalize the path - path = normalizeStringPosix(path, !isAbsolute); - - if (path.length === 0 && !isAbsolute) path = '.'; - if (path.length > 0 && trailingSeparator) path += '/'; - - if (isAbsolute) return '/' + path; - return path; - }, - - isAbsolute: function isAbsolute(path) { - assertPath(path); - return path.length > 0 && path.charCodeAt(0) === 47 /*/*/; - }, - - join: function join() { - if (arguments.length === 0) - return '.'; - var joined; - for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; - assertPath(arg); - if (arg.length > 0) { - if (joined === undefined) - joined = arg; - else - joined += '/' + arg; - } - } - if (joined === undefined) - return '.'; - return posix.normalize(joined); - }, - - relative: function relative(from, to) { - assertPath(from); - assertPath(to); - - if (from === to) return ''; - - from = posix.resolve(from); - to = posix.resolve(to); - - if (from === to) return ''; - - // Trim any leading backslashes - var fromStart = 1; - for (; fromStart < from.length; ++fromStart) { - if (from.charCodeAt(fromStart) !== 47 /*/*/) - break; - } - var fromEnd = from.length; - var fromLen = fromEnd - fromStart; - - // Trim any leading backslashes - var toStart = 1; - for (; toStart < to.length; ++toStart) { - if (to.charCodeAt(toStart) !== 47 /*/*/) - break; - } - var toEnd = to.length; - var toLen = toEnd - toStart; - - // Compare paths to find the longest common path from root - var length = fromLen < toLen ? fromLen : toLen; - var lastCommonSep = -1; - var i = 0; - for (; i <= length; ++i) { - if (i === length) { - if (toLen > length) { - if (to.charCodeAt(toStart + i) === 47 /*/*/) { - // We get here if `from` is the exact base path for `to`. - // For example: from='/foo/bar'; to='/foo/bar/baz' - return to.slice(toStart + i + 1); - } else if (i === 0) { - // We get here if `from` is the root - // For example: from='/'; to='/foo' - return to.slice(toStart + i); - } - } else if (fromLen > length) { - if (from.charCodeAt(fromStart + i) === 47 /*/*/) { - // We get here if `to` is the exact base path for `from`. - // For example: from='/foo/bar/baz'; to='/foo/bar' - lastCommonSep = i; - } else if (i === 0) { - // We get here if `to` is the root. - // For example: from='/foo'; to='/' - lastCommonSep = 0; - } - } - break; - } - var fromCode = from.charCodeAt(fromStart + i); - var toCode = to.charCodeAt(toStart + i); - if (fromCode !== toCode) - break; - else if (fromCode === 47 /*/*/) - lastCommonSep = i; - } - - var out = ''; - // Generate the relative path based on the path difference between `to` - // and `from` - for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { - if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) { - if (out.length === 0) - out += '..'; - else - out += '/..'; - } - } - - // Lastly, append the rest of the destination (`to`) path that comes after - // the common path parts - if (out.length > 0) - return out + to.slice(toStart + lastCommonSep); - else { - toStart += lastCommonSep; - if (to.charCodeAt(toStart) === 47 /*/*/) - ++toStart; - return to.slice(toStart); - } - }, - - _makeLong: function _makeLong(path) { - return path; - }, - - dirname: function dirname(path) { - assertPath(path); - if (path.length === 0) return '.'; - var code = path.charCodeAt(0); - var hasRoot = code === 47 /*/*/; - var end = -1; - var matchedSlash = true; - for (var i = path.length - 1; i >= 1; --i) { - code = path.charCodeAt(i); - if (code === 47 /*/*/) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } - - if (end === -1) return hasRoot ? '/' : '.'; - if (hasRoot && end === 1) return '//'; - return path.slice(0, end); - }, - - basename: function basename(path, ext) { - if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string'); - assertPath(path); - - var start = 0; - var end = -1; - var matchedSlash = true; - var i; - - if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { - if (ext.length === path.length && ext === path) return ''; - var extIdx = ext.length - 1; - var firstNonSlashEnd = -1; - for (i = path.length - 1; i >= 0; --i) { - var code = path.charCodeAt(i); - if (code === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else { - if (firstNonSlashEnd === -1) { - // We saw the first non-path separator, remember this index in case - // we need it if the extension ends up not matching - matchedSlash = false; - firstNonSlashEnd = i + 1; - } - if (extIdx >= 0) { - // Try to match the explicit extension - if (code === ext.charCodeAt(extIdx)) { - if (--extIdx === -1) { - // We matched the extension, so mark this as the end of our path - // component - end = i; - } - } else { - // Extension does not match, so our result is the entire path - // component - extIdx = -1; - end = firstNonSlashEnd; - } - } - } - } - - if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length; - return path.slice(start, end); - } else { - for (i = path.length - 1; i >= 0; --i) { - if (path.charCodeAt(i) === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // path component - matchedSlash = false; - end = i + 1; - } - } - - if (end === -1) return ''; - return path.slice(start, end); - } - }, - - extname: function extname(path) { - assertPath(path); - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - var preDotState = 0; - for (var i = path.length - 1; i >= 0; --i) { - var code = path.charCodeAt(i); - if (code === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (code === 46 /*.*/) { - // If this is our first dot, mark it as the start of our extension - if (startDot === -1) - startDot = i; - else if (preDotState !== 1) - preDotState = 1; - } else if (startDot !== -1) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = -1; - } - } - - if (startDot === -1 || end === -1 || - // We saw a non-dot character immediately before the dot - preDotState === 0 || - // The (right-most) trimmed path component is exactly '..' - preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { - return ''; - } - return path.slice(startDot, end); - }, - - format: function format(pathObject) { - if (pathObject === null || typeof pathObject !== 'object') { - throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject); - } - return _format('/', pathObject); - }, - - parse: function parse(path) { - assertPath(path); - - var ret = { root: '', dir: '', base: '', ext: '', name: '' }; - if (path.length === 0) return ret; - var code = path.charCodeAt(0); - var isAbsolute = code === 47 /*/*/; - var start; - if (isAbsolute) { - ret.root = '/'; - start = 1; - } else { - start = 0; - } - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; - var i = path.length - 1; - - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - var preDotState = 0; - - // Get non-dir info - for (; i >= start; --i) { - code = path.charCodeAt(i); - if (code === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (code === 46 /*.*/) { - // If this is our first dot, mark it as the start of our extension - if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1; - } else if (startDot !== -1) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = -1; - } - } - - if (startDot === -1 || end === -1 || - // We saw a non-dot character immediately before the dot - preDotState === 0 || - // The (right-most) trimmed path component is exactly '..' - preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { - if (end !== -1) { - if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end); - } - } else { - if (startPart === 0 && isAbsolute) { - ret.name = path.slice(1, startDot); - ret.base = path.slice(1, end); - } else { - ret.name = path.slice(startPart, startDot); - ret.base = path.slice(startPart, end); - } - ret.ext = path.slice(startDot, end); - } - - if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/'; - - return ret; - }, - - sep: '/', - delimiter: ':', - win32: null, - posix: null + const prototype = Object.getPrototypeOf(value); + return prototype === null || prototype === Object.prototype; }; -posix.posix = posix; +},{}],5:[function(require,module,exports){ +'use strict'; +const isOptionObject = require('is-plain-obj'); -module.exports = posix; +const {hasOwnProperty} = Object.prototype; +const {propertyIsEnumerable} = Object; +const defineProperty = (object, name, value) => Object.defineProperty(object, name, { + value, + writable: true, + enumerable: true, + configurable: true +}); -}).call(this)}).call(this,require('_process')) -},{"_process":6}],6:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } +const globalThis = this; +const defaultMergeOptions = { + concatArrays: false, + ignoreUndefined: false }; -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; +const getEnumerableOwnPropertyKeys = value => { + const keys = []; + + for (const key in value) { + if (hasOwnProperty.call(value, key)) { + keys.push(key); + } + } + + /* istanbul ignore else */ + if (Object.getOwnPropertySymbols) { + const symbols = Object.getOwnPropertySymbols(value); + + for (const symbol of symbols) { + if (propertyIsEnumerable.call(value, symbol)) { + keys.push(symbol); + } + } + } + + return keys; +}; + +function clone(value) { + if (Array.isArray(value)) { + return cloneArray(value); + } + + if (isOptionObject(value)) { + return cloneOptionObject(value); + } + + return value; } -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; -function noop() {} +function cloneArray(array) { + const result = array.slice(0, 0); -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; + getEnumerableOwnPropertyKeys(array).forEach(key => { + defineProperty(result, key, clone(array[key])); + }); -process.listeners = function (name) { return [] } + return result; +} -process.binding = function (name) { - throw new Error('process.binding is not supported'); +function cloneOptionObject(object) { + const result = Object.getPrototypeOf(object) === null ? Object.create(null) : {}; + + getEnumerableOwnPropertyKeys(object).forEach(key => { + defineProperty(result, key, clone(object[key])); + }); + + return result; +} + +/** + * @param {*} merged already cloned + * @param {*} source something to merge + * @param {string[]} keys keys to merge + * @param {Object} config Config Object + * @returns {*} cloned Object + */ +const mergeKeys = (merged, source, keys, config) => { + keys.forEach(key => { + if (typeof source[key] === 'undefined' && config.ignoreUndefined) { + return; + } + + // Do not recurse into prototype chain of merged + if (key in merged && merged[key] !== Object.getPrototypeOf(merged)) { + defineProperty(merged, key, merge(merged[key], source[key], config)); + } else { + defineProperty(merged, key, clone(source[key])); + } + }); + + return merged; }; -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; +/** + * @param {*} merged already cloned + * @param {*} source something to merge + * @param {Object} config Config Object + * @returns {*} cloned Object + * + * see [Array.prototype.concat ( ...arguments )](http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat) + */ +const concatArrays = (merged, source, config) => { + let result = merged.slice(0, 0); + let resultIndex = 0; -},{}],7:[function(require,module,exports){ + [merged, source].forEach(array => { + const indices = []; + + // `result.concat(array)` with cloning + for (let k = 0; k < array.length; k++) { + if (!hasOwnProperty.call(array, k)) { + continue; + } + + indices.push(String(k)); + + if (array === merged) { + // Already cloned + defineProperty(result, resultIndex++, array[k]); + } else { + defineProperty(result, resultIndex++, clone(array[k])); + } + } + + // Merge non-index keys + result = mergeKeys(result, array, getEnumerableOwnPropertyKeys(array).filter(key => !indices.includes(key)), config); + }); + + return result; +}; + +/** + * @param {*} merged already cloned + * @param {*} source something to merge + * @param {Object} config Config Object + * @returns {*} cloned Object + */ +function merge(merged, source, config) { + if (config.concatArrays && Array.isArray(merged) && Array.isArray(source)) { + return concatArrays(merged, source, config); + } + + if (!isOptionObject(source) || !isOptionObject(merged)) { + return clone(source); + } + + return mergeKeys(merged, source, getEnumerableOwnPropertyKeys(source), config); +} + +module.exports = function (...options) { + const config = merge(clone(defaultMergeOptions), (this !== globalThis && this) || {}, defaultMergeOptions); + let merged = {_: {}}; + + for (const option of options) { + if (option === undefined) { + continue; + } + + if (!isOptionObject(option)) { + throw new TypeError('`' + option + '` is not an Option Object'); + } + + merged = merge(merged, {_: option}, config); + } + + return merged._; +}; + +},{"is-plain-obj":4}],6:[function(require,module,exports){ (function(module) { 'use strict'; @@ -1122,7 +471,7 @@ process.umask = function() { return 0; }; })(module); -},{}],8:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ const utils = require('./utils') const runOnJson = (res, proofData, checkPath, checkClaim, checkRelation) => { @@ -1157,7 +506,9 @@ const runOnJson = (res, proofData, checkPath, checkClaim, checkRelation) => { return res } - if (!(checkPath[0] in proofData)) { + try { + checkPath[0] in proofData + } catch(e) { res.errors.push('err_data_structure_incorrect') return res } @@ -1187,7 +538,7 @@ const run = (proofData, spData) => { exports.run = run -},{"./utils":25}],9:[function(require,module,exports){ +},{"./utils":24}],8:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1203,6 +554,7 @@ 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. */ +const mergeOptions = require('merge-options') const validUrl = require('valid-url') const serviceproviders = require('./serviceproviders') const claimVerification = require('./claimVerification') @@ -1212,6 +564,13 @@ const verify = async (uri, fingerprint, opts) => { if (!fingerprint) { fingerprint = null } if (!opts) { opts = {} } + const defaultOpts = { + returnMatchesOnly: false, + proxyPolicy: 'adaptive', + doipProxyHostname: 'proxy.keyoxide.org' + } + opts = mergeOptions(defaultOpts, opts) + if (!validUrl.isUri(uri)) { throw new Error('Not a valid URI') } @@ -1230,10 +589,10 @@ const verify = async (uri, fingerprint, opts) => { if (spData.customRequestHandler instanceof Function) { proofData = await spData.customRequestHandler(spData, opts) - } else if (!spData.proof.useProxy || 'useProxyWhenNeeded' in opts && !opts.useProxyWhenNeeded) { - proofData = await serviceproviders.directRequestHandler(spData) + } else if (!spData.proof.useProxy || 'proxyPolicy' in opts && !opts.useProxyWhenNeeded) { + proofData = await serviceproviders.directRequestHandler(spData, opts) } else { - proofData = await serviceproviders.proxyRequestHandler(spData) + proofData = await serviceproviders.proxyRequestHandler(spData, opts) } if (proofData) { @@ -1255,7 +614,6 @@ const verify = async (uri, fingerprint, opts) => { return { isVerified: claimVerificationResult.isVerified, - matchedServiceprovider: spData ? spData.serviceprovider.name : null, serviceproviderData: spData } } @@ -1265,7 +623,7 @@ exports.serviceproviders = serviceproviders exports.claimVerification = claimVerification exports.utils = utils -},{"./claimVerification":8,"./serviceproviders":10,"./utils":25,"valid-url":7}],10:[function(require,module,exports){ +},{"./claimVerification":7,"./serviceproviders":9,"./utils":24,"merge-options":5,"valid-url":6}],9:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1332,8 +690,8 @@ const match = (uri, opts) => { return matches } -const directRequestHandler = async (spData) => { - const res = await req(spData.proof.fetch ? spData.proof.fetch : spData.proof.uri, 'json', { Accept: 'application/json' }) +const directRequestHandler = async (spData, opts) => { + const res = await req(spData.proof.fetch ? spData.proof.fetch : spData.proof.uri, null, { Accept: 'application/json' }) switch (spData.proof.format) { case 'json': @@ -1348,9 +706,9 @@ const directRequestHandler = async (spData) => { } } -const proxyRequestHandler = async (spData) => { +const proxyRequestHandler = async (spData, opts) => { const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri - const res = await req(utils.generateProxyURL(spData.proof.format, url), 'json', { Accept: 'application/json' }) + const res = await req(utils.generateProxyURL(spData.proof.format, url, opts), null, { Accept: 'application/json' }) const json = await res.json() return json.content } @@ -1361,7 +719,7 @@ exports.match = match exports.directRequestHandler = directRequestHandler exports.proxyRequestHandler = proxyRequestHandler -},{"./serviceproviders/devto":11,"./serviceproviders/discourse":12,"./serviceproviders/dns":13,"./serviceproviders/fediverse":14,"./serviceproviders/gitea":15,"./serviceproviders/github":16,"./serviceproviders/gitlab":17,"./serviceproviders/hackernews":18,"./serviceproviders/liberapay":19,"./serviceproviders/lobsters":20,"./serviceproviders/mastodon":21,"./serviceproviders/reddit":22,"./serviceproviders/twitter":23,"./serviceproviders/xmpp":24,"./utils":25,"bent":1}],11:[function(require,module,exports){ +},{"./serviceproviders/devto":10,"./serviceproviders/discourse":11,"./serviceproviders/dns":12,"./serviceproviders/fediverse":13,"./serviceproviders/gitea":14,"./serviceproviders/github":15,"./serviceproviders/gitlab":16,"./serviceproviders/hackernews":17,"./serviceproviders/liberapay":18,"./serviceproviders/lobsters":19,"./serviceproviders/mastodon":20,"./serviceproviders/reddit":21,"./serviceproviders/twitter":22,"./serviceproviders/xmpp":23,"./utils":24,"bent":1}],10:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1390,7 +748,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: `https://dev.to/${match[1]}` + uri: `https://dev.to/${match[1]}`, + qr: null }, proof: { uri: uri, @@ -1404,7 +763,7 @@ const processURI = (uri, opts) => { path: ['body_markdown'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1427,7 +786,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],12:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1456,7 +815,8 @@ const processURI = (uri, opts) => { }, profile: { display: `${match[2]}@${match[1]}`, - uri: uri + uri: uri, + qr: null }, proof: { uri: uri, @@ -1470,7 +830,7 @@ const processURI = (uri, opts) => { path: ['user', 'bio_raw'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1493,7 +853,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],13:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1509,9 +869,35 @@ 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. */ +const dns = require('dns') +const bent = require('bent') +const req = bent('GET') const utils = require('../utils') const reURI = /^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/ +const customRequestHandler = async (spData, opts) => { + if (('resolveTxt' in dns)) { + const prom = async () => { + return new Promise((resolve, reject) => { + dns.resolveTxt(spData.profile.display, (err, records) => { + if (err) reject(err) + resolve(records) + }) + }) + } + return { + hostname: spData.profile.display, + records: { + txt: await prom() + } + } + } else { + const res = await req(spData.proof.uri, null, { Accept: 'application/json' }) + const json = await res.json() + return json + } +} + const processURI = (uri, opts) => { if (!opts) { opts = {} } const match = uri.match(reURI) @@ -1523,7 +909,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: `https://${match[1]}` + uri: `https://${match[1]}`, + qr: null }, proof: { uri: utils.generateProxyURL('dns', match[1]), @@ -1537,7 +924,7 @@ const processURI = (uri, opts) => { path: ['records', 'txt'], relation: 'contains' }, - qr: null + customRequestHandler: customRequestHandler } } @@ -1560,7 +947,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"../utils":25}],14:[function(require,module,exports){ +},{"../utils":24,"bent":1,"dns":3}],13:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1589,7 +976,8 @@ const processURI = (uri, opts) => { }, profile: { display: `@${match[2]}@${match[1]}`, - uri: uri + uri: uri, + qr: null }, proof: { uri: uri, @@ -1603,7 +991,7 @@ const processURI = (uri, opts) => { path: ['summary'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1626,7 +1014,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],15:[function(require,module,exports){ +},{}],14:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1655,7 +1043,8 @@ const processURI = (uri, opts) => { }, profile: { display: `${match[2]}@${match[1]}`, - uri: `https://${match[1]}/${match[2]}` + uri: `https://${match[1]}/${match[2]}`, + qr: null }, proof: { uri: uri, @@ -1669,7 +1058,7 @@ const processURI = (uri, opts) => { path: ['description'], relation: 'equals' }, - qr: null + customRequestHandler: null } } @@ -1692,7 +1081,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],16:[function(require,module,exports){ +},{}],15:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1721,7 +1110,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: `https://github.com/${match[1]}` + uri: `https://github.com/${match[1]}`, + qr: null }, proof: { uri: uri, @@ -1735,7 +1125,7 @@ const processURI = (uri, opts) => { path: ['files', 'openpgp.md', 'content'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1758,7 +1148,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],17:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1814,7 +1204,8 @@ const processURI = (uri, opts) => { }, profile: { display: `${match[2]}@${match[1]}`, - uri: `https://${match[1]}/${match[2]}` + uri: `https://${match[1]}/${match[2]}`, + qr: null }, proof: { uri: uri, @@ -1828,7 +1219,6 @@ const processURI = (uri, opts) => { path: ['description'], relation: 'equals' }, - qr: null, customRequestHandler: customRequestHandler } } @@ -1852,7 +1242,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"bent":1}],18:[function(require,module,exports){ +},{"bent":1}],17:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1881,7 +1271,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: uri + uri: uri, + qr: null }, proof: { uri: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`, @@ -1895,7 +1286,7 @@ const processURI = (uri, opts) => { path: ['about'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1918,7 +1309,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],19:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -1947,7 +1338,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: uri + uri: uri, + qr: null }, proof: { uri: uri, @@ -1961,7 +1353,7 @@ const processURI = (uri, opts) => { path: ['statements', 'content'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -1984,7 +1376,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],20:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -2013,7 +1405,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: uri + uri: uri, + qr: null }, proof: { uri: `https://lobste.rs/u/${match[1]}.json`, @@ -2027,7 +1420,7 @@ const processURI = (uri, opts) => { path: ['about'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -2050,7 +1443,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],21:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -2079,7 +1472,8 @@ const processURI = (uri, opts) => { }, profile: { display: `@${match[2]}@${match[1]}`, - uri: uri + uri: uri, + qr: null }, proof: { uri: uri, @@ -2093,7 +1487,7 @@ const processURI = (uri, opts) => { path: ['attachment', 'value'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -2116,7 +1510,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],22:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -2145,7 +1539,8 @@ const processURI = (uri, opts) => { }, profile: { display: match[1], - uri: `https://www.reddit.com/user/${match[1]}` + uri: `https://www.reddit.com/user/${match[1]}`, + qr: null }, proof: { uri: uri, @@ -2159,7 +1554,7 @@ const processURI = (uri, opts) => { path: ['data', 'children', 'data', 'selftext'], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -2190,7 +1585,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],23:[function(require,module,exports){ +},{}],22:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -2219,7 +1614,8 @@ const processURI = (uri, opts) => { }, profile: { display: `@${match[1]}`, - uri: `https://twitter.com/${match[1]}` + uri: `https://twitter.com/${match[1]}`, + qr: null }, proof: { uri: uri, @@ -2233,7 +1629,7 @@ const processURI = (uri, opts) => { path: [], relation: 'contains' }, - qr: null + customRequestHandler: null } } @@ -2256,7 +1652,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],24:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ /* Copyright 2020 Yarmo Mackenbach @@ -2285,7 +1681,8 @@ const processURI = (uri, opts) => { }, profile: { display: `${match[1]}@${match[2]}`, - uri: uri + uri: uri, + qr: uri }, proof: { uri: 'xmppVcardServerDomain' in opts @@ -2301,7 +1698,7 @@ const processURI = (uri, opts) => { path: [], relation: 'contains' }, - qr: uri + customRequestHandler: null } } @@ -2324,14 +1721,10 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],25:[function(require,module,exports){ -(function (process){(function (){ -require('dotenv').config() - -const DOIP_PROXY_HOSTNAME = process.env.DOIP_PROXY_HOSTNAME || 'proxy.keyoxide.org' - -const generateProxyURL = (type, url) => { - return `https://${DOIP_PROXY_HOSTNAME}/api/1/get/${type}/${encodeURIComponent(url)}` +},{}],24:[function(require,module,exports){ +const generateProxyURL = (type, url, opts) => { + if (!opts || !opts.doipProxyHostname) { return null } + return `https://${opts.doipProxyHostname}/api/1/get/${type}/${encodeURIComponent(url)}` } const generateClaim = (fingerprint, format) => { @@ -2353,6 +1746,5 @@ const generateClaim = (fingerprint, format) => { exports.generateProxyURL = generateProxyURL exports.generateClaim = generateClaim -}).call(this)}).call(this,require('_process')) -},{"_process":6,"dotenv":4}]},{},[9])(9) +},{}]},{},[8])(8) }); diff --git a/dist/doip.min.js b/dist/doip.min.js index 5937188..7e4be76 100644 --- a/dist/doip.min.js +++ b/dist/doip.min.js @@ -1 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).doip=e()}}((function(){return function e(t,r,o){function i(s,a){if(!r[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(n)return n(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[s]={exports:{}};t[s][0].call(l.exports,(function(e){return i(t[s][1][e]||e)}),l,l.exports,e,t,r,o)}return r[s].exports}for(var n="function"==typeof require&&require,s=0;s(r||(r=this.arrayBuffer()),r)}),this.headers={};for(const[t,r]of e.headers.entries())this.headers[t.toLowerCase()]=r}}t.exports=o(((e,t,r,o,n)=>async(s,a,c={})=>{s=n+(s||"");let u=new URL(s);if(o||(o={}),u.username&&(o.Authorization="Basic "+btoa(u.username+":"+u.password),u=new URL(u.protocol+"//"+u.host+u.pathname+u.search)),"https:"!==u.protocol&&"http:"!==u.protocol)throw new Error("Unknown protocol, "+u.protocol);if(a)if(a instanceof ArrayBuffer||ArrayBuffer.isView(a)||"string"==typeof a);else{if("object"!=typeof a)throw new Error("Unknown body type.");a=JSON.stringify(a),o["Content-Type"]="application/json"}c=new Headers({...o||{},...c});const l=await fetch(u,{method:t,headers:c,body:a});if(l.statusCode=l.status,!e.has(l.status))throw new i(l);return"json"===r?l.json():"buffer"===r?l.arrayBuffer():"string"===r?l.text():l}))},{"./core":2}],2:[function(e,t,r){"use strict";const o=new Set(["json","buffer","string"]);t.exports=e=>(...t)=>{const r=new Set;let i,n,s,a="";return t.forEach((e=>{if("string"==typeof e)if(e.toUpperCase()===e){if(i){throw new Error(`Can't set method to ${e}, already set to ${i}.`)}i=e}else if(e.startsWith("http:")||e.startsWith("https:"))a=e;else{if(!o.has(e))throw new Error("Unknown encoding, "+e);n=e}else if("number"==typeof e)r.add(e);else{if("object"!=typeof e)throw new Error("Unknown type: "+typeof e);if(Array.isArray(e)||e instanceof Set)e.forEach((e=>r.add(e)));else{if(s)throw new Error("Cannot set headers twice.");s=e}}})),i||(i="GET"),0===r.size&&r.add(200),e(r,i,n,s,a)}},{}],3:[function(e,t,r){},{}],4:[function(e,t,r){(function(r){(function(){const o=e("fs"),i=e("path");function n(e){console.log("[dotenv][DEBUG] "+e)}const s=/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/,a=/\\n/g,c=/\n|\r|\r\n/;function u(e,t){const r=Boolean(t&&t.debug),o={};return e.toString().split(c).forEach((function(e,t){const i=e.match(s);if(null!=i){const e=i[1];let t=i[2]||"";const r=t.length-1,n='"'===t[0]&&'"'===t[r];"'"===t[0]&&"'"===t[r]||n?(t=t.substring(1,r),n&&(t=t.replace(a,"\n"))):t=t.trim(),o[e]=t}else r&&n(`did not match key and value when parsing line ${t+1}: ${e}`)})),o}t.exports.config=function(e){let t=i.resolve(r.cwd(),".env"),s="utf8",a=!1;e&&(null!=e.path&&(t=e.path),null!=e.encoding&&(s=e.encoding),null!=e.debug&&(a=!0));try{const e=u(o.readFileSync(t,{encoding:s}),{debug:a});return Object.keys(e).forEach((function(t){Object.prototype.hasOwnProperty.call(r.env,t)?a&&n(`"${t}" is already defined in \`process.env\` and will not be overwritten`):r.env[t]=e[t]})),{parsed:e}}catch(e){return{error:e}}},t.exports.parse=u}).call(this)}).call(this,e("_process"))},{_process:6,fs:3,path:5}],5:[function(e,t,r){(function(e){(function(){"use strict";function r(e){if("string"!=typeof e)throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}function o(e,t){for(var r,o="",i=0,n=-1,s=0,a=0;a<=e.length;++a){if(a2){var c=o.lastIndexOf("/");if(c!==o.length-1){-1===c?(o="",i=0):i=(o=o.slice(0,c)).length-1-o.lastIndexOf("/"),n=a,s=0;continue}}else if(2===o.length||1===o.length){o="",i=0,n=a,s=0;continue}t&&(o.length>0?o+="/..":o="..",i=2)}else o.length>0?o+="/"+e.slice(n+1,a):o=e.slice(n+1,a),i=a-n-1;n=a,s=0}else 46===r&&-1!==s?++s:s=-1}return o}var i={resolve:function(){for(var t,i="",n=!1,s=arguments.length-1;s>=-1&&!n;s--){var a;s>=0?a=arguments[s]:(void 0===t&&(t=e.cwd()),a=t),r(a),0!==a.length&&(i=a+"/"+i,n=47===a.charCodeAt(0))}return i=o(i,!n),n?i.length>0?"/"+i:"/":i.length>0?i:"."},normalize:function(e){if(r(e),0===e.length)return".";var t=47===e.charCodeAt(0),i=47===e.charCodeAt(e.length-1);return 0!==(e=o(e,!t)).length||t||(e="."),e.length>0&&i&&(e+="/"),t?"/"+e:e},isAbsolute:function(e){return r(e),e.length>0&&47===e.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var e,t=0;t0&&(void 0===e?e=o:e+="/"+o)}return void 0===e?".":i.normalize(e)},relative:function(e,t){if(r(e),r(t),e===t)return"";if((e=i.resolve(e))===(t=i.resolve(t)))return"";for(var o=1;ou){if(47===t.charCodeAt(a+p))return t.slice(a+p+1);if(0===p)return t.slice(a+p)}else s>u&&(47===e.charCodeAt(o+p)?l=p:0===p&&(l=0));break}var h=e.charCodeAt(o+p);if(h!==t.charCodeAt(a+p))break;47===h&&(l=p)}var f="";for(p=o+l+1;p<=n;++p)p!==n&&47!==e.charCodeAt(p)||(0===f.length?f+="..":f+="/..");return f.length>0?f+t.slice(a+l):(a+=l,47===t.charCodeAt(a)&&++a,t.slice(a))},_makeLong:function(e){return e},dirname:function(e){if(r(e),0===e.length)return".";for(var t=e.charCodeAt(0),o=47===t,i=-1,n=!0,s=e.length-1;s>=1;--s)if(47===(t=e.charCodeAt(s))){if(!n){i=s;break}}else n=!1;return-1===i?o?"/":".":o&&1===i?"//":e.slice(0,i)},basename:function(e,t){if(void 0!==t&&"string"!=typeof t)throw new TypeError('"ext" argument must be a string');r(e);var o,i=0,n=-1,s=!0;if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var a=t.length-1,c=-1;for(o=e.length-1;o>=0;--o){var u=e.charCodeAt(o);if(47===u){if(!s){i=o+1;break}}else-1===c&&(s=!1,c=o+1),a>=0&&(u===t.charCodeAt(a)?-1==--a&&(n=o):(a=-1,n=c))}return i===n?n=c:-1===n&&(n=e.length),e.slice(i,n)}for(o=e.length-1;o>=0;--o)if(47===e.charCodeAt(o)){if(!s){i=o+1;break}}else-1===n&&(s=!1,n=o+1);return-1===n?"":e.slice(i,n)},extname:function(e){r(e);for(var t=-1,o=0,i=-1,n=!0,s=0,a=e.length-1;a>=0;--a){var c=e.charCodeAt(a);if(47!==c)-1===i&&(n=!1,i=a+1),46===c?-1===t?t=a:1!==s&&(s=1):-1!==t&&(s=-1);else if(!n){o=a+1;break}}return-1===t||-1===i||0===s||1===s&&t===i-1&&t===o+1?"":e.slice(t,i)},format:function(e){if(null===e||"object"!=typeof e)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return function(e,t){var r=t.dir||t.root,o=t.base||(t.name||"")+(t.ext||"");return r?r===t.root?r+o:r+e+o:o}("/",e)},parse:function(e){r(e);var t={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return t;var o,i=e.charCodeAt(0),n=47===i;n?(t.root="/",o=1):o=0;for(var s=-1,a=0,c=-1,u=!0,l=e.length-1,p=0;l>=o;--l)if(47!==(i=e.charCodeAt(l)))-1===c&&(u=!1,c=l+1),46===i?-1===s?s=l:1!==p&&(p=1):-1!==s&&(p=-1);else if(!u){a=l+1;break}return-1===s||-1===c||0===p||1===p&&s===c-1&&s===a+1?-1!==c&&(t.base=t.name=0===a&&n?e.slice(1,c):e.slice(a,c)):(0===a&&n?(t.name=e.slice(1,s),t.base=e.slice(1,c)):(t.name=e.slice(a,s),t.base=e.slice(a,c)),t.ext=e.slice(s,c)),a>0?t.dir=e.slice(0,a-1):n&&(t.dir="/"),t},sep:"/",delimiter:":",win32:null,posix:null};i.posix=i,t.exports=i}).call(this)}).call(this,e("_process"))},{_process:6}],6:[function(e,t,r){var o,i,n=t.exports={};function s(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function c(e){if(o===setTimeout)return setTimeout(e,0);if((o===s||!o)&&setTimeout)return o=setTimeout,setTimeout(e,0);try{return o(e,0)}catch(t){try{return o.call(null,e,0)}catch(t){return o.call(this,e,0)}}}!function(){try{o="function"==typeof setTimeout?setTimeout:s}catch(e){o=s}try{i="function"==typeof clearTimeout?clearTimeout:a}catch(e){i=a}}();var u,l=[],p=!1,h=-1;function f(){p&&u&&(p=!1,u.length?l=u.concat(l):h=-1,l.length&&d())}function d(){if(!p){var e=c(f);p=!0;for(var t=l.length;t;){for(u=l,l=[];++h1)for(var r=1;r=0){if(o&&o.length){if(0!==i.length&&!/^\//.test(i))return}else if(/^\/\//.test(i))return;if(/^[a-z][a-z0-9\+\-\.]*$/.test(a.toLowerCase()))return c+=a+":",o&&o.length&&(c+="//"+o),c+=i,n&&n.length&&(c+="?"+n),s&&s.length&&(c+="#"+s),c}}}function o(e,o){if(r(e)){var i,n,s,a,c="",u="",l="",p="";if(c=(i=t(e))[1],u=i[2],n=i[3],s=i[4],a=i[5],c){if(o){if("https"!=c.toLowerCase())return}else if("http"!=c.toLowerCase())return;if(u)return/:(\d+)$/.test(u)&&(l=u.match(/:(\d+)$/)[0],u=u.replace(/:\d+$/,"")),p+=c+":",p+="//"+u,l&&(p+=l),p+=n,s&&s.length&&(p+="?"+s),a&&a.length&&(p+="#"+a),p}}}function i(e){return o(e,!0)}function n(e){return o(e)||i(e)}}(t)},{}],8:[function(e,t,r){const o=e("./utils"),i=(e,t,r,o,n)=>{let s;if(e.isVerified||!t)return e;if(Array.isArray(t))return t.forEach(((t,s)=>{e=i(e,t,r,o,n)})),e;if(0==r.length){switch(n){default:case"contains":s=new RegExp(o.replace("[","\\[").replace("]","\\]"),"gi"),e.isVerified=s.test(t.replace(/\r?\n|\r/,""));break;case"equals":e.isVerified=t.replace(/\r?\n|\r/,"").toLowerCase()==o.toLowerCase();break;case"oneOf":s=new RegExp(o,"gi"),e.isVerified=s.test(t.join("|"))}return e}return r[0]in t?e=i(e,t[r[0]],r.slice(1),o,n):(e.errors.push("err_data_structure_incorrect"),e)};r.run=(e,t)=>{let r={isVerified:!1,errors:[]};switch(t.proof.format){case"json":r=i(r,e,t.claim.path,o.generateClaim(t.claim.fingerprint,t.claim.format),t.claim.relation);break;case"text":re=new RegExp(o.generateClaim(t.claim.fingerprint,t.claim.format),"gi"),r=re.test(e.replace(/\r?\n|\r/,""))}return r}},{"./utils":25}],9:[function(e,t,r){const o=e("valid-url"),i=e("./serviceproviders"),n=e("./claimVerification"),s=e("./utils");r.verify=async(e,t,r)=>{if(t||(t=null),r||(r={}),!o.isUri(e))throw new Error("Not a valid URI");const s=i.match(e,r);if("returnMatchesOnly"in r&&r.returnMatchesOnly)return s;let a,c,u,l,p=!1,h=0;for(;!p&&h{let r,o=[];return n.forEach(((i,n)=>{r=s[i],r.reURI.test(e)&&o.push(r.processURI(e,t))})),o},r.directRequestHandler=async e=>{const t=await o(e.proof.fetch?e.proof.fetch:e.proof.uri,"json",{Accept:"application/json"});switch(e.proof.format){case"json":return await t.json();case"text":return await t.text();default:throw new Error("No specified proof data format")}},r.proxyRequestHandler=async e=>{const t=e.proof.fetch?e.proof.fetch:e.proof.uri,r=await o(i.generateProxyURL(e.proof.format,t),"json",{Accept:"application/json"});return(await r.json()).content}},{"./serviceproviders/devto":11,"./serviceproviders/discourse":12,"./serviceproviders/dns":13,"./serviceproviders/fediverse":14,"./serviceproviders/gitea":15,"./serviceproviders/github":16,"./serviceproviders/gitlab":17,"./serviceproviders/hackernews":18,"./serviceproviders/liberapay":19,"./serviceproviders/lobsters":20,"./serviceproviders/mastodon":21,"./serviceproviders/reddit":22,"./serviceproviders/twitter":23,"./serviceproviders/xmpp":24,"./utils":25,bent:1}],11:[function(e,t,r){const o=/^https:\/\/dev\.to\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"devto"},profile:{display:r[1],uri:"https://dev.to/"+r[1]},proof:{uri:e,fetch:`https://dev.to/api/articles/${r[1]}/${r[2]}`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["body_markdown"],relation:"contains"},qr:null}},r.tests=[{uri:"https://dev.to/alice/post",shouldMatch:!0},{uri:"https://dev.to/alice/post/",shouldMatch:!0},{uri:"https://domain.org/alice/post",shouldMatch:!1}]},{}],12:[function(e,t,r){const o=/^https:\/\/(.*)\/u\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"discourse"},profile:{display:`${r[2]}@${r[1]}`,uri:e},proof:{uri:e,fetch:`https://${r[1]}/u/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["user","bio_raw"],relation:"contains"},qr:null}},r.tests=[{uri:"https://domain.org/u/alice",shouldMatch:!0},{uri:"https://domain.org/u/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],13:[function(e,t,r){const o=e("../utils"),i=/^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"dns"},profile:{display:r[1],uri:"https://"+r[1]},proof:{uri:o.generateProxyURL("dns",r[1]),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"uri",path:["records","txt"],relation:"contains"},qr:null}},r.tests=[{uri:"dns:domain.org",shouldMatch:!0},{uri:"dns:domain.org?type=TXT",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":25}],14:[function(e,t,r){const o=/^https:\/\/(.*)\/users\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"fediverse"},profile:{display:`@${r[2]}@${r[1]}`,uri:e},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["summary"],relation:"contains"},qr:null}},r.tests=[{uri:"https://domain.org/users/alice",shouldMatch:!0},{uri:"https://domain.org/users/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],15:[function(e,t,r){const o=/^https:\/\/(.*)\/(.*)\/gitea_proof\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"gitea"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`},proof:{uri:e,fetch:`https://${r[1]}/api/v1/repos/${r[2]}/gitea_proof`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},qr:null}},r.tests=[{uri:"https://domain.org/alice/gitea_proof",shouldMatch:!0},{uri:"https://domain.org/alice/gitea_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{}],16:[function(e,t,r){const o=/^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"github"},profile:{display:r[1],uri:"https://github.com/"+r[1]},proof:{uri:e,fetch:"https://api.github.com/gists/"+r[2],useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["files","openpgp.md","content"],relation:"contains"},qr:null}},r.tests=[{uri:"https://gist.github.com/Alice/123456789",shouldMatch:!0},{uri:"https://gist.github.com/Alice/123456789/",shouldMatch:!0},{uri:"https://domain.org/Alice/123456789",shouldMatch:!1}]},{}],17:[function(e,t,r){const o=e("bent")("GET"),i=/^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/,n=async(e,t)=>{const r=e.proof.uri.match(i),n=`https://${r[1]}/api/v4/users?username=${r[2]}`,s=await o(n,"json",{Accept:"application/json"}),a=(await s.json()).find((e=>e.username===r[2]));if(!a)throw new Error("No user with username "+r[2]);const c=`https://${r[1]}/api/v4/users/${a.id}/projects`,u=await o(c,{},{Accept:"application/json"}),l=(await u.json()).find((e=>"gitlab_proof"===e.path));if(!l)throw new Error("No project at "+e.proof.uri);return l};r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"gitlab"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},qr:null,customRequestHandler:n}},r.tests=[{uri:"https://gitlab.domain.org/alice/gitlab_proof",shouldMatch:!0},{uri:"https://gitlab.domain.org/alice/gitlab_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{bent:1}],18:[function(e,t,r){const o=/^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"hackernews"},profile:{display:r[1],uri:e},proof:{uri:`https://hacker-news.firebaseio.com/v0/user/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"uri",path:["about"],relation:"contains"},qr:null}},r.tests=[{uri:"https://news.ycombinator.com/user?id=Alice",shouldMatch:!0},{uri:"https://news.ycombinator.com/user?id=Alice/",shouldMatch:!0},{uri:"https://domain.org/user?id=Alice",shouldMatch:!1}]},{}],19:[function(e,t,r){const o=/^https:\/\/liberapay\.com\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"liberapay"},profile:{display:r[1],uri:e},proof:{uri:e,fetch:`https://liberapay.com/${r[1]}/public.json`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["statements","content"],relation:"contains"},qr:null}},r.tests=[{uri:"https://liberapay.com/alice",shouldMatch:!0},{uri:"https://liberapay.com/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],20:[function(e,t,r){const o=/^https:\/\/lobste\.rs\/u\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"lobsters"},profile:{display:r[1],uri:e},proof:{uri:`https://lobste.rs/u/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["about"],relation:"contains"},qr:null}},r.tests=[{uri:"https://lobste.rs/u/Alice",shouldMatch:!0},{uri:"https://lobste.rs/u/Alice/",shouldMatch:!0},{uri:"https://domain.org/u/Alice",shouldMatch:!1}]},{}],21:[function(e,t,r){const o=/^https:\/\/(.*)\/@(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"mastodon"},profile:{display:`@${r[2]}@${r[1]}`,uri:e},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["attachment","value"],relation:"contains"},qr:null}},r.tests=[{uri:"https://domain.org/@alice",shouldMatch:!0},{uri:"https://domain.org/@alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],22:[function(e,t,r){const o=/^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"reddit"},profile:{display:r[1],uri:"https://www.reddit.com/user/"+r[1]},proof:{uri:e,fetch:`https://www.reddit.com/user/${r[1]}/comments/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["data","children","data","selftext"],relation:"contains"},qr:null}},r.tests=[{uri:"https://www.reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://www.reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://domain.org/user/Alice/comments/123456/post",shouldMatch:!1}]},{}],23:[function(e,t,r){const o=/^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"twitter"},profile:{display:"@"+r[1],uri:"https://twitter.com/"+r[1]},proof:{uri:e,fetch:`https://mobile.twitter.com/${r[1]}/status/${r[2]}`,useProxy:!1,format:"text"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},qr:null}},r.tests=[{uri:"https://twitter.com/alice/status/1234567890123456789",shouldMatch:!0},{uri:"https://twitter.com/alice/status/1234567890123456789/",shouldMatch:!0},{uri:"https://domain.org/alice/status/1234567890123456789",shouldMatch:!1}]},{}],24:[function(e,t,r){const o=/^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"communication",name:"xmpp"},profile:{display:`${r[1]}@${r[2]}`,uri:e},proof:{uri:"xmppVcardServerDomain"in t?`https://${t.xmppVcardServerDomain}/api/vcard/${r[1]}@${r[2]}/DESC`:null,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},qr:e}},r.tests=[{uri:"xmpp:alice@domain.org",shouldMatch:!0},{uri:"xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{}],25:[function(e,t,r){(function(t){(function(){e("dotenv").config();const o=t.env.DOIP_PROXY_HOSTNAME||"proxy.keyoxide.org";r.generateProxyURL=(e,t)=>`https://${o}/api/1/get/${e}/${encodeURIComponent(t)}`,r.generateClaim=(e,t)=>{switch(t){case"uri":return"openpgp4fpr:"+e;case"message":return`[Verifying my OpenPGP key: openpgp4fpr:${e}]`;case"fingerprint":return e;default:throw new Error("No valid claim format")}}}).call(this)}).call(this,e("_process"))},{_process:6,dotenv:4}]},{},[9])(9)})); +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).doip=t()}}((function(){return function t(e,r,o){function s(n,a){if(!r[n]){if(!e[n]){var c="function"==typeof require&&require;if(!a&&c)return c(n,!0);if(i)return i(n,!0);var u=new Error("Cannot find module '"+n+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[n]={exports:{}};e[n][0].call(l.exports,(function(t){return s(e[n][1][t]||t)}),l,l.exports,t,e,r,o)}return r[n].exports}for(var i="function"==typeof require&&require,n=0;n(r||(r=this.arrayBuffer()),r)}),this.headers={};for(const[e,r]of t.headers.entries())this.headers[e.toLowerCase()]=r}}e.exports=o(((t,e,r,o,i)=>async(n,a,c={})=>{n=i+(n||"");let u=new URL(n);if(o||(o={}),u.username&&(o.Authorization="Basic "+btoa(u.username+":"+u.password),u=new URL(u.protocol+"//"+u.host+u.pathname+u.search)),"https:"!==u.protocol&&"http:"!==u.protocol)throw new Error("Unknown protocol, "+u.protocol);if(a)if(a instanceof ArrayBuffer||ArrayBuffer.isView(a)||"string"==typeof a);else{if("object"!=typeof a)throw new Error("Unknown body type.");a=JSON.stringify(a),o["Content-Type"]="application/json"}c=new Headers({...o||{},...c});const l=await fetch(u,{method:e,headers:c,body:a});if(l.statusCode=l.status,!t.has(l.status))throw new s(l);return"json"===r?l.json():"buffer"===r?l.arrayBuffer():"string"===r?l.text():l}))},{"./core":2}],2:[function(t,e,r){"use strict";const o=new Set(["json","buffer","string"]);e.exports=t=>(...e)=>{const r=new Set;let s,i,n,a="";return e.forEach((t=>{if("string"==typeof t)if(t.toUpperCase()===t){if(s){throw new Error(`Can't set method to ${t}, already set to ${s}.`)}s=t}else if(t.startsWith("http:")||t.startsWith("https:"))a=t;else{if(!o.has(t))throw new Error("Unknown encoding, "+t);i=t}else if("number"==typeof t)r.add(t);else{if("object"!=typeof t)throw new Error("Unknown type: "+typeof t);if(Array.isArray(t)||t instanceof Set)t.forEach((t=>r.add(t)));else{if(n)throw new Error("Cannot set headers twice.");n=t}}})),s||(s="GET"),0===r.size&&r.add(200),t(r,s,i,n,a)}},{}],3:[function(t,e,r){},{}],4:[function(t,e,r){"use strict";e.exports=t=>{if("[object Object]"!==Object.prototype.toString.call(t))return!1;const e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}},{}],5:[function(t,e,r){"use strict";const o=t("is-plain-obj"),{hasOwnProperty:s}=Object.prototype,{propertyIsEnumerable:i}=Object,n=(t,e,r)=>Object.defineProperty(t,e,{value:r,writable:!0,enumerable:!0,configurable:!0}),a=this,c={concatArrays:!1,ignoreUndefined:!1},u=t=>{const e=[];for(const r in t)s.call(t,r)&&e.push(r);if(Object.getOwnPropertySymbols){const r=Object.getOwnPropertySymbols(t);for(const o of r)i.call(t,o)&&e.push(o)}return e};function l(t){return Array.isArray(t)?function(t){const e=t.slice(0,0);return u(t).forEach((r=>{n(e,r,l(t[r]))})),e}(t):o(t)?function(t){const e=null===Object.getPrototypeOf(t)?Object.create(null):{};return u(t).forEach((r=>{n(e,r,l(t[r]))})),e}(t):t}const p=(t,e,r,o)=>(r.forEach((r=>{void 0===e[r]&&o.ignoreUndefined||(r in t&&t[r]!==Object.getPrototypeOf(t)?n(t,r,h(t[r],e[r],o)):n(t,r,l(e[r])))})),t);function h(t,e,r){return r.concatArrays&&Array.isArray(t)&&Array.isArray(e)?((t,e,r)=>{let o=t.slice(0,0),i=0;return[t,e].forEach((e=>{const a=[];for(let r=0;r!a.includes(t))),r)})),o})(t,e,r):o(e)&&o(t)?p(t,e,u(e),r):l(e)}e.exports=function(...t){const e=h(l(c),this!==a&&this||{},c);let r={_:{}};for(const s of t)if(void 0!==s){if(!o(s))throw new TypeError("`"+s+"` is not an Option Object");r=h(r,{_:s},e)}return r._}},{"is-plain-obj":4}],6:[function(t,e,r){!function(t){"use strict";t.exports.is_uri=r,t.exports.is_http_uri=o,t.exports.is_https_uri=s,t.exports.is_web_uri=i,t.exports.isUri=r,t.exports.isHttpUri=o,t.exports.isHttpsUri=s,t.exports.isWebUri=i;var e=function(t){return t.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/)};function r(t){if(t&&!/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(t)&&!/%[^0-9a-f]/i.test(t)&&!/%[0-9a-f](:?[^0-9a-f]|$)/i.test(t)){var r,o,s,i,n,a="",c="";if(a=(r=e(t))[1],o=r[2],s=r[3],i=r[4],n=r[5],a&&a.length&&s.length>=0){if(o&&o.length){if(0!==s.length&&!/^\//.test(s))return}else if(/^\/\//.test(s))return;if(/^[a-z][a-z0-9\+\-\.]*$/.test(a.toLowerCase()))return c+=a+":",o&&o.length&&(c+="//"+o),c+=s,i&&i.length&&(c+="?"+i),n&&n.length&&(c+="#"+n),c}}}function o(t,o){if(r(t)){var s,i,n,a,c="",u="",l="",p="";if(c=(s=e(t))[1],u=s[2],i=s[3],n=s[4],a=s[5],c){if(o){if("https"!=c.toLowerCase())return}else if("http"!=c.toLowerCase())return;if(u)return/:(\d+)$/.test(u)&&(l=u.match(/:(\d+)$/)[0],u=u.replace(/:\d+$/,"")),p+=c+":",p+="//"+u,l&&(p+=l),p+=i,n&&n.length&&(p+="?"+n),a&&a.length&&(p+="#"+a),p}}}function s(t){return o(t,!0)}function i(t){return o(t)||s(t)}}(e)},{}],7:[function(t,e,r){const o=t("./utils"),s=(t,e,r,o,i)=>{let n;if(t.isVerified||!e)return t;if(Array.isArray(e))return e.forEach(((e,n)=>{t=s(t,e,r,o,i)})),t;if(0==r.length){switch(i){default:case"contains":n=new RegExp(o.replace("[","\\[").replace("]","\\]"),"gi"),t.isVerified=n.test(e.replace(/\r?\n|\r/,""));break;case"equals":t.isVerified=e.replace(/\r?\n|\r/,"").toLowerCase()==o.toLowerCase();break;case"oneOf":n=new RegExp(o,"gi"),t.isVerified=n.test(e.join("|"))}return t}try{r[0]}catch(e){return t.errors.push("err_data_structure_incorrect"),t}return t=s(t,e[r[0]],r.slice(1),o,i)};r.run=(t,e)=>{let r={isVerified:!1,errors:[]};switch(e.proof.format){case"json":r=s(r,t,e.claim.path,o.generateClaim(e.claim.fingerprint,e.claim.format),e.claim.relation);break;case"text":re=new RegExp(o.generateClaim(e.claim.fingerprint,e.claim.format),"gi"),r=re.test(t.replace(/\r?\n|\r/,""))}return r}},{"./utils":24}],8:[function(t,e,r){const o=t("merge-options"),s=t("valid-url"),i=t("./serviceproviders"),n=t("./claimVerification"),a=t("./utils");r.verify=async(t,e,r)=>{e||(e=null),r||(r={});if(r=o({returnMatchesOnly:!1,proxyPolicy:"adaptive",doipProxyHostname:"proxy.keyoxide.org"},r),!s.isUri(t))throw new Error("Not a valid URI");const a=i.match(t,r);if("returnMatchesOnly"in r&&r.returnMatchesOnly)return a;let c,u,l,p,h=!1,d=0;for(;!h&&d{let r,o=[];return i.forEach(((s,i)=>{r=n[s],r.reURI.test(t)&&o.push(r.processURI(t,e))})),o},r.directRequestHandler=async(t,e)=>{const r=await o(t.proof.fetch?t.proof.fetch:t.proof.uri,null,{Accept:"application/json"});switch(t.proof.format){case"json":return await r.json();case"text":return await r.text();default:throw new Error("No specified proof data format")}},r.proxyRequestHandler=async(t,e)=>{const r=t.proof.fetch?t.proof.fetch:t.proof.uri,i=await o(s.generateProxyURL(t.proof.format,r,e),null,{Accept:"application/json"});return(await i.json()).content}},{"./serviceproviders/devto":10,"./serviceproviders/discourse":11,"./serviceproviders/dns":12,"./serviceproviders/fediverse":13,"./serviceproviders/gitea":14,"./serviceproviders/github":15,"./serviceproviders/gitlab":16,"./serviceproviders/hackernews":17,"./serviceproviders/liberapay":18,"./serviceproviders/lobsters":19,"./serviceproviders/mastodon":20,"./serviceproviders/reddit":21,"./serviceproviders/twitter":22,"./serviceproviders/xmpp":23,"./utils":24,bent:1}],10:[function(t,e,r){const o=/^https:\/\/dev\.to\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"devto"},profile:{display:r[1],uri:"https://dev.to/"+r[1],qr:null},proof:{uri:t,fetch:`https://dev.to/api/articles/${r[1]}/${r[2]}`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["body_markdown"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://dev.to/alice/post",shouldMatch:!0},{uri:"https://dev.to/alice/post/",shouldMatch:!0},{uri:"https://domain.org/alice/post",shouldMatch:!1}]},{}],11:[function(t,e,r){const o=/^https:\/\/(.*)\/u\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"discourse"},profile:{display:`${r[2]}@${r[1]}`,uri:t,qr:null},proof:{uri:t,fetch:`https://${r[1]}/u/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["user","bio_raw"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/u/alice",shouldMatch:!0},{uri:"https://domain.org/u/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],12:[function(t,e,r){const o=t("dns"),s=t("bent")("GET"),i=t("../utils"),n=/^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/,a=async(t,e)=>{if("resolveTxt"in o){const e=async()=>new Promise(((e,r)=>{o.resolveTxt(t.profile.display,((t,o)=>{t&&r(t),e(o)}))}));return{hostname:t.profile.display,records:{txt:await e()}}}{const e=await s(t.proof.uri,null,{Accept:"application/json"});return await e.json()}};r.reURI=n,r.processURI=(t,e)=>{e||(e={});const r=t.match(n);return{serviceprovider:{type:"web",name:"dns"},profile:{display:r[1],uri:"https://"+r[1],qr:null},proof:{uri:i.generateProxyURL("dns",r[1]),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"uri",path:["records","txt"],relation:"contains"},customRequestHandler:a}},r.tests=[{uri:"dns:domain.org",shouldMatch:!0},{uri:"dns:domain.org?type=TXT",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":24,bent:1,dns:3}],13:[function(t,e,r){const o=/^https:\/\/(.*)\/users\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"fediverse"},profile:{display:`@${r[2]}@${r[1]}`,uri:t,qr:null},proof:{uri:t,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["summary"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/users/alice",shouldMatch:!0},{uri:"https://domain.org/users/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],14:[function(t,e,r){const o=/^https:\/\/(.*)\/(.*)\/gitea_proof\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"gitea"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:t,fetch:`https://${r[1]}/api/v1/repos/${r[2]}/gitea_proof`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/alice/gitea_proof",shouldMatch:!0},{uri:"https://domain.org/alice/gitea_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{}],15:[function(t,e,r){const o=/^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"github"},profile:{display:r[1],uri:"https://github.com/"+r[1],qr:null},proof:{uri:t,fetch:"https://api.github.com/gists/"+r[2],useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["files","openpgp.md","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://gist.github.com/Alice/123456789",shouldMatch:!0},{uri:"https://gist.github.com/Alice/123456789/",shouldMatch:!0},{uri:"https://domain.org/Alice/123456789",shouldMatch:!1}]},{}],16:[function(t,e,r){const o=t("bent")("GET"),s=/^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/,i=async(t,e)=>{const r=t.proof.uri.match(s),i=`https://${r[1]}/api/v4/users?username=${r[2]}`,n=await o(i,"json",{Accept:"application/json"}),a=(await n.json()).find((t=>t.username===r[2]));if(!a)throw new Error("No user with username "+r[2]);const c=`https://${r[1]}/api/v4/users/${a.id}/projects`,u=await o(c,{},{Accept:"application/json"}),l=(await u.json()).find((t=>"gitlab_proof"===t.path));if(!l)throw new Error("No project at "+t.proof.uri);return l};r.reURI=s,r.processURI=(t,e)=>{e||(e={});const r=t.match(s);return{serviceprovider:{type:"web",name:"gitlab"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:t,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:i}},r.tests=[{uri:"https://gitlab.domain.org/alice/gitlab_proof",shouldMatch:!0},{uri:"https://gitlab.domain.org/alice/gitlab_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{bent:1}],17:[function(t,e,r){const o=/^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"hackernews"},profile:{display:r[1],uri:t,qr:null},proof:{uri:`https://hacker-news.firebaseio.com/v0/user/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"uri",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://news.ycombinator.com/user?id=Alice",shouldMatch:!0},{uri:"https://news.ycombinator.com/user?id=Alice/",shouldMatch:!0},{uri:"https://domain.org/user?id=Alice",shouldMatch:!1}]},{}],18:[function(t,e,r){const o=/^https:\/\/liberapay\.com\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"liberapay"},profile:{display:r[1],uri:t,qr:null},proof:{uri:t,fetch:`https://liberapay.com/${r[1]}/public.json`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["statements","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://liberapay.com/alice",shouldMatch:!0},{uri:"https://liberapay.com/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],19:[function(t,e,r){const o=/^https:\/\/lobste\.rs\/u\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"lobsters"},profile:{display:r[1],uri:t,qr:null},proof:{uri:`https://lobste.rs/u/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://lobste.rs/u/Alice",shouldMatch:!0},{uri:"https://lobste.rs/u/Alice/",shouldMatch:!0},{uri:"https://domain.org/u/Alice",shouldMatch:!1}]},{}],20:[function(t,e,r){const o=/^https:\/\/(.*)\/@(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"mastodon"},profile:{display:`@${r[2]}@${r[1]}`,uri:t,qr:null},proof:{uri:t,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["attachment","value"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/@alice",shouldMatch:!0},{uri:"https://domain.org/@alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],21:[function(t,e,r){const o=/^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(.*)\/(.*)\/?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"reddit"},profile:{display:r[1],uri:"https://www.reddit.com/user/"+r[1],qr:null},proof:{uri:t,fetch:`https://www.reddit.com/user/${r[1]}/comments/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["data","children","data","selftext"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://www.reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://www.reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://domain.org/user/Alice/comments/123456/post",shouldMatch:!1}]},{}],22:[function(t,e,r){const o=/^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"web",name:"twitter"},profile:{display:"@"+r[1],uri:"https://twitter.com/"+r[1],qr:null},proof:{uri:t,fetch:`https://mobile.twitter.com/${r[1]}/status/${r[2]}`,useProxy:!1,format:"text"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://twitter.com/alice/status/1234567890123456789",shouldMatch:!0},{uri:"https://twitter.com/alice/status/1234567890123456789/",shouldMatch:!0},{uri:"https://domain.org/alice/status/1234567890123456789",shouldMatch:!1}]},{}],23:[function(t,e,r){const o=/^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/;r.reURI=o,r.processURI=(t,e)=>{e||(e={});const r=t.match(o);return{serviceprovider:{type:"communication",name:"xmpp"},profile:{display:`${r[1]}@${r[2]}`,uri:t,qr:t},proof:{uri:"xmppVcardServerDomain"in e?`https://${e.xmppVcardServerDomain}/api/vcard/${r[1]}@${r[2]}/DESC`:null,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"xmpp:alice@domain.org",shouldMatch:!0},{uri:"xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{}],24:[function(t,e,r){r.generateProxyURL=(t,e,r)=>r&&r.doipProxyHostname?`https://${r.doipProxyHostname}/api/1/get/${t}/${encodeURIComponent(e)}`:null,r.generateClaim=(t,e)=>{switch(e){case"uri":return"openpgp4fpr:"+t;case"message":return`[Verifying my OpenPGP key: openpgp4fpr:${t}]`;case"fingerprint":return t;default:throw new Error("No valid claim format")}}},{}]},{},[8])(8)})); diff --git a/docs/changelog.md b/docs/changelog.md index 70b7569..a013d37 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,24 @@ # Changelog +## 0.4.0 + +[2020-11-06](https://codeberg.org/keyoxide/doipjs/releases/tag/0.4.0) + +### Added +- Custom request handler for DNS service provider +- Docs + +### Changed +- Service provider data structure +- More consistent handling of options + +### Removed +- dotenv dependency + +### Fixed +- Crash for unexpected JSON data structure +- Body in http requests + ## 0.3.0 [2020-11-04](https://codeberg.org/keyoxide/doipjs/releases/tag/0.3.0) diff --git a/package.json b/package.json index 1c22c38..10be225 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doipjs", - "version": "0.3.0", + "version": "0.4.0", "description": "Decentralized OpenPGP Identity Proofs library in node", "main": "src/index.js", "dependencies": {