From 751a3a97c38a4d9e8e0e075e84d845860d3cf8eb Mon Sep 17 00:00:00 2001 From: Semisol Date: Thu, 7 Oct 2021 12:47:33 +0300 Subject: [PATCH] Initial commit --- .gitignore | 4 + LICENSE | 11 + README.md | 3 + config.example.json | 26 +++ index.js | 367 +++++++++++++++++++++++++++++ package.json | 16 ++ pnpm-lock.yaml | 549 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 976 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config.example.json create mode 100644 index.js create mode 100644 package.json create mode 100644 pnpm-lock.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77492e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +data.json +config.json +node_modules \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c49648c --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright 2021 Semisol + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b093d36 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# CertServ + +Certificate expiry utilities \ No newline at end of file diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..3bc81a8 --- /dev/null +++ b/config.example.json @@ -0,0 +1,26 @@ +{ + "user": { + "nick": "CertServ", + "ident": "certserv", + "gecos": "CertServ", + "oper": { + "name": "CertServ", + "password": "password" + } + }, + "channels": [ + "#services" + ], + "server": { + "host": "localhost", + "port": 6697, + "secure": true + }, + "timeout": 10000, + "rate": 10, + "log": true, + "prefix": ".", + "overrideHost": { + "example-irc-server-name.invalid": "example.com" + } +} \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..b43cb26 --- /dev/null +++ b/index.js @@ -0,0 +1,367 @@ +const fs = require("fs") +const tls = require("tls") +const IRC = require("irc-framework") +const statsRegexp = /^\*\*\* Listener on .+:([0-9]+) \(IPv(?:4|6)\): has [0-9]+ client\(s\), options: (.*)$/ +let config = JSON.parse(fs.readFileSync(__dirname + "/config.json")) +let state = { + expiryState: {}, + networkState: {}, + expiryLastUpdated: Date.now(), + networkLastUpdated: Date.now() +} +if (fs.existsSync(__dirname + "/data.json")) { + state = JSON.parse(fs.readFileSync(__dirname + "/data.json")) +} else { + saveState() +} +let temp = { + expiryState: null, + queue: [], + networkState: null, + pendingStats: new Set(), + refreshCallbacks: [], + rev: 0, + inProgress: 0, + isRefreshAll: false +} +process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0 +function log(str, ...args) { + if (config.log) { + console.log(str, ...args) + } +} +const bot = new IRC.Client({ + nick: config.user.nick, + username: config.user.ident, + gecos: config.user.gecos, + version: "CertServ", + host: config.server.host, + tls: config.server.secure, + port: config.server.port +}) +bot.on("registered", () => { + bot.raw("oper", config.user.oper.name, config.user.oper.password) + config.channels.forEach(channel => { + bot.join(channel) + }) + refreshState() +}) +function saveState() { + fs.writeFileSync(__dirname + "/data.json", JSON.stringify(state)) + log("Persisted data to disk") +} +function refreshState() { + bot.raw("links") + log("Refreshing network state") +} +bot.on("server links", (links) => { + log("Got link data") + let servers = new Set() + let rev = ++temp.rev + temp.networkState = {} + temp.pendingStats = new Set() + links.links.forEach(link => { + servers.add(link.address) + servers.add(link.access_via) + }) + servers = [...servers] + log("Got %s servers", servers.length) + servers.forEach(el => { + temp.networkState[el] = { + c2s: [], + s2s: [] + } + temp.pendingStats.add(el) + bot.raw("stats", "P", el) + }) + setTimeout(() => { + if (rev !== temp.rev) return + let deleted = 0 + for (let i of temp.pendingStats) { + delete temp.networkState[i] + deleted++ + } + temp.pendingStats.clear() + state.networkState = temp.networkState + state.networkLastUpdated = Date.now() + temp.networkState = null + saveState() + log("State refresh complete with %s not responding", deleted) + temp.refreshCallbacks.forEach(cb => cb()) + temp.refreshCallbacks = [] + }, 3000) +}) +bot.on("notice", notice => { + let match + if (notice.from_server && notice.target === config.user.nick && temp.pendingStats.has(notice.hostname) && (match = notice.message.match(statsRegexp))) { + let server = notice.hostname + let opts = match[2].replace(/ +$/, "").split(" ") + let port = +match[1] + if (!opts.includes("tls")) return + let arr = temp.networkState[server][opts.includes("serversonly") ? "s2s" : "c2s"] + if (!arr.includes(port)) { + arr.push(port) + } + } +}) +bot.on("raw", line => { + if (!line.from_server) return + let match + if (match = line.line.match(/:([^ ]+) 219 [^ ]+ P :End of \/STATS report\r?\n/)) { + temp.pendingStats.delete(match[1]) + } +}) + +bot.on("privmsg", msg => { + if (msg.batch && msg.batch.type === "chathistory") return + if (config.channels.includes(msg.target) && msg.message.length > config.prefix.length && msg.message.startsWith(config.prefix)) { + let args = msg.message.slice(config.prefix.length).split(" ") + let cmd = args.shift() + switch (cmd) { + case "help": { + msg.reply("CertServ is a utility to view information about certificate expiry.") + msg.reply("Source: https://git.semisol.dev/Semisol/CertServ") + msg.reply(" help: Get this message") + msg.reply(" refreshnet: Refresh network state") + msg.reply(" refresh : Refresh a server") + msg.reply(" check : Check a server") + msg.reply(" refreshall: Refresh all servers") + msg.reply(" info: Show information about the bot, and statistics") + msg.reply(" expired: Show expired certificates") + msg.reply(" expiringsoon: Show certificates expiring in 7 days") + break + } + case "refresh": { + if (args.length === 0) { + msg.reply(`ERROR: Please provide a server argument`) + return + } + if (!state.networkState[args[0]]) { + msg.reply(`ERROR: No such server`) + return + } + let ports = state.networkState[args[0]] + delete temp.expiryState[args[0]] + for (let i of ports.c2s) { + temp.queue.push({ + server: args[0], + addr: config.overrideHost[args[0]] || args[0], + port: i, + type: "c2s" + }) + } + for (let i of ports.s2s) { + temp.queue.push({ + server: args[0], + addr: config.overrideHost[args[0]] || args[0], + port: i, + type: "s2s" + }) + } + msg.reply(`Added ${ports.s2s.length + ports.c2s.length} jobs`) + break + } + case "refreshnet": { + temp.refreshCallbacks.push(function () { + msg.reply("Done!") + }) + msg.reply("Please wait...") + refreshState() + break + } + case "refreshall": { + let jobs = 0 + let servers = 0 + temp.expiryState = {} + temp.isRefreshAll = true + Object.keys(state.networkState).forEach(srv => { + let ports = state.networkState[srv] + for (let i of ports.c2s) { + temp.queue.push({ + server: srv, + addr: config.overrideHost[srv] || srv, + port: i, + type: "c2s" + }) + jobs++ + } + for (let i of ports.s2s) { + temp.queue.push({ + server: srv, + addr: config.overrideHost[srv] || srv, + port: i, + type: "s2s" + }) + jobs++ + } + servers++ + }) + msg.reply(`Added ${jobs} jobs (${servers} servers)`) + log("Refreshing all...") + break + } + case "check": { + if (args.length === 0) { + msg.reply(`ERROR: Please provide a server argument`) + return + } + if (!state.expiryState[args[0]]) { + if (!state.networkState[args[0]]) { + msg.reply(`ERROR: No such server`) + } else { + msg.reply(`ERROR: Please \`refresh\` the server, as it has not been processed yet.`) + } + return + } + let seenInvalid = false + msg.reply(`Server information for ${args[0]}:`) + state.expiryState[args[0]].checks.forEach(check => { + let addr = `${args[0] === check.addr ? `Port ` : `${check.addr}:`}${check.port} (${check.type.toUpperCase()})` + switch (check.status) { + case "success": { + if (check.expiryTS > Date.now()) { + if (check.valid) seenInvalid = true + msg.reply(` ${addr}: Expires in ${((check.expiryTS - Date.now()) / 86400000).toFixed(2)}d (${check.expiry})${check.valid ? "" : " (!)"}`) + } else { + msg.reply(` ${addr}: Expired ${((Date.now() - check.expiryTS) / 86400000).toFixed(2)}d ago (${check.expiry})`) + } + break + } + case "timeout": { + msg.reply(` ${addr}: Timed out while connecting`) + break + } + case "error": { + msg.reply(` ${addr}: Encountered error while connecting`) + break + } + } + }) + if (seenInvalid) msg.reply(`(!): Self signed, wrong domain or something else`) + break + } + case "info": { + msg.reply(`CertServ version 1.0.0`) + if (temp.pendingStats.length > 0) { + msg.reply(`Network refresh: Waiting for ${temp.pendingStats.length} server${temp.pendingStats.length === 1 ? "" : "s"}`) + } else if (temp.networkState) { + msg.reply(`Network refresh: Waiting...`) + } + if (temp.queue.length > 0 || temp.inProgress > 0) { + msg.reply(`Expiry refresh: ${temp.queue.length} in queue`) + msg.reply(`Expiry refresh: Waiting for ${temp.inProgress} connection${temp.inProgress === 1 ? "" : "s"}`) + msg.reply(`Expiry refresh: Processing ${config.rate} job${config.rate === 1 ? "" : "s"} per second`) + } + msg.reply(`Network state: ${Object.keys(state.networkState).length} servers`) + msg.reply(`Network state: Last updated ${((Date.now() - state.networkLastUpdated) / 1000 / 60).toFixed(2)}m ago`) + msg.reply(`Expiry state: ${Object.keys(state.expiryState).length} servers`) + msg.reply(`Expiry state: Last updated ${((Date.now() - state.expiryLastUpdated) / 1000 / 60 / 60).toFixed(2)}h ago`) + if (temp.expiryState && temp.queue.length === 0 && temp.inProgress === 0) + msg.reply(`WARNING: No jobs are running but a transient state exists`) + break + } + case "expiringsoon": { + let checks = [] + msg.reply(`Certificates expiring soon:`) + Object.keys(state.expiryState).forEach(srv => { + state.expiryState[srv].checks.forEach(check => { + if (check.status !== "success") return + if (check.expiryTS < (Date.now() + (7 * 24 * 60 * 60 * 1000)) && check.expiryTS > Date.now()) { + checks.push({...check, server: srv}) + } + }) + }) + checks.sort((b, a) => a.expiryTS - b.expiryTS) + checks.forEach(check => { + let addr = `${check.addr}:${check.port}${check.server !== check.addr ? ` (${check.server})` : `` } (${check.type.toUpperCase()})` + msg.reply(` ${addr}, in ${((check.expiryTS - Date.now()) / 86400000).toFixed(2)}d`) + }) + if (checks.length === 0) msg.reply("None! \\o/") + break + } + case "expired": { + let checks = [] + msg.reply(`Certificates that expired:`) + Object.keys(state.expiryState).forEach(srv => { + state.expiryState[srv].checks.forEach(check => { + if (check.status !== "success") return + if (check.expiryTS < Date.now()) { + checks.push({...check, server: srv}) + } + }) + }) + checks.sort((b, a) => a.expiryTS - b.expiryTS) + checks.forEach(check => { + let addr = `${check.addr}:${check.port}${check.server !== check.addr ? ` (${check.server})` : `` } (${check.type.toUpperCase()})` + msg.reply(` ${addr}, ${((Date.now() - check.expiryTS) / 86400000).toFixed(2)}d ago`) + }) + if (checks.length === 0) msg.reply("None! \\o/") + break + } + } + } +}) + +setInterval(() => { + if (temp.queue.length > 0) { + if (!temp.expiryState) { + temp.expiryState = { ...state.expiryState } + log("Copying original state to transient") + } + let job = temp.queue.shift() + log("Starting job %s, %s:%s, %s", job.server, job.addr, job.port, job.type) + temp.inProgress++ + let hasFinished = false + let res = { + addr: job.addr, + type: job.type, + port: job.port, + status: "unknown" + } + function jobEnded() { + temp.inProgress-- + hasFinished = true + log("Ended job %s, %s:%s, %s with status %s", job.server, job.addr, job.port, job.type, res.status) + if (!temp.expiryState[job.server]) { + temp.expiryState[job.server] = { + checks: [] + } + } + temp.expiryState[job.server].checks.push(res) + if (temp.inProgress === 0 && temp.queue.length === 0) { + log("Replaced original state with transient state") + state.expiryState = temp.expiryState + temp.expiryState = null + saveState() + } + } + let conn = tls.connect({ + host: job.server, + port: job.port, + timeout: config.timeout + }, () => { + if (hasFinished) return + let cert = conn.getPeerX509Certificate() + res.status = "success" + res.expiry = cert.validTo + res.expiryTS = +new Date(cert.validTo) + res.valid = conn.authorized + jobEnded() + conn.end() + }) + conn.on("error", () => { + if (hasFinished) return + res.status = "error" + jobEnded() + conn.end() + }) + conn.on("timeout", () => { + if (hasFinished) return + res.status = "timeout" + jobEnded() + conn.end() + }) + } +}, 1000 / config.rate) + +bot.connect() \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ab908c --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "certserv", + "version": "1.0.0", + "description": "Certificate expiry utilities", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Semisol", + "license": "BSD-3-Clause", + "keywords": [], + "dependencies": { + "irc-framework": "^4.11.0" + }, + "devDependencies": {} +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9cec8bb --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,549 @@ +lockfileVersion: 5.3 + +specifiers: + irc-framework: ^4.11.0 + +dependencies: + irc-framework: registry.npmjs.org/irc-framework/4.11.0 + +packages: + + registry.npmjs.org/available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz} + name: available-typed-arrays + version: 1.0.5 + engines: {node: '>= 0.4'} + dev: false + + registry.npmjs.org/base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz} + name: base64-js + version: 1.5.1 + dev: false + + registry.npmjs.org/buffer/6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz} + name: buffer + version: 6.0.3 + dependencies: + base64-js: registry.npmjs.org/base64-js/1.5.1 + ieee754: registry.npmjs.org/ieee754/1.2.1 + dev: false + + registry.npmjs.org/call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz} + name: call-bind + version: 1.0.2 + dependencies: + function-bind: registry.npmjs.org/function-bind/1.1.1 + get-intrinsic: registry.npmjs.org/get-intrinsic/1.1.1 + dev: false + + registry.npmjs.org/core-js/3.18.2: + resolution: {integrity: sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/core-js/-/core-js-3.18.2.tgz} + name: core-js + version: 3.18.2 + requiresBuild: true + dev: false + + registry.npmjs.org/define-properties/1.1.3: + resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz} + name: define-properties + version: 1.1.3 + engines: {node: '>= 0.4'} + dependencies: + object-keys: registry.npmjs.org/object-keys/1.1.1 + dev: false + + registry.npmjs.org/es-abstract/1.19.1: + resolution: {integrity: sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz} + name: es-abstract + version: 1.19.1 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + es-to-primitive: registry.npmjs.org/es-to-primitive/1.2.1 + function-bind: registry.npmjs.org/function-bind/1.1.1 + get-intrinsic: registry.npmjs.org/get-intrinsic/1.1.1 + get-symbol-description: registry.npmjs.org/get-symbol-description/1.0.0 + has: registry.npmjs.org/has/1.0.3 + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + internal-slot: registry.npmjs.org/internal-slot/1.0.3 + is-callable: registry.npmjs.org/is-callable/1.2.4 + is-negative-zero: registry.npmjs.org/is-negative-zero/2.0.1 + is-regex: registry.npmjs.org/is-regex/1.1.4 + is-shared-array-buffer: registry.npmjs.org/is-shared-array-buffer/1.0.1 + is-string: registry.npmjs.org/is-string/1.0.7 + is-weakref: registry.npmjs.org/is-weakref/1.0.1 + object-inspect: registry.npmjs.org/object-inspect/1.11.0 + object-keys: registry.npmjs.org/object-keys/1.1.1 + object.assign: registry.npmjs.org/object.assign/4.1.2 + string.prototype.trimend: registry.npmjs.org/string.prototype.trimend/1.0.4 + string.prototype.trimstart: registry.npmjs.org/string.prototype.trimstart/1.0.4 + unbox-primitive: registry.npmjs.org/unbox-primitive/1.0.1 + dev: false + + registry.npmjs.org/es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz} + name: es-to-primitive + version: 1.2.1 + engines: {node: '>= 0.4'} + dependencies: + is-callable: registry.npmjs.org/is-callable/1.2.4 + is-date-object: registry.npmjs.org/is-date-object/1.0.5 + is-symbol: registry.npmjs.org/is-symbol/1.0.4 + dev: false + + registry.npmjs.org/eventemitter3/4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz} + name: eventemitter3 + version: 4.0.7 + dev: false + + registry.npmjs.org/fast-text-encoding/1.0.3: + resolution: {integrity: sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz} + name: fast-text-encoding + version: 1.0.3 + dev: false + + registry.npmjs.org/foreach/2.0.5: + resolution: {integrity: sha1-C+4AUBiusmDQo6865ljdATbsG5k=, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz} + name: foreach + version: 2.0.5 + dev: false + + registry.npmjs.org/function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz} + name: function-bind + version: 1.1.1 + dev: false + + registry.npmjs.org/get-intrinsic/1.1.1: + resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz} + name: get-intrinsic + version: 1.1.1 + dependencies: + function-bind: registry.npmjs.org/function-bind/1.1.1 + has: registry.npmjs.org/has/1.0.3 + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + dev: false + + registry.npmjs.org/get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz} + name: get-symbol-description + version: 1.0.0 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + get-intrinsic: registry.npmjs.org/get-intrinsic/1.1.1 + dev: false + + registry.npmjs.org/grapheme-splitter/1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz} + name: grapheme-splitter + version: 1.0.4 + dev: false + + registry.npmjs.org/has-bigints/1.0.1: + resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz} + name: has-bigints + version: 1.0.1 + dev: false + + registry.npmjs.org/has-symbols/1.0.2: + resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz} + name: has-symbols + version: 1.0.2 + engines: {node: '>= 0.4'} + dev: false + + registry.npmjs.org/has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz} + name: has-tostringtag + version: 1.0.0 + engines: {node: '>= 0.4'} + dependencies: + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + dev: false + + registry.npmjs.org/has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/has/-/has-1.0.3.tgz} + name: has + version: 1.0.3 + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: registry.npmjs.org/function-bind/1.1.1 + dev: false + + registry.npmjs.org/iconv-lite/0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz} + name: iconv-lite + version: 0.6.3 + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: registry.npmjs.org/safer-buffer/2.1.2 + dev: false + + registry.npmjs.org/ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz} + name: ieee754 + version: 1.2.1 + dev: false + + registry.npmjs.org/inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz} + name: inherits + version: 2.0.4 + dev: false + + registry.npmjs.org/internal-slot/1.0.3: + resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz} + name: internal-slot + version: 1.0.3 + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: registry.npmjs.org/get-intrinsic/1.1.1 + has: registry.npmjs.org/has/1.0.3 + side-channel: registry.npmjs.org/side-channel/1.0.4 + dev: false + + registry.npmjs.org/ip/1.1.5: + resolution: {integrity: sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/ip/-/ip-1.1.5.tgz} + name: ip + version: 1.1.5 + dev: false + + registry.npmjs.org/irc-framework/4.11.0: + resolution: {integrity: sha512-A7AoNxAGzViARQv4sVchmTzRiWiQZMCuQVnCOhrggEgAMsc8Vr345U5/JMN5I45gqL4LVfjtruWokp5YiU23Iw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/irc-framework/-/irc-framework-4.11.0.tgz} + name: irc-framework + version: 4.11.0 + dependencies: + buffer: registry.npmjs.org/buffer/6.0.3 + core-js: registry.npmjs.org/core-js/3.18.2 + eventemitter3: registry.npmjs.org/eventemitter3/4.0.7 + grapheme-splitter: registry.npmjs.org/grapheme-splitter/1.0.4 + iconv-lite: registry.npmjs.org/iconv-lite/0.6.3 + isomorphic-textencoder: registry.npmjs.org/isomorphic-textencoder/1.0.1 + lodash: registry.npmjs.org/lodash/4.17.21 + middleware-handler: registry.npmjs.org/middleware-handler/0.2.0 + regenerator-runtime: registry.npmjs.org/regenerator-runtime/0.13.9 + socks: registry.npmjs.org/socks/2.6.1 + stream-browserify: registry.npmjs.org/stream-browserify/3.0.0 + util: registry.npmjs.org/util/0.12.4 + dev: false + + registry.npmjs.org/is-arguments/1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz} + name: is-arguments + version: 1.1.1 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz} + name: is-bigint + version: 1.0.4 + dependencies: + has-bigints: registry.npmjs.org/has-bigints/1.0.1 + dev: false + + registry.npmjs.org/is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz} + name: is-boolean-object + version: 1.1.2 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-callable/1.2.4: + resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz} + name: is-callable + version: 1.2.4 + engines: {node: '>= 0.4'} + dev: false + + registry.npmjs.org/is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz} + name: is-date-object + version: 1.0.5 + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-generator-function/1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz} + name: is-generator-function + version: 1.0.10 + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-negative-zero/2.0.1: + resolution: {integrity: sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz} + name: is-negative-zero + version: 2.0.1 + engines: {node: '>= 0.4'} + dev: false + + registry.npmjs.org/is-number-object/1.0.6: + resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz} + name: is-number-object + version: 1.0.6 + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz} + name: is-regex + version: 1.1.4 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-shared-array-buffer/1.0.1: + resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz} + name: is-shared-array-buffer + version: 1.0.1 + dev: false + + registry.npmjs.org/is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz} + name: is-string + version: 1.0.7 + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz} + name: is-symbol + version: 1.0.4 + engines: {node: '>= 0.4'} + dependencies: + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + dev: false + + registry.npmjs.org/is-typed-array/1.1.8: + resolution: {integrity: sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz} + name: is-typed-array + version: 1.1.8 + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: registry.npmjs.org/available-typed-arrays/1.0.5 + call-bind: registry.npmjs.org/call-bind/1.0.2 + es-abstract: registry.npmjs.org/es-abstract/1.19.1 + foreach: registry.npmjs.org/foreach/2.0.5 + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + dev: false + + registry.npmjs.org/is-weakref/1.0.1: + resolution: {integrity: sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz} + name: is-weakref + version: 1.0.1 + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + dev: false + + registry.npmjs.org/isomorphic-textencoder/1.0.1: + resolution: {integrity: sha512-676hESgHullDdHDsj469hr+7t3i/neBKU9J7q1T4RHaWwLAsaQnywC0D1dIUId0YZ+JtVrShzuBk1soo0+GVcQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/isomorphic-textencoder/-/isomorphic-textencoder-1.0.1.tgz} + name: isomorphic-textencoder + version: 1.0.1 + dependencies: + fast-text-encoding: registry.npmjs.org/fast-text-encoding/1.0.3 + dev: false + + registry.npmjs.org/lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz} + name: lodash + version: 4.17.21 + dev: false + + registry.npmjs.org/middleware-handler/0.2.0: + resolution: {integrity: sha1-vwKvfmtXfAIwYJsq5Y3w5Ebz/QI=, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/middleware-handler/-/middleware-handler-0.2.0.tgz} + name: middleware-handler + version: 0.2.0 + dev: false + + registry.npmjs.org/object-inspect/1.11.0: + resolution: {integrity: sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz} + name: object-inspect + version: 1.11.0 + dev: false + + registry.npmjs.org/object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz} + name: object-keys + version: 1.1.1 + engines: {node: '>= 0.4'} + dev: false + + registry.npmjs.org/object.assign/4.1.2: + resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz} + name: object.assign + version: 4.1.2 + engines: {node: '>= 0.4'} + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + define-properties: registry.npmjs.org/define-properties/1.1.3 + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + object-keys: registry.npmjs.org/object-keys/1.1.1 + dev: false + + registry.npmjs.org/readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz} + name: readable-stream + version: 3.6.0 + engines: {node: '>= 6'} + dependencies: + inherits: registry.npmjs.org/inherits/2.0.4 + string_decoder: registry.npmjs.org/string_decoder/1.3.0 + util-deprecate: registry.npmjs.org/util-deprecate/1.0.2 + dev: false + + registry.npmjs.org/regenerator-runtime/0.13.9: + resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz} + name: regenerator-runtime + version: 0.13.9 + dev: false + + registry.npmjs.org/safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz} + name: safe-buffer + version: 5.2.1 + dev: false + + registry.npmjs.org/safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz} + name: safer-buffer + version: 2.1.2 + dev: false + + registry.npmjs.org/side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz} + name: side-channel + version: 1.0.4 + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + get-intrinsic: registry.npmjs.org/get-intrinsic/1.1.1 + object-inspect: registry.npmjs.org/object-inspect/1.11.0 + dev: false + + registry.npmjs.org/smart-buffer/4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz} + name: smart-buffer + version: 4.2.0 + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + + registry.npmjs.org/socks/2.6.1: + resolution: {integrity: sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/socks/-/socks-2.6.1.tgz} + name: socks + version: 2.6.1 + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: registry.npmjs.org/ip/1.1.5 + smart-buffer: registry.npmjs.org/smart-buffer/4.2.0 + dev: false + + registry.npmjs.org/stream-browserify/3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz} + name: stream-browserify + version: 3.0.0 + dependencies: + inherits: registry.npmjs.org/inherits/2.0.4 + readable-stream: registry.npmjs.org/readable-stream/3.6.0 + dev: false + + registry.npmjs.org/string.prototype.trimend/1.0.4: + resolution: {integrity: sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz} + name: string.prototype.trimend + version: 1.0.4 + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + define-properties: registry.npmjs.org/define-properties/1.1.3 + dev: false + + registry.npmjs.org/string.prototype.trimstart/1.0.4: + resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz} + name: string.prototype.trimstart + version: 1.0.4 + dependencies: + call-bind: registry.npmjs.org/call-bind/1.0.2 + define-properties: registry.npmjs.org/define-properties/1.1.3 + dev: false + + registry.npmjs.org/string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz} + name: string_decoder + version: 1.3.0 + dependencies: + safe-buffer: registry.npmjs.org/safe-buffer/5.2.1 + dev: false + + registry.npmjs.org/unbox-primitive/1.0.1: + resolution: {integrity: sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz} + name: unbox-primitive + version: 1.0.1 + dependencies: + function-bind: registry.npmjs.org/function-bind/1.1.1 + has-bigints: registry.npmjs.org/has-bigints/1.0.1 + has-symbols: registry.npmjs.org/has-symbols/1.0.2 + which-boxed-primitive: registry.npmjs.org/which-boxed-primitive/1.0.2 + dev: false + + registry.npmjs.org/util-deprecate/1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz} + name: util-deprecate + version: 1.0.2 + dev: false + + registry.npmjs.org/util/0.12.4: + resolution: {integrity: sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/util/-/util-0.12.4.tgz} + name: util + version: 0.12.4 + dependencies: + inherits: registry.npmjs.org/inherits/2.0.4 + is-arguments: registry.npmjs.org/is-arguments/1.1.1 + is-generator-function: registry.npmjs.org/is-generator-function/1.0.10 + is-typed-array: registry.npmjs.org/is-typed-array/1.1.8 + safe-buffer: registry.npmjs.org/safe-buffer/5.2.1 + which-typed-array: registry.npmjs.org/which-typed-array/1.1.7 + dev: false + + registry.npmjs.org/which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz} + name: which-boxed-primitive + version: 1.0.2 + dependencies: + is-bigint: registry.npmjs.org/is-bigint/1.0.4 + is-boolean-object: registry.npmjs.org/is-boolean-object/1.1.2 + is-number-object: registry.npmjs.org/is-number-object/1.0.6 + is-string: registry.npmjs.org/is-string/1.0.7 + is-symbol: registry.npmjs.org/is-symbol/1.0.4 + dev: false + + registry.npmjs.org/which-typed-array/1.1.7: + resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz} + name: which-typed-array + version: 1.1.7 + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: registry.npmjs.org/available-typed-arrays/1.0.5 + call-bind: registry.npmjs.org/call-bind/1.0.2 + es-abstract: registry.npmjs.org/es-abstract/1.19.1 + foreach: registry.npmjs.org/foreach/2.0.5 + has-tostringtag: registry.npmjs.org/has-tostringtag/1.0.0 + is-typed-array: registry.npmjs.org/is-typed-array/1.1.8 + dev: false