From 81934ff8920c78d8983e17dd2def597a8a5b830c Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Thu, 24 Nov 2022 10:10:55 +1300 Subject: [PATCH 01/17] test of minio writting --- app/index.js | 29 +- package-lock.json | 1597 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 3 files changed, 1601 insertions(+), 26 deletions(-) diff --git a/app/index.js b/app/index.js index 69373f7..4e3d1bc 100644 --- a/app/index.js +++ b/app/index.js @@ -2,14 +2,16 @@ import inject from 'seacreature/lib/inject' import pLimit from 'p-limit' import { exec } from 'child_process' import pg from 'pg' -import fs from 'fs/promises' +import fsp from 'fs/promises' +import fs from 'fs' +import Minio from 'minio' const assert_dir = async dir => { try { - await fs.access(dir) + await fsp.access(dir) } catch (err) { if (err.code === 'ENOENT') { - await fs.mkdir(dir, { recursive: true }) + await fsp.mkdir(dir, { recursive: true }) } else { throw err } @@ -35,6 +37,7 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => error(...args) reject(args[1]) } + const p = exec(command, { shell: '/bin/sh', ...options }) // p.on('spawn', () => // log(`${name} spawned`)) @@ -45,12 +48,25 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => complete_resolve(`${name} closed`, code) }) p.on('exit', async code => { + const [ table_dir, ...rest ] = name.split('.') + const table_file = rest.join('.') + const file_stream = await fs.createReadStream(`./data/${table_dir}/${table_file}.sql`) + const min = await minio.putObject(`${process.env.MINIO_BUCKET}`, `${table_dir}/${table_file}.sql`, file_stream) + const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) complete_resolve(`${name} exited`, code) }) // p.stdout.on('data', msg => log(msg)) // p.stderr.on('data', msg => error(msg)) }) +const minio = new Minio.Client({ + endPoint: process.env.MINIO_URL, + port: 9000, + useSSL: false, + accessKey: process.env.MINIO_ACCESS_KEY, + secretKey: process.env.MINIO_SECRET_KEY +}) + const db_options = name => ({ host: process.env.DB_HOST, user: process.env.DB_USER, @@ -105,6 +121,13 @@ inject('pod', async ({ boss }) => { log('Backing up tables') const limit = pLimit(10) await Promise.all(tasks.map(t => limit(t))) + + // const all_directories = await fsp.readdir('./data') + // const directories = all_directories.filter(p => p != 'README.md') + // for(const dir of directories) { + // await fs.rmdirSync(`./data/${dir}`) + // } + log('Backup complete') } catch(e) { error(`Error encountered during backup - ${e}`) diff --git a/package-lock.json b/package-lock.json index 022e9d0..d886637 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "cross-env": "^7.0.3", "dotenv": "^16.0.0", + "minio": "^7.0.32", "neo-blessed": "^0.2.0", "node-fetch": "^3.2.0", "p-limit": "^4.0.0", @@ -20,6 +21,12 @@ "telnet2": "^0.0.1" } }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -32,6 +39,128 @@ "node": ">=8" } }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/block-stream2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", + "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/browser-or-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz", + "integrity": "sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg==" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -40,6 +169,32 @@ "node": ">=4" } }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -48,6 +203,45 @@ "node": ">=6" } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "node_modules/cron-parser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.2.1.tgz", @@ -89,6 +283,27 @@ "node": ">= 8" } }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, "node_modules/data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -97,6 +312,14 @@ "node": ">= 12" } }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/delay": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", @@ -108,6 +331,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/dotenv": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", @@ -116,6 +363,54 @@ "node": ">=12" } }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/fast-xml-parser": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "dependencies": { + "strnum": "^1.0.4" + }, + "bin": { + "xml2js": "cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, "node_modules/fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -138,6 +433,22 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -149,6 +460,103 @@ "node": ">=12.20.0" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -157,11 +565,92 @@ "node": ">=8" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/json-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz", + "integrity": "sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -175,6 +664,108 @@ "node": "*" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minio": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/minio/-/minio-7.0.32.tgz", + "integrity": "sha512-txa7Vr0N24MKzeAybP/wY1jxbLnfGHXwZYyfFXuMW55HX2+HOcKEIgH4hU6Qj/kiMgyXs/ozHjAuLIDrR8nwLg==", + "dependencies": { + "async": "^3.1.0", + "block-stream2": "^2.0.0", + "browser-or-node": "^1.3.0", + "buffer-crc32": "^0.2.13", + "crypto-browserify": "^3.12.0", + "es6-error": "^4.1.1", + "fast-xml-parser": "^3.17.5", + "ipaddr.js": "^2.0.1", + "json-stream": "^1.0.0", + "lodash": "^4.17.21", + "mime-types": "^2.1.14", + "mkdirp": "^0.5.1", + "query-string": "^7.1.1", + "through2": "^3.0.1", + "web-encoding": "^1.1.5", + "xml": "^1.0.0", + "xml2js": "^0.4.15" + }, + "engines": { + "node": ">8 <=18" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/neo-blessed": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/neo-blessed/-/neo-blessed-0.2.0.tgz", @@ -254,6 +845,18 @@ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -262,6 +865,21 @@ "node": ">=8" } }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/pg": { "version": "8.7.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", @@ -387,43 +1005,213 @@ "node": ">=0.10.0" } }, - "node_modules/seacreature": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/seacreature/-/seacreature-2.17.0.tgz", - "integrity": "sha512-sivEzMuoGMpTwpVL4lZdjCoRkdDjZjlc2RJy5GzQCszBbOToxnvRYG+GbNKjhotqhBUO2yjmfgKF10U+bBoxag==" + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/query-string": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz", + "integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==", "dependencies": { - "shebang-regex": "^3.0.0" + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">= 10.x" + "node": ">= 6" } }, - "node_modules/telnet2": { - "version": "0.0.1", + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/seacreature": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/seacreature/-/seacreature-2.17.0.tgz", + "integrity": "sha512-sivEzMuoGMpTwpVL4lZdjCoRkdDjZjlc2RJy5GzQCszBbOToxnvRYG+GbNKjhotqhBUO2yjmfgKF10U+bBoxag==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/telnet2": { + "version": "0.0.1", "resolved": "https://registry.npmjs.org/telnet2/-/telnet2-0.0.1.tgz", "integrity": "sha1-Ts+LETwzp+B3CSxik+5CffMzKw0=" }, + "node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -432,6 +1220,17 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, "node_modules/web-streams-polyfill": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", @@ -454,6 +1253,50 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -475,6 +1318,12 @@ } }, "dependencies": { + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -484,16 +1333,195 @@ "indent-string": "^4.0.0" } }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "block-stream2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", + "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", + "requires": { + "readable-stream": "^3.4.0" + } + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "browser-or-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz", + "integrity": "sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg==" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "cron-parser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.2.1.tgz", @@ -520,21 +1548,113 @@ "which": "^2.0.1" } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, "data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==" + }, "delay": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==" }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, "dotenv": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "fast-xml-parser": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "requires": { + "strnum": "^1.0.4" + } + }, "fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -544,6 +1664,19 @@ "web-streams-polyfill": "^3.0.3" } }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -552,16 +1685,143 @@ "fetch-blob": "^3.1.2" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "json-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz", + "integrity": "sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -572,6 +1832,92 @@ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==" }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + }, + "minio": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/minio/-/minio-7.0.32.tgz", + "integrity": "sha512-txa7Vr0N24MKzeAybP/wY1jxbLnfGHXwZYyfFXuMW55HX2+HOcKEIgH4hU6Qj/kiMgyXs/ozHjAuLIDrR8nwLg==", + "requires": { + "async": "^3.1.0", + "block-stream2": "^2.0.0", + "browser-or-node": "^1.3.0", + "buffer-crc32": "^0.2.13", + "crypto-browserify": "^3.12.0", + "es6-error": "^4.1.1", + "fast-xml-parser": "^3.17.5", + "ipaddr.js": "^2.0.1", + "json-stream": "^1.0.0", + "lodash": "^4.17.21", + "mime-types": "^2.1.14", + "mkdirp": "^0.5.1", + "query-string": "^7.1.1", + "through2": "^3.0.1", + "web-encoding": "^1.1.5", + "xml": "^1.0.0", + "xml2js": "^0.4.15" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, "neo-blessed": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/neo-blessed/-/neo-blessed-0.2.0.tgz", @@ -613,11 +1959,35 @@ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pg": { "version": "8.7.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", @@ -709,11 +2079,102 @@ "xtend": "^4.0.0" } }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "query-string": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz", + "integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==", + "requires": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "seacreature": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/seacreature/-/seacreature-2.17.0.tgz", "integrity": "sha512-sivEzMuoGMpTwpVL4lZdjCoRkdDjZjlc2RJy5GzQCszBbOToxnvRYG+GbNKjhotqhBUO2yjmfgKF10U+bBoxag==" }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -727,21 +2188,79 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, "split2": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==" }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "telnet2": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/telnet2/-/telnet2-0.0.1.tgz", "integrity": "sha1-Ts+LETwzp+B3CSxik+5CffMzKw0=" }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, + "web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + } + }, "web-streams-polyfill": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", @@ -755,6 +2274,38 @@ "isexe": "^2.0.0" } }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 9463835..efc883e 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": { "cross-env": "^7.0.3", "dotenv": "^16.0.0", + "minio": "^7.0.32", "neo-blessed": "^0.2.0", "node-fetch": "^3.2.0", "p-limit": "^4.0.0", From 8a42793677dcd2862f33020a6d3a514961f74064 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Thu, 24 Nov 2022 10:15:54 +1300 Subject: [PATCH 02/17] remove file delete for test pass --- app/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index 4e3d1bc..4146ccc 100644 --- a/app/index.js +++ b/app/index.js @@ -52,7 +52,7 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => const table_file = rest.join('.') const file_stream = await fs.createReadStream(`./data/${table_dir}/${table_file}.sql`) const min = await minio.putObject(`${process.env.MINIO_BUCKET}`, `${table_dir}/${table_file}.sql`, file_stream) - const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) + // const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) complete_resolve(`${name} exited`, code) }) // p.stdout.on('data', msg => log(msg)) From 5437a209b5887fb6c5e77eeb7d985821586c7867 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Thu, 24 Nov 2022 11:04:05 +1300 Subject: [PATCH 03/17] add logging for audti table --- app/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/index.js b/app/index.js index 4146ccc..716c5dd 100644 --- a/app/index.js +++ b/app/index.js @@ -52,6 +52,11 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => const table_file = rest.join('.') const file_stream = await fs.createReadStream(`./data/${table_dir}/${table_file}.sql`) const min = await minio.putObject(`${process.env.MINIO_BUCKET}`, `${table_dir}/${table_file}.sql`, file_stream) + if(table_dir == 'audit') { + console.log('db: ', table_dir) + console.log('table: ', table_file) + console.log(min) + } // const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) complete_resolve(`${name} exited`, code) }) From e29c6f47114346e1143dda00c0c01936bb867467 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Thu, 24 Nov 2022 14:40:09 +1300 Subject: [PATCH 04/17] enable local file deletion --- app/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index 716c5dd..5ece6c7 100644 --- a/app/index.js +++ b/app/index.js @@ -57,7 +57,7 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => console.log('table: ', table_file) console.log(min) } - // const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) + const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) complete_resolve(`${name} exited`, code) }) // p.stdout.on('data', msg => log(msg)) From f4d9db8ed5414aa1ec5ae0c656a9d7bb481e2ded Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 10:58:45 +1300 Subject: [PATCH 05/17] rework for pgdump_all, add compression, minio writing, notifications, table exclusions for newer postgres and flags for logging and structure only --- .env-example | 33 +++-- app/backup.sh | 2 +- app/index.js | 287 ++++++++++++++++++++++++++++++--------- docker-compose.yml | 36 +++++ docker-postgres-init.sql | 1 + index.js | 2 + lib/discord.js | 32 +++++ lib/minio.js | 14 ++ lib/pg-boss.js | 2 +- lib/stats.js | 55 ++++++++ package-lock.json | 84 +++++++++++- package.json | 5 +- 12 files changed, 474 insertions(+), 79 deletions(-) create mode 100644 docker-compose.yml create mode 100644 docker-postgres-init.sql create mode 100644 lib/discord.js create mode 100644 lib/minio.js create mode 100644 lib/stats.js diff --git a/.env-example b/.env-example index f5bb4f2..6fa1cd9 100644 --- a/.env-example +++ b/.env-example @@ -1,3 +1,6 @@ +SERVER_NAME=ubuntu +CONTAINER_NAME=srv-captain--postgres-container + DB_HOST=localhost DB_PORT=5432 DB_DATABASE=postgres @@ -9,13 +12,27 @@ BOSS_USER=postgres BOSS_DATABASE=boss BOSS_PASSWORD=postgres BOSS_PORT=5432 -BOSS_APPLICATION_NAME=postgres-boss-backup +BOSS_APPLICATION_NAME=caprover-postgres-backup BOSS_SCHEMA=public -SCHEDULE=0 2 * * * -TZ=UTC -QUEUE=postgres-boss-backup -RETRY_LIMIT=0 -RETRY_DELAY=300 -RETRY_BACKOFF=0 -EXPIRE_MINUTES=180 +BOSS_SCHEDULE='0 1 * * *' +BOSS_RETRY_DELAY=300 +BOSS_RETRY_LIMIT=5 +BOSS_RETRY_BACKOFF=0 +BOSS_EXPIRE_MINUTES=30 +BOSS_TZ=Pacific/Auckland + +MINIO_URL=localhost +MINIO_PORT=9000 +MINIO_USE_SSL=0 +MINIO_ACCESS_KEY=minioadmin +MINIO_SECRET_KEY=minioadmin + +DISCORD_CHANNEL='discord_channel' +DISCORD_TOKEN='discord_token' +DISCORD_ICON='discord_icon' +DISCORD_NOTIFY=0 + +DATABASE_BLACKLIST= +DATABASE_STRUCTURE_ONLY=0 +DUMP_LOGGING=0 \ No newline at end of file diff --git a/app/backup.sh b/app/backup.sh index c105e42..a157946 100755 --- a/app/backup.sh +++ b/app/backup.sh @@ -1,4 +1,4 @@ #!/bin/sh set -e -pg_dump --compress=0 --format=plain --file=$BK_DATABASE/$BK_TABLE.sql --table=$BK_TABLE $BK_HOST/$BK_DATABASE \ No newline at end of file +pg_dumpall --compress=0 --format=plain --file=test.sql \ No newline at end of file diff --git a/app/index.js b/app/index.js index 5ece6c7..cb3a676 100644 --- a/app/index.js +++ b/app/index.js @@ -5,6 +5,8 @@ import pg from 'pg' import fsp from 'fs/promises' import fs from 'fs' import Minio from 'minio' +import { format } from 'date-fns' +import zlib from 'zlib' const assert_dir = async dir => { try { @@ -48,56 +50,95 @@ const launch = (name, command, options = {}) => new Promise((resolve, reject) => complete_resolve(`${name} closed`, code) }) p.on('exit', async code => { - const [ table_dir, ...rest ] = name.split('.') - const table_file = rest.join('.') - const file_stream = await fs.createReadStream(`./data/${table_dir}/${table_file}.sql`) - const min = await minio.putObject(`${process.env.MINIO_BUCKET}`, `${table_dir}/${table_file}.sql`, file_stream) - if(table_dir == 'audit') { - console.log('db: ', table_dir) - console.log('table: ', table_file) - console.log(min) - } - const file_del = await fs.unlinkSync(`./data/${table_dir}/${table_file}.sql`) complete_resolve(`${name} exited`, code) }) - // p.stdout.on('data', msg => log(msg)) - // p.stderr.on('data', msg => error(msg)) + p.stdout.on('data', msg => log(msg)) + p.stderr.on('data', msg => error(msg)) }) -const minio = new Minio.Client({ - endPoint: process.env.MINIO_URL, - port: 9000, - useSSL: false, - accessKey: process.env.MINIO_ACCESS_KEY, - secretKey: process.env.MINIO_SECRET_KEY -}) +const compress = (input_file, output_file) => new Promise((resolve, reject) => { + const read_stream = fs.createReadStream(input_file) + const write_stream = fs.createWriteStream(output_file) + const gzip = zlib.createGzip() -const db_options = name => ({ - host: process.env.DB_HOST, - user: process.env.DB_USER, - database: name || process.env.DB_DATABASE, - password: process.env.DB_PASSWORD, - port: process.env.DB_PORT + read_stream.pipe(gzip).pipe(write_stream) + + write_stream.on('close', () => { + resolve('file compressed successfully.') + }) + + write_stream.on('error', (error) => { + reject(error); + }) }) -inject('pod', async ({ boss }) => { - const name = process.env.QUEUE || 'postgres-boss-backup' - const db_host = `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}` - const pgdb = new Pool(db_options()) - pgdb.on('error', error) +const to_mins_and_seconds = async (ms) => { + const minutes = Math.floor(ms / 60000) + const seconds = ((ms % 60000) / 1000).toFixed(0) + return minutes + ":" + (seconds < 10 ? '0' : '') + seconds +} + +const format_string = async (text) => { + const formatted = text.split(' ').map(t => t.charAt(0).toUpperCase() + t.slice(1)) + return formatted.join('') +} + +inject('pod', async ({ boss, minio, discord }) => { + const { + BACKUP_DIRECTORY, + BOSS_APPLICATION_NAME, + BOSS_SCHEDULE, + BOSS_RETRY_DELAY, + BOSS_RETRY_LIMIT, + BOSS_RETRY_BACKOFF, + BOSS_EXPIRE_MINUTES, + BOSS_TZ, + CONTAINER_NAME, + DATABASE_BLACKLIST, + DATABASE_STRUCTURE_ONLY, + DB_HOST, + DB_PORT, + DB_USER, + DISCORD_ICON, + DUMP_LOGGING, + SERVER_NAME + } = process.env + + const job_prefix = 'postgres-backup' + + // check for minio bucket existence + const minio_bucket_check = async () => { + try { + const buckets = await minio.listBuckets() + const exists = buckets.find(b => b.name === SERVER_NAME.toLowerCase()) + if (!exists) { + await minio.makeBucket(SERVER_NAME.toLowerCase(), 'us-east-1') + console.log(`minio bucket '${SERVER_NAME.toLowerCase()}' created`) + } else { + console.log(`minio bucket '${SERVER_NAME.toLowerCase()}' already exists`) + } + } catch (err) { + console.log(`something went wrong verifying/creating a minio bucket for '${SERVER_NAME.toLowerCase()}'`) + console.log(err.message) + } + } + await minio_bucket_check() - await boss.work(name, async () => { + const postgres_backup = async (name) => { try { - log('Discovering databases') - const { rows: dats } = await pgdb.query('select datname from pg_database where datistemplate = false') - const databases = dats.map(d => d.datname) + log('queueing backup') const tasks = [] - const add_task = (d, t) => tasks.push(async () => { - const cmd = `pg_dump --compress=0 --format=plain --file=${t}.sql --table=${t} ${db_host}/${d}` - const dir = `${process.env.BK_DIR || `${process.cwd()}/data`}/${d}` + const add_task = (c) => tasks.push(async () => { + const verbose = DUMP_LOGGING ? '-v' : '' + const structure_only = DATABASE_STRUCTURE_ONLY ? '-s' : '' + const blacklist = DATABASE_BLACKLIST ? DATABASE_BLACKLIST.split(',') : [] + const exclusions = blacklist.length ? blacklist.map(db => `--exclude-database=${db}`).join(' ') : '' + + const cmd = `pg_dumpall -h ${DB_HOST} -p ${DB_PORT} ${verbose} ${structure_only} -U ${DB_USER} --file=${c}.sql ${exclusions}` + const dir = `${process.env.BK_DIR || `${process.cwd()}/data`}` await assert_dir(dir) try { - await launch(`${d}.${t}`, cmd, { + await launch(`${c}`, cmd, { cwd: dir, env: { PATH: process.env.PATH @@ -109,46 +150,158 @@ inject('pod', async ({ boss }) => { throw e } }) - log('Discovering database tables') - for (const d of databases) { - const db = new Client(db_options(d)) - db.on('error', e => console.error(e)) - db.connect() - const { rows: tab } = await db.query(` - select concat(table_schema , '.', table_name) as t - from information_schema.tables - where table_type = 'BASE TABLE'`) - db.end() - const tables = tab.map(t => t.t) - for (const t of tables) add_task(d, t) - } - log('Backing up tables') + const container = CONTAINER_NAME || 'postgres-container' + add_task(container) + + log('begin back up process') const limit = pLimit(10) await Promise.all(tasks.map(t => limit(t))) - // const all_directories = await fsp.readdir('./data') - // const directories = all_directories.filter(p => p != 'README.md') - // for(const dir of directories) { - // await fs.rmdirSync(`./data/${dir}`) - // } - - log('Backup complete') + log('backup complete') } catch(e) { - error(`Error encountered during backup - ${e}`) + error(`error encountered during backup - ${e}`) throw e } + } + + const compress_backup = async (file_name) => { + try { + console.log('compress back up') + + const read_file = `${file_name}.sql` + const write_file = `${file_name}.sql.gz` + + await compress(`./data/${read_file}`, `./data/${write_file}`) + console.log('compressed backup') + + } catch (err) { + console.error(`something went wrong writing a backup to minio bucket '${SERVER_NAME.toLowerCase()}'`) + console.error(err.message) + throw err + } + } + + const minio_write = async (file_name) => { + try { + console.log('write back ups to minio') + const backup_path = `./data/${file_name}.sql` + const backup_file = fs.readFileSync(backup_path) + const backup_name = `${file_name}.sql` + + const backup_path_compressed = `./data/${file_name}.sql.gz` + const backup_file_compressed = fs.readFileSync(backup_path_compressed) + const backup_name_compressed = `${file_name}.sql.gz` + + const date_directory = format(new Date(), 'yyyy-MM-dd') + + if(!await fs.existsSync(backup_path) || !await fs.existsSync(backup_path_compressed)) { + console.error(`unable to locate either '${backup_path}' or '${backup_path_compressed}'.`) + throw new Error(`unable to locate either '${backup_path}' or '${backup_path_compressed}'.`) + } + + await minio.putObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name}`, backup_file) + await minio.putObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name_compressed}`, backup_file_compressed) + console.log('written back ups to minio') + + // keep files on the server until disk space is an issue + // fs.unlinkSync(backup_path) + // console.log(`postgres backup '${backup_path}' deleted`) + } catch (err) { + console.log(`something went wrong writing a backup to minio bucket '${SERVER_NAME.toLowerCase()}'`) + console.log(err.message) + } + } + + const SCHEDULE = BOSS_SCHEDULE || '0 0 * * *' + await boss.schedule(`${job_prefix}.${SERVER_NAME.CONTAINER_NAME}`, SCHEDULE, null, { + singletonKey: `${BOSS_APPLICATION_NAME}.${SERVER_NAME.toLowerCase()}`, + retryLimit: Number(BOSS_RETRY_LIMIT || 5), + retryDelay: Number(BOSS_RETRY_DELAY || 300), + retryBackoff: Boolean(BOSS_RETRY_BACKOFF || false), + expireInMinutes: Number(BOSS_EXPIRE_MINUTES || 5), + tz: BOSS_TZ || 'UTC' }) - await boss.schedule(name, process.env.SCHEDULE, null, { - retryLimit: Number(process.env.RETRY_LIMIT || 0), - retryDelay: Number(process.env.RETRY_DELAY || 300), - retryBackoff: Boolean(process.env.RETRY_BACKOFF || false), - expireInMinutes: Number(process.env.EXPIRE_MINUTES || 180), - tz: process.env.TZ || 'UTC' + await boss.work(`${job_prefix}.${CONTAINER_NAME}`, async job => { + const job_entry = await boss.getJobById(job.id) + try { + const start = Date.now() + const backup_start = Date.now() + await postgres_backup() + const backup_end = Date.now() + const compression_start = Date.now() + await compress_backup(CONTAINER_NAME) + const compression_end = Date.now() + const minio_start = Date.now() + await minio_write(CONTAINER_NAME) + const minio_end = Date.now() + + const backup = fs.statSync(`./data/${CONTAINER_NAME}.sql`) + const backup_compressed = fs.statSync(`./data/${CONTAINER_NAME}.sql.gz`) + + const size = { + backup: (backup.size/1024/1024).toFixed(0), + compressed: (backup_compressed.size/1024/1024).toFixed(0) + } + + const end = Date.now() + + const timing = { + backup: await to_mins_and_seconds(backup_end - backup_start), + compression: await to_mins_and_seconds(compression_end - compression_start), + minio: await to_mins_and_seconds(minio_end - minio_start), + total: await to_mins_and_seconds(end - start) + } + + let timing_output = '' + for (const [key, value] of Object.entries(timing)) { + const formatted_key = await format_string(key) + timing_output += `${formatted_key}: ${value}mins\n` + } + + let size_output = '' + for (const [key, value] of Object.entries(size)) { + const formatted_key = await format_string(key) + size_output += `${formatted_key}: ${value}MB\n` + } + + await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()}' completed successfully.`, [ + { + title: `Backup completed successfully in ${timing.total}mins`, + color: 65280, + timestamp: new Date(), + fields: [ + { + name: 'Timing', + value: timing_output + }, + { + name: 'Size', + value: size_output + } + ] + } + ]) + await job.done() + } catch (e) { + console.error(`unable to perform postgres backup for '${SERVER_NAME.toLowerCase()}'`) + if (job_entry.retrycount < 3) { + await discord.notification(`:warning: Postgres Backup → Unable to perform a database backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()}', retrying...`, [ + { + title: 'An error has occured while trying to back up the database.', + color: 16711680, + timestamp: new Date(), + fields: [e] + } + ]) + } + console.error(e) + await job.done(e) + } }) inject('command.now', async ({ boss }) => { - await boss.send(name) + await boss.send(`${job_prefix}.${CONTAINER_NAME}`) }) }) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f590f5a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: '3.7' + +services: + postgres: + image: postgres:15.4 + ports: + - "5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - './docker-postgres-init.sql:/docker-entrypoint-initdb.d/docker-postgres-init.sql' + networks: + - postgres-boss-backup + + minio: + image: minio/minio + ports: + - "9000:9000" + - "9001:9001" + environment: + - MINIO_ROOT_USER=minioadmin + - MINIO_ROOT_PASSWORD=minioadmin + - MINIO_PORT=9000 + - MINIO_USE_SSL=0 + - MINIO_BROWSER_REDIRECT_URL=http://localhost:9001 + - MINIO_SERVER_URL=http://localhost:9000 + volumes: + - /var/data/minio:/data + command: minio server /data --console-address ":9001" + networks: + - postgres-boss-backup + +networks: + postgres-boss-backup: diff --git a/docker-postgres-init.sql b/docker-postgres-init.sql new file mode 100644 index 0000000..8bc5310 --- /dev/null +++ b/docker-postgres-init.sql @@ -0,0 +1 @@ +create database boss; \ No newline at end of file diff --git a/index.js b/index.js index 25c8a3a..9c0a4d0 100644 --- a/index.js +++ b/index.js @@ -3,5 +3,7 @@ import './lib/health' import './lib/pg-boss' import './lib/require' import './lib/telnet' +import './lib/minio' +import './lib/discord' import './app/index' import './lib/plumbing' diff --git a/lib/discord.js b/lib/discord.js new file mode 100644 index 0000000..677222c --- /dev/null +++ b/lib/discord.js @@ -0,0 +1,32 @@ +import inject from 'seacreature/lib/inject' +import pjson from '../package.json' assert { type: 'json' } + +inject('ctx', async () => { + const { DISCORD_CHANNEL, DISCORD_TOKEN, DISCORD_NOTIFY } = process.env + + const notification = async (content, embeds = []) => { + if(!Number(DISCORD_NOTIFY)) return + + try { + await fetch(`https://discord.com/api/v9/channels/${DISCORD_CHANNEL}/messages`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bot ${DISCORD_TOKEN}`, + 'User-Agent': `Y5 DevOps (https://y5.nz, ${pjson.version})` + }, + body: JSON.stringify({ content, embeds }) + }) + + return + } catch (e) { + console.error(e) + } + } + + return { + discord: { + notification + } + } +}) diff --git a/lib/minio.js b/lib/minio.js new file mode 100644 index 0000000..ea66131 --- /dev/null +++ b/lib/minio.js @@ -0,0 +1,14 @@ +import inject from 'seacreature/lib/inject' +// import Minio from 'minio' +import * as Minio from 'minio' + +inject('ctx', async () => { + const minio = new Minio.Client({ + endPoint: process.env.MINIO_URL, + port: parseInt(process.env.MINIO_PORT), + useSSL: process.env.MINIO_USE_SSL == 'true', + accessKey: process.env.MINIO_ACCESS_KEY, + secretKey: process.env.MINIO_SECRET_KEY + }) + return { minio } +}) \ No newline at end of file diff --git a/lib/pg-boss.js b/lib/pg-boss.js index 8519e86..f2db821 100644 --- a/lib/pg-boss.js +++ b/lib/pg-boss.js @@ -19,7 +19,7 @@ inject('ctx', async ({ startup }) => { retryBackoff: true, expireInMinutes: 60, application_name: process.env.BOSS_APPLICATION_NAME, - schema: process.env.BOSS_PG_SCHEMA + schema: process.env.BOSS_SCHEMA }) .on('error', (e) => console.error(e)) .start() diff --git a/lib/stats.js b/lib/stats.js new file mode 100644 index 0000000..8c960f4 --- /dev/null +++ b/lib/stats.js @@ -0,0 +1,55 @@ +import inject from 'seacreature/lib/inject.js' +import { Stats } from 'fast-stats' + +inject('ctx', () => { + const stats = new Map() + + const rec = (name, ms) => { + if (!stats.has(name)) { + console.log(`${name} recording stats`) + stats.set(name, { + s: new Stats({ + bucket_precision: 50, + store_data: false + }), + c: 0 + }) + } + const s = stats.get(name) + s.s.push(ms) + s.c++ + } + + const reset = () => { + for (const s of stats.values()) { + s.s.reset() + s.c = 0 + } + } + + const print = name => { + if (!stats.has(name)) return + const { s, c } = stats.get(name) + if (c == 0) return + const p = n => s.percentile(n).toFixed(0).padStart(5) + console.log( + `${new Date().toISOString()} ${name.padStart(32).substring(0, 32)} ${c.toString().padStart(5)}∑ ${p(50)}×50 ${p( + 95 + )}×95 ${p(99)}×99` + ) + } + + const print_all = () => { + for (const name of stats.keys()) print(name) + } + + const ms = () => new Date().getTime() + + setInterval(print_all, 3e5) // 5 min + setInterval(reset, 3.6e6) // 1 hour + // setInterval(() => { rec('task_update.query', [Math.random() * 1000]) }, 10) + + return { + stats: { rec, reset, print, print_all, ms } + } +}) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d886637..b831c1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "license": "ISC", "dependencies": { "cross-env": "^7.0.3", + "date-fns": "^2.30.0", "dotenv": "^16.0.0", + "fast-stats": "^0.0.6", "minio": "^7.0.32", "neo-blessed": "^0.2.0", "node-fetch": "^3.2.0", @@ -18,7 +20,19 @@ "pg": "^8.7.3", "pg-boss": "^7.1.0", "seacreature": "^2.17.0", - "telnet2": "^0.0.1" + "telnet2": "^0.0.1", + "zlib": "^1.0.5" + } + }, + "node_modules/@babel/runtime": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", + "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@zxing/text-encoding": { @@ -312,6 +326,21 @@ "node": ">= 12" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -396,6 +425,14 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/fast-stats": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/fast-stats/-/fast-stats-0.0.6.tgz", + "integrity": "sha512-m0zkwa7Z07Wc4xm1YtcrCHmhzNxiYRrrfUyhkdhSZPzaAH/Ewbocdaq7EPVBFz19GWfIyyPcLfRHjHJYe83jlg==", + "engines": { + "node": "*" + } + }, "node_modules/fast-xml-parser": { "version": "3.21.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", @@ -1070,6 +1107,11 @@ "node": ">= 6" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -1315,9 +1357,26 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zlib": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", + "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==", + "hasInstallScript": true, + "engines": { + "node": ">=0.2.0" + } } }, "dependencies": { + "@babel/runtime": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", + "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, "@zxing/text-encoding": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", @@ -1571,6 +1630,14 @@ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" }, + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -1647,6 +1714,11 @@ "safe-buffer": "^5.1.1" } }, + "fast-stats": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/fast-stats/-/fast-stats-0.0.6.tgz", + "integrity": "sha512-m0zkwa7Z07Wc4xm1YtcrCHmhzNxiYRrrfUyhkdhSZPzaAH/Ewbocdaq7EPVBFz19GWfIyyPcLfRHjHJYe83jlg==" + }, "fast-xml-parser": { "version": "3.21.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", @@ -2137,6 +2209,11 @@ "util-deprecate": "^1.0.1" } }, + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -2315,6 +2392,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==" + }, + "zlib": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", + "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==" } } } diff --git a/package.json b/package.json index efc883e..47a8d0a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "homepage": "https://github.com/y5labs/postgres-boss-backup#readme", "dependencies": { "cross-env": "^7.0.3", + "date-fns": "^2.30.0", "dotenv": "^16.0.0", + "fast-stats": "^0.0.6", "minio": "^7.0.32", "neo-blessed": "^0.2.0", "node-fetch": "^3.2.0", @@ -29,6 +31,7 @@ "pg": "^8.7.3", "pg-boss": "^7.1.0", "seacreature": "^2.17.0", - "telnet2": "^0.0.1" + "telnet2": "^0.0.1", + "zlib": "^1.0.5" } } From fbda87f7dd187b4ee97f1ca00dba82ec34324cba Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 12:58:26 +1300 Subject: [PATCH 06/17] update node version --- captain-definition | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/captain-definition b/captain-definition index d7c7c89..7399bbd 100644 --- a/captain-definition +++ b/captain-definition @@ -1,7 +1,7 @@ { "schemaVersion": 2, "dockerfileLines": [ - "FROM node:17-alpine", + "FROM node:18-alpine", "RUN apk add --no-cache postgresql-client", "RUN mkdir -p /usr/src/app", "WORKDIR /usr/src/app", From 172a35d51c970f7cad5613230b3ba0e4bbb25a72 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 13:08:27 +1300 Subject: [PATCH 07/17] tweak minio import --- lib/minio.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/minio.js b/lib/minio.js index ea66131..7458519 100644 --- a/lib/minio.js +++ b/lib/minio.js @@ -1,9 +1,9 @@ import inject from 'seacreature/lib/inject' // import Minio from 'minio' -import * as Minio from 'minio' +import { Client }from 'minio' inject('ctx', async () => { - const minio = new Minio.Client({ + const minio = new Client({ endPoint: process.env.MINIO_URL, port: parseInt(process.env.MINIO_PORT), useSSL: process.env.MINIO_USE_SSL == 'true', From 44d422c4c2aa819627e04e193761291de1c04f4f Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 13:12:06 +1300 Subject: [PATCH 08/17] rogue import wreacking havoc --- app/index.js | 1 - lib/minio.js | 1 - 2 files changed, 2 deletions(-) diff --git a/app/index.js b/app/index.js index cb3a676..ad9bc0c 100644 --- a/app/index.js +++ b/app/index.js @@ -4,7 +4,6 @@ import { exec } from 'child_process' import pg from 'pg' import fsp from 'fs/promises' import fs from 'fs' -import Minio from 'minio' import { format } from 'date-fns' import zlib from 'zlib' diff --git a/lib/minio.js b/lib/minio.js index 7458519..7b2d510 100644 --- a/lib/minio.js +++ b/lib/minio.js @@ -1,5 +1,4 @@ import inject from 'seacreature/lib/inject' -// import Minio from 'minio' import { Client }from 'minio' inject('ctx', async () => { From 89dd5613f498d151e2ddc0ee05234843153b4c37 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 14:20:09 +1300 Subject: [PATCH 09/17] type cast envs --- app/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/index.js b/app/index.js index ad9bc0c..4ea954a 100644 --- a/app/index.js +++ b/app/index.js @@ -128,8 +128,8 @@ inject('pod', async ({ boss, minio, discord }) => { log('queueing backup') const tasks = [] const add_task = (c) => tasks.push(async () => { - const verbose = DUMP_LOGGING ? '-v' : '' - const structure_only = DATABASE_STRUCTURE_ONLY ? '-s' : '' + const verbose = Number(DUMP_LOGGING) ? '-v' : '' + const structure_only = Number(DATABASE_STRUCTURE_ONLY) ? '-s' : '' const blacklist = DATABASE_BLACKLIST ? DATABASE_BLACKLIST.split(',') : [] const exclusions = blacklist.length ? blacklist.map(db => `--exclude-database=${db}`).join(' ') : '' From 04eca27c870ee99a60dd2a25b92703da82814e8f Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 14:26:18 +1300 Subject: [PATCH 10/17] identify container on logs --- app/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/index.js b/app/index.js index 4ea954a..f52ff6f 100644 --- a/app/index.js +++ b/app/index.js @@ -265,7 +265,7 @@ inject('pod', async ({ boss, minio, discord }) => { size_output += `${formatted_key}: ${value}MB\n` } - await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()}' completed successfully.`, [ + await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()} - ${CONTAINER_NAME}' completed successfully.`, [ { title: `Backup completed successfully in ${timing.total}mins`, color: 65280, @@ -286,7 +286,7 @@ inject('pod', async ({ boss, minio, discord }) => { } catch (e) { console.error(`unable to perform postgres backup for '${SERVER_NAME.toLowerCase()}'`) if (job_entry.retrycount < 3) { - await discord.notification(`:warning: Postgres Backup → Unable to perform a database backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()}', retrying...`, [ + await discord.notification(`:warning: Postgres Backup → Unable to perform a database backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()} - ${CONTAINER_NAME}', retrying...`, [ { title: 'An error has occured while trying to back up the database.', color: 16711680, From 4debdd00501d5929059ce2e17769f155c74a76bd Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 14:28:46 +1300 Subject: [PATCH 11/17] polish --- app/index.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/index.js b/app/index.js index f52ff6f..d6da488 100644 --- a/app/index.js +++ b/app/index.js @@ -125,7 +125,7 @@ inject('pod', async ({ boss, minio, discord }) => { const postgres_backup = async (name) => { try { - log('queueing backup') + console.log('queueing backup') const tasks = [] const add_task = (c) => tasks.push(async () => { const verbose = Number(DUMP_LOGGING) ? '-v' : '' @@ -153,13 +153,13 @@ inject('pod', async ({ boss, minio, discord }) => { const container = CONTAINER_NAME || 'postgres-container' add_task(container) - log('begin back up process') + console.log('begin back up process') const limit = pLimit(10) await Promise.all(tasks.map(t => limit(t))) - log('backup complete') + console.log('backup complete') } catch(e) { - error(`error encountered during backup - ${e}`) + console.error(`error encountered during backup - ${e}`) throw e } } @@ -224,6 +224,8 @@ inject('pod', async ({ boss, minio, discord }) => { await boss.work(`${job_prefix}.${CONTAINER_NAME}`, async job => { const job_entry = await boss.getJobById(job.id) + const formatted_name = await format_string(CONTAINER_NAME.toLowerCase()) + try { const start = Date.now() const backup_start = Date.now() @@ -265,7 +267,8 @@ inject('pod', async ({ boss, minio, discord }) => { size_output += `${formatted_key}: ${value}MB\n` } - await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()} - ${CONTAINER_NAME}' completed successfully.`, [ + const formatted_name = await format_string(CONTAINER_NAME.toLowerCase()) + await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${formatted_name} - ${CONTAINER_NAME}' completed successfully.`, [ { title: `Backup completed successfully in ${timing.total}mins`, color: 65280, @@ -286,7 +289,7 @@ inject('pod', async ({ boss, minio, discord }) => { } catch (e) { console.error(`unable to perform postgres backup for '${SERVER_NAME.toLowerCase()}'`) if (job_entry.retrycount < 3) { - await discord.notification(`:warning: Postgres Backup → Unable to perform a database backup for '${DISCORD_ICON} ${SERVER_NAME.toLowerCase()} - ${CONTAINER_NAME}', retrying...`, [ + await discord.notification(`:warning: Postgres Backup → Unable to perform a database backup for '${DISCORD_ICON} ${formatted_name} - ${CONTAINER_NAME}', retrying...`, [ { title: 'An error has occured while trying to back up the database.', color: 16711680, From e5f1217564bb0940d73c43ced496cb33fffe3282 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 14:32:28 +1300 Subject: [PATCH 12/17] container name to server name --- app/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/index.js b/app/index.js index d6da488..4a99789 100644 --- a/app/index.js +++ b/app/index.js @@ -224,7 +224,7 @@ inject('pod', async ({ boss, minio, discord }) => { await boss.work(`${job_prefix}.${CONTAINER_NAME}`, async job => { const job_entry = await boss.getJobById(job.id) - const formatted_name = await format_string(CONTAINER_NAME.toLowerCase()) + const formatted_name = await format_string(SERVER_NAME.toLowerCase()) try { const start = Date.now() @@ -267,7 +267,6 @@ inject('pod', async ({ boss, minio, discord }) => { size_output += `${formatted_key}: ${value}MB\n` } - const formatted_name = await format_string(CONTAINER_NAME.toLowerCase()) await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${formatted_name} - ${CONTAINER_NAME}' completed successfully.`, [ { title: `Backup completed successfully in ${timing.total}mins`, From e37c825dc07d030dc0c8499489181f82d0883c15 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 21:13:53 +1300 Subject: [PATCH 13/17] for bryce --- app/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/index.js b/app/index.js index 4a99789..7466f17 100644 --- a/app/index.js +++ b/app/index.js @@ -249,22 +249,22 @@ inject('pod', async ({ boss, minio, discord }) => { const end = Date.now() const timing = { - backup: await to_mins_and_seconds(backup_end - backup_start), - compression: await to_mins_and_seconds(compression_end - compression_start), - minio: await to_mins_and_seconds(minio_end - minio_start), - total: await to_mins_and_seconds(end - start) + backup: ((backup_end - backup_start)/1000), + compression: ((compression_end - compression_start)/1000), + minio: ((minio_end - minio_start)/1000), + total: ((end - start)/1000) } let timing_output = '' for (const [key, value] of Object.entries(timing)) { const formatted_key = await format_string(key) - timing_output += `${formatted_key}: ${value}mins\n` + timing_output += `${formatted_key}: ${value} secs\n` } let size_output = '' for (const [key, value] of Object.entries(size)) { const formatted_key = await format_string(key) - size_output += `${formatted_key}: ${value}MB\n` + size_output += `${formatted_key}: ${value} MB\n` } await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${formatted_name} - ${CONTAINER_NAME}' completed successfully.`, [ From a2a728a1e4541b9080a42ea1000cd4a858ae4e5c Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 21:14:44 +1300 Subject: [PATCH 14/17] one more --- app/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index 7466f17..4df83ee 100644 --- a/app/index.js +++ b/app/index.js @@ -269,7 +269,7 @@ inject('pod', async ({ boss, minio, discord }) => { await discord.notification(`✅ Postgres Backup → Databse backup for '${DISCORD_ICON} ${formatted_name} - ${CONTAINER_NAME}' completed successfully.`, [ { - title: `Backup completed successfully in ${timing.total}mins`, + title: `Backup completed successfully in ${timing.total} secs`, color: 65280, timestamp: new Date(), fields: [ From 5fe036883ca0ab6446262e49c4b00700e3a1f5e8 Mon Sep 17 00:00:00 2001 From: paulmaguire Date: Mon, 25 Sep 2023 21:18:37 +1300 Subject: [PATCH 15/17] rounding --- app/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/index.js b/app/index.js index 4df83ee..a56487a 100644 --- a/app/index.js +++ b/app/index.js @@ -249,10 +249,10 @@ inject('pod', async ({ boss, minio, discord }) => { const end = Date.now() const timing = { - backup: ((backup_end - backup_start)/1000), - compression: ((compression_end - compression_start)/1000), - minio: ((minio_end - minio_start)/1000), - total: ((end - start)/1000) + backup: ((backup_end - backup_start)/1000).toFixed(0), + compression: ((compression_end - compression_start)/1000).toFixed(0), + minio: ((minio_end - minio_start)/1000).toFixed(0), + total: ((end - start)/1000).toFixed(0) } let timing_output = '' From 15a0f5f408e80bec2f5f08406a0daf8a46b74577 Mon Sep 17 00:00:00 2001 From: micah Date: Tue, 26 Sep 2023 21:00:33 +1300 Subject: [PATCH 16/17] fix filesize issue for minio upload. use fPutObject with filepath v putObject with pre read file Buffer (blows up > 2G), plus some comments --- app/index.js | 16 +++++++++------- scratch.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 scratch.js diff --git a/app/index.js b/app/index.js index a56487a..0823f47 100644 --- a/app/index.js +++ b/app/index.js @@ -125,7 +125,7 @@ inject('pod', async ({ boss, minio, discord }) => { const postgres_backup = async (name) => { try { - console.log('queueing backup') + console.log(`queueing backup '${name}'`) const tasks = [] const add_task = (c) => tasks.push(async () => { const verbose = Number(DUMP_LOGGING) ? '-v' : '' @@ -135,6 +135,7 @@ inject('pod', async ({ boss, minio, discord }) => { const cmd = `pg_dumpall -h ${DB_HOST} -p ${DB_PORT} ${verbose} ${structure_only} -U ${DB_USER} --file=${c}.sql ${exclusions}` const dir = `${process.env.BK_DIR || `${process.cwd()}/data`}` + console.log('cmd',cmd) await assert_dir(dir) try { await launch(`${c}`, cmd, { @@ -166,7 +167,7 @@ inject('pod', async ({ boss, minio, discord }) => { const compress_backup = async (file_name) => { try { - console.log('compress back up') + console.log(`compressing back up: ${file_name}`) const read_file = `${file_name}.sql` const write_file = `${file_name}.sql.gz` @@ -175,7 +176,7 @@ inject('pod', async ({ boss, minio, discord }) => { console.log('compressed backup') } catch (err) { - console.error(`something went wrong writing a backup to minio bucket '${SERVER_NAME.toLowerCase()}'`) + console.error(`something went wrong compressing the backup '${SERVER_NAME.toLowerCase()}'`) console.error(err.message) throw err } @@ -185,11 +186,9 @@ inject('pod', async ({ boss, minio, discord }) => { try { console.log('write back ups to minio') const backup_path = `./data/${file_name}.sql` - const backup_file = fs.readFileSync(backup_path) const backup_name = `${file_name}.sql` const backup_path_compressed = `./data/${file_name}.sql.gz` - const backup_file_compressed = fs.readFileSync(backup_path_compressed) const backup_name_compressed = `${file_name}.sql.gz` const date_directory = format(new Date(), 'yyyy-MM-dd') @@ -199,8 +198,11 @@ inject('pod', async ({ boss, minio, discord }) => { throw new Error(`unable to locate either '${backup_path}' or '${backup_path_compressed}'.`) } - await minio.putObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name}`, backup_file) - await minio.putObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name_compressed}`, backup_file_compressed) + console.log(`writing backup file to minio :${backup_path}`) + await minio.fPutObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name}`, backup_path) + + console.log(`writing backup file to minio :${backup_path_compressed}`) + await minio.fPutObject(SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name_compressed}`, backup_path_compressed) console.log('written back ups to minio') // keep files on the server until disk space is an issue diff --git a/scratch.js b/scratch.js new file mode 100644 index 0000000..efd026c --- /dev/null +++ b/scratch.js @@ -0,0 +1,45 @@ +import { config } from 'dotenv' +config() +import { Client } from 'minio' +import fs from 'fs' +import path from 'path' +import { constrainedMemory } from 'process' + + +const minio = new Client({ + endPoint: process.env.MINIO_URL, + port: parseInt(process.env.MINIO_PORT), + useSSL: process.env.MINIO_USE_SSL == 'true', + accessKey: process.env.MINIO_ACCESS_KEY, + secretKey: process.env.MINIO_SECRET_KEY +}) +console.log(minio) + + +async function upload(file_path) { + const date_directory = new Date().toISOString().slice(0, 13) + const backup_name = file_path.split("/").slice(-1)[0] + console.log(file_path) + console.log(backup_name) + try { + const res = await minio.fPutObject(process.env.SERVER_NAME.toLowerCase(), `${date_directory}/${backup_name}`,file_path ) + console.log(res) + } + catch (e) { + console.log(e) + } +} + + +const data_dir = 'data' +const file_names = fs.readdirSync(data_dir).filter(f => !f.toLowerCase().startsWith("read")); +const file_paths = file_names.map(f => path.join(data_dir, f)) +console.log(file_paths) +// process.exit(0) + +const big_file = 'data/srv-captain--postgres-db-mcgrath.sql' +await upload(big_file) +// for (const file_path of file_paths) { +// await upload(file_path) +// } + From ef3bb4c8f1a8e95190d412d8ad89dbf1d210aa38 Mon Sep 17 00:00:00 2001 From: james-wylie <51935661+james-wylie@users.noreply.github.com> Date: Fri, 8 Dec 2023 11:51:48 +1300 Subject: [PATCH 17/17] update boss job names --- app/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/index.js b/app/index.js index 0823f47..683a69f 100644 --- a/app/index.js +++ b/app/index.js @@ -215,7 +215,7 @@ inject('pod', async ({ boss, minio, discord }) => { } const SCHEDULE = BOSS_SCHEDULE || '0 0 * * *' - await boss.schedule(`${job_prefix}.${SERVER_NAME.CONTAINER_NAME}`, SCHEDULE, null, { + await boss.schedule(`${job_prefix}.${SERVER_NAME}.${CONTAINER_NAME}`, SCHEDULE, null, { singletonKey: `${BOSS_APPLICATION_NAME}.${SERVER_NAME.toLowerCase()}`, retryLimit: Number(BOSS_RETRY_LIMIT || 5), retryDelay: Number(BOSS_RETRY_DELAY || 300), @@ -224,7 +224,7 @@ inject('pod', async ({ boss, minio, discord }) => { tz: BOSS_TZ || 'UTC' }) - await boss.work(`${job_prefix}.${CONTAINER_NAME}`, async job => { + await boss.work(`${job_prefix}.${SERVER_NAME}.${CONTAINER_NAME}`, async job => { const job_entry = await boss.getJobById(job.id) const formatted_name = await format_string(SERVER_NAME.toLowerCase()) @@ -305,6 +305,6 @@ inject('pod', async ({ boss, minio, discord }) => { }) inject('command.now', async ({ boss }) => { - await boss.send(`${job_prefix}.${CONTAINER_NAME}`) + await boss.send(`${job_prefix}.${SERVER_NAME}.${CONTAINER_NAME}`) }) })