From e18e5a57012172786e0fe59de7a1b77e50dc321f Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:25:07 +0000 Subject: [PATCH 01/18] Upgrade dependencies --- package.json | 17 +-- yarn.lock | 364 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 249 insertions(+), 132 deletions(-) diff --git a/package.json b/package.json index de78b4fa..a29ac5c6 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "./public/**" ], "dependencies": { + "@babel/traverse": "7.23.6", "@fastify/busboy": "1.0.0", "bcryptjs": "2.4.3", "caniuse-lite": "^1.0.30001561", @@ -83,7 +84,7 @@ "yarn": "1.22.17" }, "optionalDependencies": { - "sqlite3": "5.1.6" + "sqlite3": "5.1.7" }, "devDependencies": { "@babel/core": "7.17.10", @@ -92,15 +93,15 @@ "@fortawesome/fontawesome-free": "5.15.4", "@istanbuljs/nyc-config-typescript": "1.0.2", "@textcomplete/core": "0.1.10", - "@textcomplete/textarea": "0.1.12", - "@types/bcryptjs": "2.4.5", + "@textcomplete/textarea": "0.1.13", + "@types/bcryptjs": "2.4.6", "@types/chai": "4.3.5", - "@types/cheerio": "0.22.33", - "@types/content-disposition": "0.5.7", + "@types/cheerio": "0.22.35", + "@types/content-disposition": "0.5.8", "@types/express": "4.17.13", - "@types/is-utf8": "0.2.2", + "@types/is-utf8": "0.2.3", "@types/ldapjs": "2.2.2", - "@types/linkify-it": "3.0.3", + "@types/linkify-it": "3.0.5", "@types/lodash": "4.14.200", "@types/mime-types": "2.1.1", "@types/mocha": "9.1.1", @@ -168,4 +169,4 @@ "webpack-dev-middleware": "5.3.3", "webpack-hot-middleware": "2.25.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 1839f1c6..de065b9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,14 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + "@babel/compat-data@^7.17.10", "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.9": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.20.tgz#8df6e96661209623f1975d66c35ffca66f3306d0" @@ -80,6 +88,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -242,6 +260,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" @@ -279,11 +302,25 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.17.10", "@babel/parser@^7.20.15", "@babel/parser@^7.21.3", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== +"@babel/parser@^7.23.6": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962" @@ -946,6 +983,22 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" +"@babel/traverse@7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" + integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" + debug "^4.3.1" + globals "^11.1.0" + "@babel/traverse@^7.17.10", "@babel/traverse@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.0.tgz#18196ddfbcf4ccea324b7f6d3ada00d8c5a99c53" @@ -971,6 +1024,15 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@babel/types@^7.23.6": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -1138,21 +1200,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mapbox/node-pre-gyp@^1.0.0": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" - integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== - dependencies: - detect-libc "^2.0.0" - https-proxy-agent "^5.0.0" - make-dir "^3.1.0" - node-fetch "^2.6.7" - nopt "^5.0.0" - npmlog "^5.0.1" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.11" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1279,19 +1326,19 @@ dependencies: eventemitter3 "^4.0.4" -"@textcomplete/textarea@0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@textcomplete/textarea/-/textarea-0.1.12.tgz#7ff1a3a9c96677638e659bce8d02f80fd8c806d5" - integrity sha512-E05H4wXr1Q50CrCFBAHewyZqvQEX681V5zleDw/31tr8vl5PDFl6TyFmS1W0jQjlrQfxa5uVvgHCx+gpfICBDQ== +"@textcomplete/textarea@0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@textcomplete/textarea/-/textarea-0.1.13.tgz#a0e365877bdce1c16ec48bdd439cd44d28a903ef" + integrity sha512-GNathnXpV361YuZrBVXvVqFYZ5NQZsjGC7Bt2sCUA/RTWlIgxHxC0ruDChYyRDx4siQZiZZOO5pWz+z1x8pZFQ== dependencies: - "@textcomplete/utils" "^0.1.11" + "@textcomplete/utils" "^0.1.13" textarea-caret "^3.1.0" undate "^0.3.0" -"@textcomplete/utils@^0.1.11": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@textcomplete/utils/-/utils-0.1.12.tgz#04811b4f680708579d78c60a8546c81a16440120" - integrity sha512-llHhD1FAVwFaaHzs7PU0BZYTpNLDzTccDWbw+5cj0TiB2NOXZGjPm6l7PJrJwN/yUuPDxOHip/3I+kF6OBkBAg== +"@textcomplete/utils@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@textcomplete/utils/-/utils-0.1.13.tgz#0b56a5a876fb27478b702e3ea118fa75960b4331" + integrity sha512-5UW9Ee0WEX1s9K8MFffo5sfUjYm3YVhtqRhAor/ih7p0tnnpaMB7AwMRDKwhSIQL6O+g1fmEkxCeO8WqjPzjUA== "@tokenizer/token@^0.3.0": version "0.3.0" @@ -1328,10 +1375,10 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/bcryptjs@2.4.5": - version "2.4.5" - resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.5.tgz#15473cc012f825b3435b189376f645bdd2fc9f11" - integrity sha512-tOF6TivOIvq+TWQm78335CMdyVJhpBG3NUdWQDAp95ax4E2rSKbws/ELHLk5EBoucwx/tHt3/hhLOHwWJgVrSw== +"@types/bcryptjs@2.4.6": + version "2.4.6" + resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.6.tgz#2b92e3c2121c66eba3901e64faf8bb922ec291fa" + integrity sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ== "@types/body-parser@*": version "1.19.3" @@ -1361,10 +1408,10 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== -"@types/cheerio@0.22.33": - version "0.22.33" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.33.tgz#e4792408b107384d7d7469e3b4d31408078ec620" - integrity sha512-XUlu2BK4q3xJsccRLK69m/cABZd7m60o+cDEPUTG6jTpuG2vqN35UioeF99MQ/HoSOEPq0Bgil8g3jtzE0oH9A== +"@types/cheerio@0.22.35": + version "0.22.35" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.35.tgz#0d16dc1f24d426231c181b9c31847f673867595f" + integrity sha512-yD57BchKRvTV+JD53UZ6PD8KWY5g5rvvMLRnZR3EQBCZXiDT/HR+pKpMzFGlWNhFrXlo7VPZXtKvIEwZkAWOIA== dependencies: "@types/node" "*" @@ -1375,10 +1422,10 @@ dependencies: "@types/node" "*" -"@types/content-disposition@0.5.7": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.7.tgz#3b98d4bf8c80640f93b042511acb5aad18139748" - integrity sha512-V9/5u21RHFR1zfdm3rQ6pJUKV+zSSVQt+yq16i1YhdivVzWgPEoKedc3GdT8aFjsqQbakdxuy3FnEdePUQOamQ== +"@types/content-disposition@0.5.8": + version "0.5.8" + resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.8.tgz#6742a5971f490dc41e59d277eee71361fea0b537" + integrity sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg== "@types/cookie@^0.4.1": version "0.4.1" @@ -1448,10 +1495,10 @@ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.2.tgz#a86e00bbde8950364f8e7846687259ffcd96e8c2" integrity sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg== -"@types/is-utf8@0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@types/is-utf8/-/is-utf8-0.2.2.tgz#b31ab599ead973992809b0b802ce066abbb42efd" - integrity sha512-j7PFtO0ki4IoJvmMaAHQ70z74Td244dMLC7BAz5pb0v7IC8xXLtuM+7AWsMco4Minz92m30fO72+TbkmtMr4dQ== +"@types/is-utf8@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@types/is-utf8/-/is-utf8-0.2.3.tgz#4821e365f6518778bd7c9b3f8b3a5c42a8e96706" + integrity sha512-pOsafTvuyh/FBJm+LP81graldeJLPtJ/UcfqzD+qNoey7PpG2saE/v+h8r4gxT6BGO8mzAuK2fkYLr6goOdwwg== dependencies: "@types/node" "*" @@ -1474,10 +1521,10 @@ dependencies: "@types/node" "*" -"@types/linkify-it@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.3.tgz#15a0712296c5041733c79efe233ba17ae5a7587b" - integrity sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g== +"@types/linkify-it@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" + integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== "@types/lodash@4.14.200": version "4.14.200" @@ -2364,14 +2411,6 @@ archy@^1.0.0: resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== -are-we-there-yet@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" - integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" - are-we-there-yet@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" @@ -2594,6 +2633,22 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bn.js@^4.0.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -2667,6 +2722,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -2869,6 +2932,11 @@ chokidar@3.5.3, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -2949,7 +3017,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-support@^1.1.2, color-support@^1.1.3: +color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== @@ -2997,7 +3065,7 @@ config-chain@^1.1.13: ini "^1.3.4" proto-list "~1.2.1" -console-control-strings@^1.0.0, console-control-strings@^1.1.0: +console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== @@ -3270,7 +3338,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3519,7 +3587,7 @@ encoding@^0.1.12: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -3893,6 +3961,11 @@ execall@^2.0.0: dependencies: clone-regexp "^2.1.0" +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + express@4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" @@ -3993,6 +4066,11 @@ file-type@16.5.4: strtok3 "^6.2.4" token-types "^4.1.1" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filename-reserved-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" @@ -4124,6 +4202,11 @@ fromentries@^1.2.0: resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -4185,21 +4268,6 @@ fuzzy@0.1.3: resolved "https://registry.yarnpkg.com/fuzzy/-/fuzzy-0.1.3.tgz#4c76ec2ff0ac1a36a9dccf9a00df8623078d4ed8" integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w== -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" - gauge@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" @@ -4269,6 +4337,11 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -4636,7 +4709,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -4690,7 +4763,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5581,7 +5654,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5645,6 +5718,11 @@ minizlib@^2.0.0, minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -5731,6 +5809,11 @@ nanoid@^3.3.6: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -5773,22 +5856,22 @@ nise@^5.1.1: just-extend "^4.0.2" path-to-regexp "^1.7.0" +node-abi@^3.3.0: + version "3.54.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.54.0.tgz#f6386f7548817acac6434c6cba02999c9aebcc69" + integrity sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA== + dependencies: + semver "^7.3.5" + node-abort-controller@^3.0.1: version "3.1.1" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== -node-addon-api@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" - integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== - -node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" +node-addon-api@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.0.tgz#71f609369379c08e251c558527a107107b5e0fdb" + integrity sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g== node-forge@1.3.0: version "1.3.0" @@ -5904,16 +5987,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - npmlog@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" @@ -5964,7 +6037,7 @@ nyc@15.1.0: test-exclude "^6.0.0" yargs "^15.0.2" -object-assign@^4, object-assign@^4.1.1: +object-assign@^4: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -6747,6 +6820,24 @@ postcss@8.4.31, postcss@^8.1.10, postcss@^8.2.15, postcss@^8.4.5: picocolors "^1.0.0" source-map-js "^1.0.2" +prebuild-install@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" + integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -6879,7 +6970,7 @@ raw-body@2.4.3: iconv-lite "0.4.24" unpipe "1.0.0" -rc@1.2.8, rc@^1.2.8: +rc@1.2.8, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -6939,7 +7030,7 @@ read@1.0.7: dependencies: mute-stream "~0.0.4" -readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -7330,11 +7421,25 @@ sigmund@^1.0.1: resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" integrity sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g== -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + sinon@13.0.2: version "13.0.2" resolved "https://registry.yarnpkg.com/sinon/-/sinon-13.0.2.tgz#c6a8ddd655dc1415bbdc5ebf0e5b287806850c3a" @@ -7513,13 +7618,14 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sqlite3@5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.6.tgz#1d4fbc90fe4fbd51e952e0a90fd8f6c2b9098e97" - integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw== +sqlite3@5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.7.tgz#59ca1053c1ab38647396586edad019b1551041b7" + integrity sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog== dependencies: - "@mapbox/node-pre-gyp" "^1.0.0" - node-addon-api "^4.2.0" + bindings "^1.5.0" + node-addon-api "^7.0.0" + prebuild-install "^7.1.1" tar "^6.1.11" optionalDependencies: node-gyp "8.x" @@ -7794,6 +7900,27 @@ tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: version "6.2.0" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" @@ -7881,11 +8008,6 @@ token-types@^4.1.1: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -7949,6 +8071,13 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -8296,11 +8425,6 @@ web-push@3.4.5: minimist "^1.2.5" urlsafe-base64 "^1.0.0" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - webpack-cli@4.9.2: version "4.9.2" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.2.tgz#77c1adaea020c3f9e2db8aad8ea78d235c83659d" @@ -8412,14 +8536,6 @@ webpack@^5: watchpack "^2.4.0" webpack-sources "^3.2.3" -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -8461,7 +8577,7 @@ which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.2, wide-align@^1.1.5: +wide-align@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== From 0abac9742b50fcf50d1565a0938f94557ed48921 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:26:17 +0000 Subject: [PATCH 02/18] Bump version to 4.4.1-2 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a29ac5c6..d6393eec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@supernets/hardlounge", "description": "The self-hosted Web IRC client", - "version": "4.4.1-1", + "version": "4.4.1-2", "preferGlobal": true, "bin": { "hardlounge": "index.js" @@ -169,4 +169,4 @@ "webpack-dev-middleware": "5.3.3", "webpack-hot-middleware": "2.25.4" } -} +} \ No newline at end of file From e862324de83b47483b7063082a65b24dc08411e6 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:30:16 +0000 Subject: [PATCH 03/18] Dont fail if stderr not in json format --- server/command-line/utils.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/server/command-line/utils.ts b/server/command-line/utils.ts index a1a8ea6d..d07ee221 100644 --- a/server/command-line/utils.ts +++ b/server/command-line/utils.ts @@ -143,11 +143,11 @@ class Utils { data.toString() .trim() .split("\n") - .forEach((line) => { + .forEach((line: string) => { try { - line = JSON.parse(line); + const json = JSON.parse(line); - if (line.type === "success") { + if (json.type === "success") { success = true; } } catch (e: any) { @@ -163,11 +163,24 @@ class Utils { .trim() .split("\n") .forEach((line: string) => { - const json = JSON.parse(line); + try { + const json = JSON.parse(line); - if (json.type === "error") { - log.error(json.data); + switch (json.type) { + case "error": + log.error(json.data); + break; + case "warning": + // this includes pointless things like "ignored scripts due to flag" + // so let's hide it + break; + } + return; + } catch (e: any) { + // we simply fall through and log at debug... chances are there's nothing the user can do about it + // as it includes things like deprecation warnings, but we might want to know as developers } + log.debug(line); }); }); From 191c57757a63e3f1b1171009eaeb36dc9e84c330 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:39:30 +0000 Subject: [PATCH 04/18] Use variadic function for serialize_run --- server/plugins/messageStorage/sqlite.ts | 51 +++++++++++++------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/server/plugins/messageStorage/sqlite.ts b/server/plugins/messageStorage/sqlite.ts index 676e4efb..a16434e4 100644 --- a/server/plugins/messageStorage/sqlite.ts +++ b/server/plugins/messageStorage/sqlite.ts @@ -159,12 +159,12 @@ class SqliteMessageStorage implements SearchableMessageStorage { async setup_new_db() { for (const stmt of schema) { - await this.serialize_run(stmt, []); + await this.serialize_run(stmt); } await this.serialize_run( "INSERT INTO options (name, value) VALUES ('schema_version', ?)", - [currentSchemaVersion.toString()] + currentSchemaVersion.toString() ); } @@ -194,7 +194,7 @@ class SqliteMessageStorage implements SearchableMessageStorage { async update_version_in_db() { return this.serialize_run( "UPDATE options SET value = ? WHERE name = 'schema_version'", - [currentSchemaVersion.toString()] + currentSchemaVersion.toString() ); } @@ -206,14 +206,14 @@ class SqliteMessageStorage implements SearchableMessageStorage { const to_execute = necessaryMigrations(dbVersion); for (const stmt of to_execute.map((m) => m.stmts).flat()) { - await this.serialize_run(stmt, []); + await this.serialize_run(stmt); } await this.update_version_in_db(); } async run_pragmas() { - await this.serialize_run("PRAGMA foreign_keys = ON;", []); + await this.serialize_run("PRAGMA foreign_keys = ON;"); } async run_migrations() { @@ -225,7 +225,7 @@ class SqliteMessageStorage implements SearchableMessageStorage { return; // nothing to do } - await this.serialize_run("BEGIN EXCLUSIVE TRANSACTION", []); + await this.serialize_run("BEGIN EXCLUSIVE TRANSACTION"); try { if (version === 0) { @@ -236,12 +236,12 @@ class SqliteMessageStorage implements SearchableMessageStorage { await this.insert_rollback_since(version); } catch (err) { - await this.serialize_run("ROLLBACK", []); + await this.serialize_run("ROLLBACK"); throw err; } - await this.serialize_run("COMMIT", []); - await this.serialize_run("VACUUM", []); + await this.serialize_run("COMMIT"); + await this.serialize_run("VACUUM"); } async close() { @@ -296,7 +296,7 @@ class SqliteMessageStorage implements SearchableMessageStorage { async delete_migrations_older_than(version: number) { return this.serialize_run( "delete from migrations where migrations.version > ?", - [version] + version ); } @@ -315,7 +315,7 @@ class SqliteMessageStorage implements SearchableMessageStorage { for (const rollback of _rollbacks) { for (const stmt of rollback.stmts) { - await this.serialize_run(stmt, []); + await this.serialize_run(stmt); } } @@ -330,18 +330,18 @@ class SqliteMessageStorage implements SearchableMessageStorage { throw Error(`${version} is not a valid version to downgrade to`); } - await this.serialize_run("BEGIN EXCLUSIVE TRANSACTION", []); + await this.serialize_run("BEGIN EXCLUSIVE TRANSACTION"); let new_version: number; try { new_version = await this._downgrade_to(version); } catch (err) { - await this.serialize_run("ROLLBACK", []); + await this.serialize_run("ROLLBACK"); throw err; } - await this.serialize_run("COMMIT", []); + await this.serialize_run("COMMIT"); return new_version; } @@ -369,8 +369,10 @@ class SqliteMessageStorage implements SearchableMessageStorage { `insert into rollback_steps (migration_id, step, statement) values (?, ?, ?)`, - [migration.id, step, stmt] - ); + migration.id, + step, + stmt + ); step++; } } @@ -401,13 +403,11 @@ class SqliteMessageStorage implements SearchableMessageStorage { await this.serialize_run( "INSERT INTO messages(network, channel, time, type, msg) VALUES(?, ?, ?, ?, ?)", - [ - network.uuid, - channel.name.toLowerCase(), - msg.time.getTime(), - msg.type, - JSON.stringify(clonedMsg), - ] + network.uuid, + channel.name.toLowerCase(), + msg.time.getTime(), + msg.type, + JSON.stringify(clonedMsg) ); } @@ -420,7 +420,8 @@ class SqliteMessageStorage implements SearchableMessageStorage { await this.serialize_run( "DELETE FROM messages WHERE network = ? AND channel = ?", - [network.uuid, channel.name.toLowerCase()] + network.uuid, + channel.name.toLowerCase() ); } @@ -502,7 +503,7 @@ class SqliteMessageStorage implements SearchableMessageStorage { return this.isEnabled; } - private serialize_run(stmt: string, params: any[]): Promise { + private serialize_run(stmt: string, ...params: any[]): Promise { return new Promise((resolve, reject) => { this.database.serialize(() => { this.database.run(stmt, params, (err) => { From 1b9057d67db1c688b4126da588c84ee585a80452 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:45:36 +0000 Subject: [PATCH 05/18] Accept db connection string --- server/plugins/messageStorage/sqlite.ts | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/server/plugins/messageStorage/sqlite.ts b/server/plugins/messageStorage/sqlite.ts index a16434e4..b34c2417 100644 --- a/server/plugins/messageStorage/sqlite.ts +++ b/server/plugins/messageStorage/sqlite.ts @@ -126,19 +126,8 @@ class SqliteMessageStorage implements SearchableMessageStorage { this.initDone = new Deferred(); } - async _enable() { - const logsPath = Config.getUserLogsPath(); - const sqlitePath = path.join(logsPath, `${this.userName}.sqlite3`); - - try { - await fs.mkdir(logsPath, { recursive: true }); - } catch (e) { - throw Helper.catch_to_error("Unable to create logs directory", e); - } - - this.isEnabled = true; - - this.database = new sqlite3.Database(sqlitePath); + async _enable(connection_string: string) { + this.database = new sqlite3.Database(connection_string); try { await this.run_pragmas(); // must be done outside of a transaction @@ -147,11 +136,22 @@ class SqliteMessageStorage implements SearchableMessageStorage { this.isEnabled = false; throw Helper.catch_to_error("Migration failed", e); } + + this.isEnabled = true; } async enable() { + const logsPath = Config.getUserLogsPath(); + const sqlitePath = path.join(logsPath, `${this.userName}.sqlite3`); + try { - await this._enable(); + await fs.mkdir(logsPath, {recursive: true}); + } catch (e) { + throw Helper.catch_to_error("Unable to create logs directory", e); + } + + try { + await this._enable(sqlitePath); } finally { this.initDone.resolve(); // unblock the instance methods } From fb720d20803f7ed650b923bf1a86fe21df856c7e Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 02:53:54 +0000 Subject: [PATCH 06/18] implement deleteMessages --- server/plugins/messageStorage/sqlite.ts | 37 +++++++- server/plugins/messageStorage/types.d.ts | 7 ++ test/plugins/sqlite.ts | 113 +++++++++++++++++++++++ 3 files changed, 155 insertions(+), 2 deletions(-) diff --git a/server/plugins/messageStorage/sqlite.ts b/server/plugins/messageStorage/sqlite.ts index b34c2417..5525d5bd 100644 --- a/server/plugins/messageStorage/sqlite.ts +++ b/server/plugins/messageStorage/sqlite.ts @@ -11,8 +11,10 @@ import type { SearchResponse, SearchQuery, SearchableMessageStorage, + DeletionRequest } from "./types"; import Network from "../../models/network"; +import { threadId } from "worker_threads"; // TODO; type let sqlite3: any; @@ -244,6 +246,10 @@ class SqliteMessageStorage implements SearchableMessageStorage { await this.serialize_run("VACUUM"); } + async vacuum() { + await this.serialize_run("VACUUM"); + } + async close() { if (!this.isEnabled) { return; @@ -499,6 +505,33 @@ class SqliteMessageStorage implements SearchableMessageStorage { }; } + async deleteMessages(req: DeletionRequest): Promise { + await this.initDone.promise; + let sql = "delete from messages where id in (select id from messages where\n"; + + // We roughly get a timestamp from N days before. + // We don't adjust for daylight savings time or other weird time jumps + const millisecondsInDay = 24 * 60 * 60 * 1000; + const deleteBefore = Date.now() - req.olderThanDays * millisecondsInDay; + sql += `time <= ${deleteBefore}\n`; + + let typeClause = ""; + + if (req.messageTypes !== null) { + typeClause = `type in (${req.messageTypes.map((type) => `'${type}'`).join(",")})\n`; + } + + if (typeClause) { + sql += `and ${typeClause}`; + } + + sql += "order by time asc\n"; + sql += `limit ${req.limit}\n`; + sql += ")"; + + return this.serialize_run(sql); + } + canProvideMessages() { return this.isEnabled; } @@ -506,13 +539,13 @@ class SqliteMessageStorage implements SearchableMessageStorage { private serialize_run(stmt: string, ...params: any[]): Promise { return new Promise((resolve, reject) => { this.database.serialize(() => { - this.database.run(stmt, params, (err) => { + this.database.run(stmt, params, function(err) { if (err) { reject(err); return; } - resolve(); + resolve(this.changes); // number of affected rows, 'this' is re-bound by sqlite3 }); }); }); diff --git a/server/plugins/messageStorage/types.d.ts b/server/plugins/messageStorage/types.d.ts index cc305224..2e037bea 100644 --- a/server/plugins/messageStorage/types.d.ts +++ b/server/plugins/messageStorage/types.d.ts @@ -4,6 +4,13 @@ import {Channel} from "../../models/channel"; import {Message} from "../../models/message"; import {Network} from "../../models/network"; import Client from "../../client"; +import type {MessageType} from "../../models/msg"; + +export type DeletionRequest = { + olderThanDays: number; + messageTypes: MessageType[] | null; //null means no restriction + limit: number; //-1 means unlimited +} interface MessageStorage { isEnabled: boolean; diff --git a/test/plugins/sqlite.ts b/test/plugins/sqlite.ts index 5f3ecc84..199e8b1e 100644 --- a/test/plugins/sqlite.ts +++ b/test/plugins/sqlite.ts @@ -12,6 +12,7 @@ import MessageStorage, { rollbacks, } from "../../server/plugins/messageStorage/sqlite"; import sqlite3 from "sqlite3"; +import {DeletionRequest} from "../../server/plugins/messageStorage/types" const orig_schema = [ // Schema version #1 @@ -127,6 +128,112 @@ describe("SQLite migrations", function () { }); }); +describe("SQLite unit tests", function () { + let store: MessageStorage; + + beforeEach(async function () { + store = new MessageStorage("testUser"); + await store._enable(":memory:"); + store.initDone.resolve(); + }); + + afterEach(async function () { + await store.close(); + }); + + it("deletes messages when asked to", async function () { + const baseDate = new Date(); + + const net = {uuid: "testnet"} as any; + const chan = {name: "#channel"} as any; + + for (let i = 0; i < 14; ++i) { + await store.index( + net, + chan, + new Msg({ + time: dateAddDays(baseDate, -i), + text: `msg ${i}`, + }) + ); + } + + const limit = 1; + const delReq: DeletionRequest = { + messageTypes: [MessageType.MESSAGE], + limit: limit, + olderThanDays: 2, + }; + + let deleted = await store.deleteMessages(delReq); + expect(deleted).to.equal(limit, "number of deleted messages doesn't match"); + + let id = 0; + let messages = await store.getMessages(net, chan, () => id++); + expect(messages.find((m) => m.text === "msg 13")).to.be.undefined; // oldest gets deleted first + + // let's test if it properly cleans now + delReq.limit = 100; + deleted = await store.deleteMessages(delReq); + expect(deleted).to.equal(11, "number of deleted messages doesn't match"); + messages = await store.getMessages(net, chan, () => id++); + expect(messages.map((m) => m.text)).to.have.ordered.members(["msg 1", "msg 0"]); + }); + + it("deletes only the types it should", async function () { + const baseDate = new Date(); + + const net = {uuid: "testnet"} as any; + const chan = {name: "#channel"} as any; + + for (let i = 0; i < 6; ++i) { + await store.index( + net, + chan, + new Msg({ + time: dateAddDays(baseDate, -i), + text: `msg ${i}`, + type: [ + MessageType.ACTION, + MessageType.AWAY, + MessageType.JOIN, + MessageType.PART, + MessageType.KICK, + MessageType.MESSAGE, + ][i], + }) + ); + } + + const delReq: DeletionRequest = { + messageTypes: [MessageType.ACTION, MessageType.JOIN, MessageType.KICK], + limit: 100, // effectively no limit + olderThanDays: 0, + }; + + let deleted = await store.deleteMessages(delReq); + expect(deleted).to.equal(3, "number of deleted messages doesn't match"); + + let id = 0; + let messages = await store.getMessages(net, chan, () => id++); + expect(messages.map((m) => m.type)).to.have.ordered.members([ + MessageType.MESSAGE, + MessageType.PART, + MessageType.AWAY, + ]); + + delReq.messageTypes = [ + MessageType.JOIN, // this is not in the remaining set, just here as a dummy + MessageType.PART, + MessageType.MESSAGE, + ]; + deleted = await store.deleteMessages(delReq); + expect(deleted).to.equal(2, "number of deleted messages doesn't match"); + messages = await store.getMessages(net, chan, () => id++); + expect(messages.map((m) => m.type)).to.have.ordered.members([MessageType.AWAY]); + }); +}); + describe("SQLite Message Storage", function () { // Increase timeout due to unpredictable I/O on CI services this.timeout(util.isRunningOnCI() ? 25000 : 5000); @@ -388,3 +495,9 @@ describe("SQLite Message Storage", function () { expect(fs.existsSync(expectedPath)).to.be.true; }); }); + +function dateAddDays(date: Date, days: number) { + const ret = new Date(date.valueOf()); + ret.setDate(date.getDate() + days); + return ret; +} From b19562e53db5bb5adb8444b0071d5beabb4bd664 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:05:47 +0000 Subject: [PATCH 07/18] Add storage cleaner --- client/tsconfig.json | 11 +-- defaults/config.js | 20 ++++++ server/config.ts | 7 ++ server/storageCleaner.ts | 148 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 server/storageCleaner.ts diff --git a/client/tsconfig.json b/client/tsconfig.json index 4054c4f1..ab517bd2 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -11,6 +11,7 @@ "../server/log.ts", "../server/config.ts", "../server/client.ts", + "../server/storageCleaner.ts", "../server/clientManager.ts", "../server/identification.ts", "../server/plugins/changelog.ts", @@ -44,15 +45,17 @@ "compilerOptions": { "sourceMap": false /*Create source map files for emitted JavaScript files. See more: https://www.typescriptlang.org/tsconfig#sourceMap */, "jsx": "preserve" /* Specify what JSX code is generated. */, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], // this enables stricter inference for data properties on `this` "strict": true, // if using webpack 2+ or rollup, to leverage tree shaking: "module": "es2020", "moduleResolution": "node", - // TODO: Remove eventually "noImplicitAny": false /*Enable error reporting for expressions and declarations with an implied any type. See more: https://www.typescriptlang.org/tsconfig#noImplicitAny */ } /* Instructs the TypeScript compiler how to compile .ts files. */ -} +} \ No newline at end of file diff --git a/defaults/config.js b/defaults/config.js index cba10110..9ebd2b41 100644 --- a/defaults/config.js +++ b/defaults/config.js @@ -308,6 +308,26 @@ module.exports = { // This value is set to `["sqlite", "text"]` by default. messageStorage: ["sqlite", "text"], + // ### `storagePolicy` + + // When the sqlite storage is in use, control the maximum storage duration. + // A background task will periodically clean up messages older than the limit. + + // The available keys for the `storagePolicy` object are: + // + // - `enabled`: If this is false, the cleaning task is not running. + // - `maxAgeDays`: Maximum age of an entry in days. + // - `deletionPolicy`: Controls what types of messages are being deleted. + // Valid options are: + // - `statusOnly`: Only delete message types which are status related (e.g. away, back, join, parts, mode, ctcp...) + // but keep actual messages from nicks. This keeps the DB size down while retaining "precious" messages. + // - `everything`: Delete everything, including messages from irc nicks + storagePolicy: { + enabled: false, + maxAgeDays: 7, + deletionPolicy: "statusOnly", + }, + // ### `useHexIp` // // When set to `true`, users' IP addresses will be encoded as hex. diff --git a/server/config.ts b/server/config.ts index 543a8135..bad5f522 100644 --- a/server/config.ts +++ b/server/config.ts @@ -76,6 +76,12 @@ type Debug = { raw: boolean; }; +type StoragePolicy = { + enabled: boolean; + maxAgeDays: number; + deletionPolicy: "statusOnly" | "everything"; +}; + export type ConfigType = { public: boolean; host: string | undefined; @@ -97,6 +103,7 @@ export type ConfigType = { defaults: Defaults; lockNetwork: boolean; messageStorage: string[]; + storagePolicy: StoragePolicy; useHexIp: boolean; webirc?: WebIRC; identd: Identd; diff --git a/server/storageCleaner.ts b/server/storageCleaner.ts new file mode 100644 index 00000000..fc8ec5b5 --- /dev/null +++ b/server/storageCleaner.ts @@ -0,0 +1,148 @@ +import SqliteMessageStorage from "./plugins/messageStorage/sqlite"; +import {MessageType} from "./models/msg"; +import Config from "./config"; +import {DeletionRequest} from "./plugins/messageStorage/types"; +import log from "./log"; + +const status_types = [ + MessageType.AWAY, + MessageType.BACK, + MessageType.INVITE, + MessageType.JOIN, + MessageType.KICK, + MessageType.MODE, + MessageType.MODE_CHANNEL, + MessageType.MODE_USER, + MessageType.NICK, + MessageType.PART, + MessageType.QUIT, + MessageType.CTCP, // not technically a status, but generally those are only of interest temporarily + MessageType.CTCP_REQUEST, + MessageType.CHGHOST, + MessageType.TOPIC, + MessageType.TOPIC_SET_BY, +]; + +export class StorageCleaner { + db: SqliteMessageStorage; + olderThanDays: number; + messageTypes: MessageType[] | null; + limit: number; + ticker?: ReturnType; + errCount: number; + isStopped: boolean; + + constructor(db: SqliteMessageStorage) { + this.errCount = 0; + this.isStopped = true; + this.db = db; + this.limit = 200; + const policy = Config.values.storagePolicy; + this.olderThanDays = policy.maxAgeDays; + + switch (policy.deletionPolicy) { + case "statusOnly": + this.messageTypes = status_types; + break; + case "everything": + this.messageTypes = null; + break; + default: + // exhaustive switch guard, blows up when user specifies a invalid policy enum + this.messageTypes = assertNoBadPolicy(policy.deletionPolicy); + } + } + + private genDeletionRequest(): DeletionRequest { + return { + limit: this.limit, + messageTypes: this.messageTypes, + olderThanDays: this.olderThanDays, + }; + } + + async runDeletesNoLimit(): Promise { + if (!Config.values.storagePolicy.enabled) { + // this is meant to be used by cli tools, so we guard against this + throw new Error("storage policy is disabled"); + } + + const req = this.genDeletionRequest(); + req.limit = -1; // unlimited + const num_deleted = await this.db.deleteMessages(req); + return num_deleted; + } + + private async runDeletes() { + if (this.isStopped) { + return; + } + + if (!this.db.isEnabled) { + // TODO: remove this once the server is intelligent enough to wait for init + this.schedule(30 * 1000); + return; + } + + const req = this.genDeletionRequest(); + + let num_deleted = 0; + + try { + num_deleted = await this.db.deleteMessages(req); + this.errCount = 0; // reset when it works + } catch (err: any) { + this.errCount++; + log.error("can't clean messages", err.message); + + if (this.errCount === 2) { + log.error("Cleaning failed too many times, will not retry"); + this.stop(); + return; + } + } + + // need to recheck here as the field may have changed since the await + if (this.isStopped) { + return; + } + + if (num_deleted < req.limit) { + this.schedule(5 * 60 * 1000); + } else { + this.schedule(5000); // give others a chance to execute queries + } + } + + private schedule(ms: number) { + const self = this; + + this.ticker = setTimeout(() => { + self.runDeletes().catch((err) => { + log.error("storageCleaner: unexpected failure"); + throw err; + }); + }, ms); + } + + start() { + this.isStopped = false; + this.schedule(0); + } + + stop() { + this.isStopped = true; + + if (!this.ticker) { + return; + } + + clearTimeout(this.ticker); + } +} + +function assertNoBadPolicy(_: never): never { + throw new Error( + `Invalid deletion policy "${Config.values.storagePolicy.deletionPolicy}" in the \`storagePolicy\` object, fix your config.` + ); +} \ No newline at end of file From 815fe046365c83879d89b06b8f7f12d106c0c76b Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:09:44 +0000 Subject: [PATCH 08/18] Expose cli task to do cleaning + vacuum --- server/command-line/storage.ts | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/server/command-line/storage.ts b/server/command-line/storage.ts index 4848f326..4e2eed87 100644 --- a/server/command-line/storage.ts +++ b/server/command-line/storage.ts @@ -3,6 +3,7 @@ import { Command } from "commander"; import ClientManager from "../clientManager"; import Utils from "./utils"; import SqliteMessageStorage from "../plugins/messageStorage/sqlite"; +import {StorageCleaner} from "../storageCleaner"; const program = new Command("storage").description( "various utilities related to the message storage" @@ -10,7 +11,7 @@ const program = new Command("storage").description( program .command("migrate") - .argument("[user]", "migrate a specific user only, all if not provided") + .argument("[username]", "migrate a specific user only, all if not provided") .description("Migrate message storage where needed") .on("--help", Utils.extraHelp) .action(function (user) { @@ -20,7 +21,19 @@ program }); }); -async function runMigrations(user: string) { +program + .command("clean") + .argument("[user]", "clean messages for a specific user only, all if not provided") + .description("Delete messages from the DB based on the storage policy") + .on("--help", Utils.extraHelp) + .action(function (user) { + runCleaning(user).catch((err) => { + log.error(err.toString()); + process.exit(1); + }); + }); + +async function runMigrations(user?: string) { const manager = new ClientManager(); const users = manager.getUsers(); @@ -65,4 +78,46 @@ function isUserLogEnabled(manager: ClientManager, user: string): boolean { return conf.log; } +async function runCleaning(user: string) { + const manager = new ClientManager(); + const users = manager.getUsers(); + + if (user) { + if (!users.includes(user)) { + throw new Error(`invalid user ${user}`); + } + + return cleanUser(manager, user); + } + + for (const name of users) { + await cleanUser(manager, name); + // if any migration fails we blow up, + // chances are the rest won't complete either + } +} + +async function cleanUser(manager: ClientManager, user: string) { + log.info("handling user", user); + + if (!isUserLogEnabled(manager, user)) { + log.info("logging disabled for user", user, ". Skipping"); + return; + } + + const sqlite = new SqliteMessageStorage(user); + await sqlite.enable(); + const cleaner = new StorageCleaner(sqlite); + const num_deleted = await cleaner.runDeletesNoLimit(); + log.info(`deleted ${num_deleted} messages`); + log.info("running a vacuum now, this might take a while"); + + if (num_deleted > 0) { + await sqlite.vacuum(); + } + + await sqlite.close(); + log.info(`cleaning messages for ${user} has been successful`); +} + export default program; From 80c378961acad6ebca18ec0415252c0c54b90e13 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:12:12 +0000 Subject: [PATCH 09/18] Activate storage cleaner on server start --- server/client.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/client.ts b/server/client.ts index 648e4aa9..84e82d88 100644 --- a/server/client.ts +++ b/server/client.ts @@ -18,6 +18,7 @@ import TextFileMessageStorage from "./plugins/messageStorage/text"; import Network, {IgnoreListItem, NetworkConfig, NetworkWithIrcFramework} from "./models/network"; import ClientManager from "./clientManager"; import {MessageStorage, SearchQuery, SearchResponse} from "./plugins/messageStorage/types"; +import { StorageCleaner } from "./storageCleaner"; type OrderItem = Chan["id"] | Network["uuid"]; type Order = OrderItem[]; @@ -138,6 +139,13 @@ class Client { if (!Config.values.public && client.config.log) { if (Config.values.messageStorage.includes("sqlite")) { client.messageProvider = new SqliteMessageStorage(client.name); + if (Config.values.storagePolicy.enabled) { + log.info( + `Activating storage cleaner. Policy: ${Config.values.storagePolicy.deletionPolicy}. MaxAge: ${Config.values.storagePolicy.maxAgeDays} days` + ); + const cleaner = new StorageCleaner(client.messageProvider); + cleaner.start(); + } client.messageStorage.push(client.messageProvider); } From e6ab6ae8caa434b05149ae9e69e4940e044d303b Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:17:39 +0000 Subject: [PATCH 10/18] Add msg type index to speed up cleaner --- server/plugins/messageStorage/sqlite.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/plugins/messageStorage/sqlite.ts b/server/plugins/messageStorage/sqlite.ts index 5525d5bd..4d2adb7a 100644 --- a/server/plugins/messageStorage/sqlite.ts +++ b/server/plugins/messageStorage/sqlite.ts @@ -38,7 +38,7 @@ type Rollback = { stmts: string[]; }; -export const currentSchemaVersion = 1679743888000; // use `new Date().getTime()` +export const currentSchemaVersion = 1703322560448; // use `new Date().getTime()` // Desired schema, adapt to the newest version and add migrations to the array below const schema = [ @@ -57,6 +57,7 @@ const schema = [ )`, "CREATE INDEX network_channel ON messages (network, channel)", "CREATE INDEX time ON messages (time)", + "CREATE INDEX msg_type_idx on messages (type)", ]; // the migrations will be executed in an exclusive transaction as a whole @@ -90,6 +91,10 @@ export const migrations: Migration[] = [ )`, ], }, + { + version: 1703322560448, + stmts: ["CREATE INDEX msg_type_idx on messages (type)"] + } ]; // down migrations need to restore the state of the prior version. @@ -103,6 +108,10 @@ export const rollbacks: Rollback[] = [ version: 1679743888000, stmts: [], // here we can't drop the tables, as we use them in the code, so just leave those in }, + { + version: 1703322560448, + stmts: ["drop INDEX msg_type_idx"] + } ]; class Deferred { From a0f0dae3f72bf6aaeea5a74e4fe1f52a2c605123 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:20:36 +0000 Subject: [PATCH 11/18] dont use next() in router guards --- client/js/router.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/client/js/router.ts b/client/js/router.ts index c5e2879e..a2bd691b 100644 --- a/client/js/router.ts +++ b/client/js/router.ts @@ -110,26 +110,23 @@ router.beforeEach((to, from, next) => { next(); }); -router.beforeEach((to, from, next) => { +router.beforeEach((to, from) => { // Disallow navigating to non-existing routes if (!to.matched.length) { - next(false); - return; + return false; } // Disallow navigating to invalid channels if (to.name === "RoutedChat" && !store.getters.findChannel(Number(to.params.id))) { - next(false); - return; + return false; } // Disallow navigating to invalid networks if (to.name === "NetworkEdit" && !store.getters.findNetwork(String(to.params.uuid))) { - next(false); - return; + return false; } - next(); + return true; }); router.afterEach((to) => { From ef48c54cb380ad65e141442323c6cbb0ff4d6b69 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:22:27 +0000 Subject: [PATCH 12/18] Dont run coverage report --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6393eec..7b93a295 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "lint": "run-p --aggregate-output --continue-on-error lint:*", "start": "node index start", "test": "run-p --aggregate-output --continue-on-error lint:* test:*", - "test:mocha": "cross-env NODE_ENV=test webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' nyc --nycrc-path=test/.nycrc-mocha.json mocha --require ts-node/register --colors --config=test/.mocharc.yml", + "test:mocha": "cross-env NODE_ENV=test webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --require ts-node/register --colors --config=test/.mocharc.yml", "watch": "webpack --watch" }, "keywords": [ From e456afa6c4c74d86831fd5ab83d26bdb8841fb1c Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:22:59 +0000 Subject: [PATCH 13/18] Webpack doesnt switch on NODE_ENV=test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b93a295..fa9121e9 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "lint": "run-p --aggregate-output --continue-on-error lint:*", "start": "node index start", "test": "run-p --aggregate-output --continue-on-error lint:* test:*", - "test:mocha": "cross-env NODE_ENV=test webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --require ts-node/register --colors --config=test/.mocharc.yml", + "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --require ts-node/register --colors --config=test/.mocharc.yml", "watch": "webpack --watch" }, "keywords": [ From f922d783e0468543c668fa0978b75336031e808a Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:23:31 +0000 Subject: [PATCH 14/18] mocharc: remove interactive --- test/.mocharc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.mocharc.yml b/test/.mocharc.yml index 5934e4b4..c6a989c7 100644 --- a/test/.mocharc.yml +++ b/test/.mocharc.yml @@ -2,7 +2,6 @@ color: true check-leaks: true recursive: true reporter: dot -interactive: false spec: "test/**/*.ts" ignore: "test/client/**" extension: ["ts", "js"] From a3e00c95f50fd36ed4be2a0e0c5aaeee10fd3aa7 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:24:32 +0000 Subject: [PATCH 15/18] mocha: remove duplicate flags --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa9121e9..428ea227 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "lint": "run-p --aggregate-output --continue-on-error lint:*", "start": "node index start", "test": "run-p --aggregate-output --continue-on-error lint:* test:*", - "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --require ts-node/register --colors --config=test/.mocharc.yml", + "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.yml", "watch": "webpack --watch" }, "keywords": [ From 3e3ab257a5d56110c43172343670b675de8c4fb7 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:25:04 +0000 Subject: [PATCH 16/18] test: be specific as to which command we want to invoke --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 428ea227..1cf2c920 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "lint:stylelint": "stylelint --color \"client/**/*.css\"", "lint": "run-p --aggregate-output --continue-on-error lint:*", "start": "node index start", - "test": "run-p --aggregate-output --continue-on-error lint:* test:*", + "test": "run-p --aggregate-output --continue-on-error lint:* test:mocha", "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.yml", "watch": "webpack --watch" }, From bd0da6df13db25ff8f4604a553b3350467180aa8 Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:26:14 +0000 Subject: [PATCH 17/18] mocha: move spec to invocation --- package.json | 3 ++- test/.mocharc.yml | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1cf2c920..42ce93f5 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "lint": "run-p --aggregate-output --continue-on-error lint:*", "start": "node index start", "test": "run-p --aggregate-output --continue-on-error lint:* test:mocha", - "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.yml", + "test:mocha": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.yml 'test/**/*.ts'", + "test:nospec": "webpack --mode=development && cross-env NODE_ENV=test TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.yml", "watch": "webpack --watch" }, "keywords": [ diff --git a/test/.mocharc.yml b/test/.mocharc.yml index c6a989c7..4e0d5796 100644 --- a/test/.mocharc.yml +++ b/test/.mocharc.yml @@ -2,7 +2,6 @@ color: true check-leaks: true recursive: true reporter: dot -spec: "test/**/*.ts" ignore: "test/client/**" extension: ["ts", "js"] require: From 5cdfaa801968dfcac868a5eff5d8680203b04b3a Mon Sep 17 00:00:00 2001 From: hgw Date: Fri, 2 Feb 2024 03:28:57 +0000 Subject: [PATCH 18/18] Remove node 16 support, bump github build tests to node 21 --- .github/workflows/build.yml | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f2056be..ccc1d3b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,9 +12,7 @@ jobs: strategy: matrix: include: - # EOL: April 2024 - - os: ubuntu-latest - node_version: 16.x + # EOL: April 2025 - os: macOS-latest node_version: 18.x - os: windows-latest @@ -25,6 +23,9 @@ jobs: # EOL: April 2026 - os: ubuntu-latest node_version: 20.x + # EOL: April/June 2024 + - os: ubuntu-latest + node_version: 21.x runs-on: ${{ matrix.os }} diff --git a/package.json b/package.json index 42ce93f5..914e9b08 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ ], "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "files": [ "./.thelounge_home",