From cfe7f3d0dd823e4186d57153085d460b0880eea3 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Wed, 12 Mar 2025 01:10:51 +0300 Subject: [PATCH 01/17] [npm] Update dependencies install axios replace request with axios in post request migrate downloadUrlPromise from request to axios [feature] Clone sealed config objects before passing to external libraries using config.util.cloneDeep [deploy] Build and deploy server grunt module refactor fix typo update deprecated aws package update 3d party.md --- 3DPARTY.md | 81 +- Common/config/default.json | 13 +- Common/npm-shrinkwrap.json | 1017 +++-- Common/package.json | 32 +- Common/sources/activeMQCore.js | 2 +- Common/sources/mailService.js | 2 +- Common/sources/notificationService.js | 4 +- Common/sources/rabbitMQCore.js | 2 +- Common/sources/storage-s3.js | 4 +- Common/sources/taskqueueRabbitMQ.js | 10 +- Common/sources/tenantManager.js | 2 +- Common/sources/utils.js | 410 +- DocService/npm-shrinkwrap.json | 1576 +++----- DocService/package.json | 46 +- DocService/sources/DocsCoServer.js | 4 +- .../databaseConnectors/baseConnector.js | 2 +- .../databaseConnectors/damengConnector.js | 2 +- .../databaseConnectors/mssqlConnector.js | 2 +- .../databaseConnectors/mysqlConnector.js | 2 +- .../databaseConnectors/oracleConnector.js | 2 +- .../databaseConnectors/postgreConnector.js | 2 +- DocService/sources/pubsubRabbitMQ.js | 4 +- FileConverter/npm-shrinkwrap.json | 31 +- FileConverter/package.json | 7 +- FileConverter/sources/converter.js | 4 +- npm-shrinkwrap.json | 3558 ++++------------- package.json | 61 +- tests/unit/utils.tests.js | 2 +- 28 files changed, 2296 insertions(+), 4588 deletions(-) diff --git a/3DPARTY.md b/3DPARTY.md index e6806317..27aa6fe0 100644 --- a/3DPARTY.md +++ b/3DPARTY.md @@ -2,67 +2,64 @@ ## Third-party - @aws-sdk/client-s3 3.637.0 ([Apache-2.0](https://raw.githubusercontent.com/aws/aws-sdk-js-v3/main/LICENSE)) -- @aws-sdk/node-http-handler 3.374.0 ([Apache-2.0](https://raw.githubusercontent.com/aws/aws-sdk-js-v3/main/LICENSE)) +- @smithy/node-http-handler 4.0.3 ([Apache-2.0](https://raw.githubusercontent.com/smithy-lang/smithy-typescript/main/LICENSE)) - @aws-sdk/s3-request-presigner 3.370.0 ([Apache-2.0](https://raw.githubusercontent.com/aws/aws-sdk-js-v3/main/LICENSE)) -- amqplib 0.8.0 ([MIT](https://raw.githubusercontent.com/amqp-node/amqplib/main/LICENSE)) +- amqplib 0.10.5 ([MIT](https://raw.githubusercontent.com/amqp-node/amqplib/main/LICENSE)) - co 4.6.0 ([MIT](https://raw.githubusercontent.com/tj/co/master/LICENSE)) -- config 2.0.1 ([MIT](https://raw.githubusercontent.com/node-config/node-config/master/LICENSE)) -- content-disposition 0.5.3 ([MIT](https://raw.githubusercontent.com/jshttp/content-disposition/master/LICENSE)) -- dnscache 1.0.1 ([BSD](https://raw.githubusercontent.com/yahoo/dnscache/master/LICENSE)) +- config 3.3.12 ([MIT](https://raw.githubusercontent.com/node-config/node-config/master/LICENSE)) +- content-disposition 0.5.4 ([MIT](https://raw.githubusercontent.com/jshttp/content-disposition/master/LICENSE)) +- dnscache 1.0.2 ([BSD](https://raw.githubusercontent.com/yahoo/dnscache/master/LICENSE)) - escape-string-regexp 1.0.5 ([MIT](https://raw.githubusercontent.com/sindresorhus/escape-string-regexp/main/license)) -- forwarded 0.1.2 ([MIT](https://raw.githubusercontent.com/jshttp/forwarded/master/LICENSE)) -- ipaddr.js 1.8.1 ([MIT](https://raw.githubusercontent.com/whitequark/ipaddr.js/main/LICENSE)) -- jsonwebtoken 9.0.0 ([MIT](https://raw.githubusercontent.com/auth0/node-jsonwebtoken/master/LICENSE)) -- log4js 6.4.1 ([Apache-2.0](https://raw.githubusercontent.com/log4js-node/log4js-node/master/LICENSE)) +- forwarded 0.2.0 ([MIT](https://raw.githubusercontent.com/jshttp/forwarded/master/LICENSE)) +- ipaddr.js 2.2.0 ([MIT](https://raw.githubusercontent.com/whitequark/ipaddr.js/main/LICENSE)) +- jsonwebtoken 9.0.2 ([MIT](https://raw.githubusercontent.com/auth0/node-jsonwebtoken/master/LICENSE)) +- log4js 6.9.1 ([Apache-2.0](https://raw.githubusercontent.com/log4js-node/log4js-node/master/LICENSE)) - mime 2.3.1 ([MIT](https://raw.githubusercontent.com/broofa/mime/main/LICENSE)) -- ms 2.1.1 ([MIT](https://raw.githubusercontent.com/vercel/ms/main/license.md)) -- node-cache 4.2.1 ([MIT](https://raw.githubusercontent.com/node-cache/node-cache/master/LICENSE)) +- ms 2.1.3 ([MIT](https://raw.githubusercontent.com/vercel/ms/main/license.md)) +- node-cache 5.1.2 ([MIT](https://raw.githubusercontent.com/node-cache/node-cache/master/LICENSE)) - node-statsd 0.1.1 ([MIT](https://raw.githubusercontent.com/sivy/node-statsd/master/LICENSE)) -- nodemailer 6.9.13 ([MIT-0](https://raw.githubusercontent.com/nodemailer/nodemailer/master/LICENSE)) -- request 2.88.0 ([Apache-2.0](https://raw.githubusercontent.com/request/request/master/LICENSE)) +- nodemailer 6.10.0 ([MIT-0](https://raw.githubusercontent.com/nodemailer/nodemailer/master/LICENSE)) +- axios 2.88.0 ([MIT](https://raw.githubusercontent.com/axios/axios/v1.x/LICENSE)) - request-filtering-agent 1.0.5 ([MIT](https://raw.githubusercontent.com/azu/request-filtering-agent/master/LICENSE)) -- rhea 1.0.24 ([Apache-2.0](https://raw.githubusercontent.com/amqp/rhea/main/LICENSE)) -- uri-js 4.2.2 ([BSD-2-Clause](https://raw.githubusercontent.com/garycourt/uri-js/master/LICENSE)) -- win-ca 3.5.0 ([MIT](https://raw.githubusercontent.com/ukoloff/win-ca/master/LICENSE)) -- ajv 8.9.0 ([MIT](https://raw.githubusercontent.com/ajv-validator/ajv/master/LICENSE)) +- rhea 3.0.3 ([Apache-2.0](https://raw.githubusercontent.com/amqp/rhea/main/LICENSE)) +- uri-js 4.4.1 ([BSD-2-Clause](https://raw.githubusercontent.com/garycourt/uri-js/master/LICENSE)) +- win-ca 3.5.1 ([MIT](https://raw.githubusercontent.com/ukoloff/win-ca/master/LICENSE)) - apicache 1.6.3 ([MIT](https://raw.githubusercontent.com/kwhitley/apicache/master/LICENSE)) -- base64-stream 1.0.0 ([MIT](https://github.com/mazira/base64-stream?tab=readme-ov-file#license)) -- body-parser 1.20.1 ([MIT](https://raw.githubusercontent.com/expressjs/body-parser/master/LICENSE)) +- body-parser 1.20.3 ([MIT](https://raw.githubusercontent.com/expressjs/body-parser/master/LICENSE)) - bottleneck 2.19.5 ([MIT](https://raw.githubusercontent.com/SGrondin/bottleneck/master/LICENSE)) -- bytes 3.0.0 ([MIT](https://raw.githubusercontent.com/visionmedia/bytes.js/master/LICENSE)) +- bytes 3.1.2 ([MIT](https://raw.githubusercontent.com/visionmedia/bytes.js/master/LICENSE)) - co 4.6.0 ([MIT](https://raw.githubusercontent.com/tj/co/master/LICENSE)) -- config 2.0.1 ([MIT](https://raw.githubusercontent.com/node-config/node-config/master/LICENSE)) +- config 3.3.12 ([MIT](https://raw.githubusercontent.com/node-config/node-config/master/LICENSE)) - cron 1.5.0 ([MIT](https://raw.githubusercontent.com/kelektiv/node-cron/main/LICENSE)) -- deep-equal 1.0.1 ([MIT](https://raw.githubusercontent.com/inspect-js/node-deep-equal/main/LICENSE)) -- dmdb 1.0.14280 ([none](https://www.npmjs.com/package/dmdb)) +- deep-equal 2.2.3 ([MIT](https://raw.githubusercontent.com/inspect-js/node-deep-equal/main/LICENSE)) +- dmdb 1.0.33801 ([none](https://www.npmjs.com/package/dmdb)) - ejs 3.1.10 ([Apache-2.0](https://raw.githubusercontent.com/mde/ejs/main/LICENSE)) - exif-parser 0.1.12 ([MIT](https://raw.githubusercontent.com/bwindels/exif-parser/master/LICENSE.md)) -- express 4.19.2 ([MIT](https://raw.githubusercontent.com/expressjs/express/master/LICENSE)) +- express 4.21.2 ([MIT](https://raw.githubusercontent.com/expressjs/express/master/LICENSE)) - fakeredis 2.0.0 ([MIT](https://github.com/hdachev/fakeredis?tab=readme-ov-file#license)) -- ioredis 5.3.1 ([MIT](https://raw.githubusercontent.com/redis/ioredis/main/LICENSE)) +- ioredis 5.6.0 ([MIT](https://raw.githubusercontent.com/redis/ioredis/main/LICENSE)) - jimp 0.22.10 ([MIT](https://raw.githubusercontent.com/jimp-dev/jimp/main/LICENSE)) -- jsonwebtoken 9.0.0 ([MIT](https://raw.githubusercontent.com/auth0/node-jsonwebtoken/master/LICENSE)) -- jwa 1.1.6 ([MIT](https://raw.githubusercontent.com/auth0/node-jwa/master/LICENSE)) +- jsonwebtoken 9.0.2 ([MIT](https://raw.githubusercontent.com/auth0/node-jsonwebtoken/master/LICENSE)) - mime 2.3.1 ([MIT](https://raw.githubusercontent.com/broofa/mime/main/LICENSE)) -- mime-db 1.49.0 ([MIT](https://raw.githubusercontent.com/jshttp/mime-db/master/LICENSE)) -- ms 2.1.1 ([MIT](https://raw.githubusercontent.com/vercel/ms/master/license.md)) +- mime-db 1.53.0 ([MIT](https://raw.githubusercontent.com/jshttp/mime-db/master/LICENSE)) +- ms 2.1.3 ([MIT](https://raw.githubusercontent.com/vercel/ms/master/license.md)) - mssql 9.1.1 ([MIT](https://raw.githubusercontent.com/tediousjs/node-mssql/master/LICENSE.md)) -- multer 1.4.3 ([MIT](https://raw.githubusercontent.com/expressjs/multer/master/LICENSE)) -- multi-integer-range 4.0.7 ([MIT](https://raw.githubusercontent.com/smikitky/node-multi-integer-range/master/LICENSE)) -- multiparty 4.2.1 ([MIT](https://raw.githubusercontent.com/pillarjs/multiparty/master/LICENSE)) -- mysql2 3.9.8 ([MIT](https://raw.githubusercontent.com/sidorares/node-mysql2/master/License)) -- oracledb 6.3.0 ([(Apache-2.0 OR UPL-1.0)](https://raw.githubusercontent.com/oracle/node-oracledb/main/LICENSE.txt)) -- pg 8.11.3 ([MIT](https://raw.githubusercontent.com/brianc/node-postgres/master/LICENSE)) -- redis 4.6.11 ([MIT](https://raw.githubusercontent.com/redis/node-redis/master/LICENSE)) -- retry 0.12.0 ([MIT](https://raw.githubusercontent.com/tim-kos/node-retry/master/License)) +- multer 1.4.4 ([MIT](https://raw.githubusercontent.com/expressjs/multer/master/LICENSE)) +- multi-integer-range 5.2.0 ([MIT](https://raw.githubusercontent.com/smikitky/node-multi-integer-range/master/LICENSE)) +- multiparty 4.2.3 ([MIT](https://raw.githubusercontent.com/pillarjs/multiparty/master/LICENSE)) +- mysql2 3.13.0 ([MIT](https://raw.githubusercontent.com/sidorares/node-mysql2/master/License)) +- oracledb 6.8.0 ([(Apache-2.0 OR UPL-1.0)](https://raw.githubusercontent.com/oracle/node-oracledb/main/LICENSE.txt)) +- pg 8.14.0 ([MIT](https://raw.githubusercontent.com/brianc/node-postgres/master/LICENSE)) +- redis 4.7.0 ([MIT](https://raw.githubusercontent.com/redis/node-redis/master/LICENSE)) +- retry 0.13.1 ([MIT](https://raw.githubusercontent.com/tim-kos/node-retry/master/License)) - socket.io 4.8.1 ([MIT](https://raw.githubusercontent.com/socketio/socket.io/main/LICENSE)) -- underscore 1.13.1 ([MIT](https://raw.githubusercontent.com/jashkenas/underscore/master/LICENSE)) +- underscore 1.13.7 ([MIT](https://raw.githubusercontent.com/jashkenas/underscore/master/LICENSE)) - utf7 1.0.2 ([BSD](https://www.npmjs.com/package/utf7)) -- windows-locale 1.0.1 ([MIT](https://raw.githubusercontent.com/TiagoDanin/Windows-Locale/master/LICENSE)) -- xmlbuilder2 3.0.2 ([MIT](https://raw.githubusercontent.com/oozcitak/xmlbuilder2/master/LICENSE)) +- windows-locale 1.1.3 ([MIT](https://raw.githubusercontent.com/TiagoDanin/Windows-Locale/master/LICENSE)) +- xmlbuilder2 3.1.1 ([MIT](https://raw.githubusercontent.com/oozcitak/xmlbuilder2/master/LICENSE)) - @expo/spawn-async 1.7.2 ([MIT](https://raw.githubusercontent.com/TritonDataCenter/node-spawn-async/master/LICENSE)) -- bytes 3.0.0 ([MIT](https://raw.githubusercontent.com/visionmedia/bytes.js/master/LICENSE)) +- bytes 3.1.2 ([MIT](https://raw.githubusercontent.com/visionmedia/bytes.js/master/LICENSE)) - co 4.6.0 ([MIT](https://raw.githubusercontent.com/tj/co/master/LICENSE)) -- config 2.0.1 ([MIT](https://github.com/node-config/node-config/blob/master/LICENSE)) +- config 3.3.12 ([MIT](https://github.com/node-config/node-config/blob/master/LICENSE)) - lcid 3.1.1 ([MIT](https://raw.githubusercontent.com/sindresorhus/lcid/main/license)) - statsd 0.8.4 ([MIT](https://raw.githubusercontent.com/statsd/statsd/master/LICENSE)) diff --git a/Common/config/default.json b/Common/config/default.json index d681de7b..9c51012f 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -316,13 +316,12 @@ "forceSaveUsingButtonWithoutChanges": false }, "requestDefaults": { - "headers": { - "User-Agent": "Node.js/6.13", - "Connection": "Keep-Alive" - }, - "gzip": true, - "rejectUnauthorized": true - }, + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, + "decompress": true + }, "autoAssembly": { "enable": false, "interval": "5m", diff --git a/Common/npm-shrinkwrap.json b/Common/npm-shrinkwrap.json index 018e87c8..0b16072e 100644 --- a/Common/npm-shrinkwrap.json +++ b/Common/npm-shrinkwrap.json @@ -4,6 +4,16 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@acuminous/bitsyntax": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz", + "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==", + "requires": { + "buffer-more-ints": "~1.0.0", + "debug": "^4.3.4", + "safe-buffer": "~5.1.2" + } + }, "@aws-crypto/crc32": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", @@ -2771,15 +2781,6 @@ } } }, - "@aws-sdk/node-http-handler": { - "version": "3.374.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.374.0.tgz", - "integrity": "sha512-v1Z6m0wwkf65/tKuhwrtPRqVoOtNkDTRn2MBMtxCwEw+8V8Q+YRFqVgGN+J1n53ktE0G5OYVBux/NHiAjJHReQ==", - "requires": { - "@smithy/node-http-handler": "^1.0.2", - "tslib": "^2.5.0" - } - }, "@aws-sdk/region-config-resolver": { "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", @@ -3077,12 +3078,27 @@ } }, "@smithy/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-tb2h0b+JvMee+eAxTmhnyqyNk51UXIK949HnE14lFeezKsVJTB30maan+CO2IMwnig2wVYQH84B5qk6ylmKCuA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "requires": { + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + } } }, "@smithy/chunked-blob-reader": { @@ -4170,15 +4186,57 @@ } }, "@smithy/node-http-handler": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.3.tgz", - "integrity": "sha512-PcPUSzTbIb60VCJCiH0PU0E6bwIekttsIEf5Aoo/M0oTfiqsxHTn0Rcij6QoH6qJy6piGKXzLSegspXg5+Kq6g==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", "requires": { - "@smithy/abort-controller": "^1.0.2", - "@smithy/protocol-http": "^1.1.1", - "@smithy/querystring-builder": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "requires": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "requires": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + } } }, "@smithy/property-provider": { @@ -4906,6 +4964,96 @@ "@smithy/util-hex-encoding": "^1.0.2", "@smithy/util-utf8": "^1.0.2", "tslib": "^2.5.0" + }, + "dependencies": { + "@smithy/abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.1.0.tgz", + "integrity": "sha512-5imgGUlZL4dW4YWdMYAKLmal9ny/tlenM81QZY7xYyb76z9Z/QOg7oM5Ak9HQl8QfFTlGVWwcMXl+54jroRgEQ==", + "requires": { + "@smithy/types": "^1.2.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "@smithy/types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", + "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", + "requires": { + "tslib": "^2.5.0" + } + } + } + }, + "@smithy/node-http-handler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.1.0.tgz", + "integrity": "sha512-d3kRriEgaIiGXLziAM8bjnaLn1fthCJeTLZIwEIpzQqe6yPX0a+yQoLCTyjb2fvdLwkMoG4p7THIIB5cj5lkbg==", + "requires": { + "@smithy/abort-controller": "^1.1.0", + "@smithy/protocol-http": "^1.2.0", + "@smithy/querystring-builder": "^1.1.0", + "@smithy/types": "^1.2.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "@smithy/types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", + "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", + "requires": { + "tslib": "^2.5.0" + } + } + } + }, + "@smithy/protocol-http": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.2.0.tgz", + "integrity": "sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q==", + "requires": { + "@smithy/types": "^1.2.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "@smithy/types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", + "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", + "requires": { + "tslib": "^2.5.0" + } + } + } + }, + "@smithy/querystring-builder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.1.0.tgz", + "integrity": "sha512-gDEi4LxIGLbdfjrjiY45QNbuDmpkwh9DX4xzrR2AzjjXpxwGyfSpbJaYhXARw9p17VH0h9UewnNQXNwaQyYMDA==", + "requires": { + "@smithy/types": "^1.2.0", + "@smithy/util-uri-escape": "^1.1.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "@smithy/types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", + "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", + "requires": { + "tslib": "^2.5.0" + } + } + } + }, + "@smithy/util-uri-escape": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz", + "integrity": "sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w==", + "requires": { + "tslib": "^2.5.0" + } + } } }, "@smithy/util-uri-escape": { @@ -4959,108 +5107,57 @@ } } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, "amqplib": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz", - "integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.5.tgz", + "integrity": "sha512-Dx5zmy0Ur+Q7LPPdhz+jx5IzmJBoHd15tOeAfQ8SuvEtyPJ20hBemhOBA4b1WeORCRa0ENM/kHCzmem1w/zHvQ==", "requires": { - "bitsyntax": "~0.1.0", - "bluebird": "^3.7.2", + "@acuminous/bitsyntax": "^0.1.2", "buffer-more-ints": "~1.0.0", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "~5.2.1", - "url-parse": "~1.5.1" - }, - "dependencies": { - "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==" - } + "url-parse": "~1.5.10" } }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "axios": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bitsyntax": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", - "requires": { - "buffer-more-ints": "~1.0.0", - "debug": "~2.6.9", - "safe-buffer": "~5.1.2" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { - "ms": "2.0.0" + "delayed-stream": "~1.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + } } } }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -5076,69 +5173,59 @@ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "config": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/config/-/config-2.0.1.tgz", - "integrity": "sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.12.tgz", + "integrity": "sha512-Vmx389R/QVM3foxqBzXO8t2tUikYZP64Q6vQxGrsMpREeJc/aWRnPRERXWsYzOHAumx/AOoILWe6nU3ZJL+6Sw==", "requires": { - "json5": "^1.0.1" + "json5": "^2.2.3" } }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" + "safe-buffer": "5.2.1" + }, + "dependencies": { + "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==" + } } }, "date-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", - "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==" + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==" }, "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { - "ms": "^2.1.1" + "ms": "^2.1.3" } }, "delayed-stream": { @@ -5147,21 +5234,22 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "dnscache": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dnscache/-/dnscache-1.0.1.tgz", - "integrity": "sha1-Qssrm/tej736OVqsdOEn/AUHTTE=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dnscache/-/dnscache-1.0.2.tgz", + "integrity": "sha512-2FFKzmLGOnD+Y378bRKH+gTjRMuSpH7OKgPy31KjjfCoKZx7tU8Dmqfd/3fhG2d/4bppuN8/KtWMUZBAcUCRnQ==", "requires": { - "asap": "~2.0.3", - "lodash.clone": "~4.3.2" + "asap": "^2.0.6", + "lodash.clone": "^4.5.0" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" } }, "ecdsa-sig-formatter": { @@ -5172,31 +5260,40 @@ "safe-buffer": "^5.0.1" } }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, "fast-xml-parser": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", @@ -5206,142 +5303,130 @@ } }, "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } + "follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "requires": { - "assert-plus": "^1.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" } }, - "http-signature": { + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "has-symbols": "^1.0.3" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } }, "ipaddr.js": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.1.tgz", - "integrity": "sha1-+kt5+kf9Pe9eOxWYJRYcClGclCc=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==" }, "is-electron": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz", - "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" }, "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "requires": { - "minimist": "^1.2.0" + "graceful-fs": "^4.1.6" } }, "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "requires": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "dependencies": { - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - } + "semver": "^7.5.4" } }, "jwa": { @@ -5363,57 +5448,56 @@ "safe-buffer": "^5.0.1" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=" - }, "lodash.clone": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.3.2.tgz", - "integrity": "sha1-5WsXa2gjp93jj38r9Y3n1ZcSAOk=", - "requires": { - "lodash._baseclone": "~4.5.0" - } + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "log4js": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", - "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "requires": { - "date-format": "^4.0.3", - "debug": "^4.3.3", - "flatted": "^3.2.4", + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", "rfdc": "^1.3.0", - "streamroller": "^3.0.2" - }, - "dependencies": { - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" + "streamroller": "^3.1.5" } }, "make-dir": { @@ -5424,6 +5508,11 @@ "pify": "^3.0.0" } }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "mime": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", @@ -5442,23 +5531,17 @@ "mime-db": "~1.37.0" } }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node-cache": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-4.2.1.tgz", - "integrity": "sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", "requires": { - "clone": "2.x", - "lodash": "^4.17.15" + "clone": "2.x" } }, "node-forge": { @@ -5472,85 +5555,30 @@ "integrity": "sha1-J6WTSHY9CvegN6wqAx/vPwUQE9M=" }, "nodemailer": { - "version": "6.9.13", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", - "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz", + "integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==" }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } - } - }, "request-filtering-agent": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/request-filtering-agent/-/request-filtering-agent-1.0.5.tgz", @@ -5569,19 +5597,19 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, "rhea": { - "version": "1.0.24", - "resolved": "https://registry.npmjs.org/rhea/-/rhea-1.0.24.tgz", - "integrity": "sha512-PEl62U2EhxCO5wMUZ2/bCBcXAVKN9AdMSNQOrp3+R5b77TEaOSiy16MQ0sIOmzj/iqsgIAgPs1mt3FYfu1vIXA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/rhea/-/rhea-3.0.3.tgz", + "integrity": "sha512-Y7se0USZQu6dErWSZ7eCmSVTMscyVfz/0+jjhBF7f9PqYfEXdIoQpPkC9Strks6wF9WytuBhn8w8Nz/tmBWpgA==", "requires": { - "debug": "0.8.0 - 3.5.0" + "debug": "^4.3.3" } }, "safe-buffer": { @@ -5589,18 +5617,10 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==" }, "split": { "version": "1.0.1", @@ -5610,81 +5630,16 @@ "through": "2" } }, - "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "streamroller": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", - "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", "requires": { - "date-format": "^4.0.3", - "debug": "^4.1.1", - "fs-extra": "^10.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "requires": { - "ms": "2.1.2" - } - }, - "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -5693,55 +5648,24 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "tslib": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } } }, "url-parse": { @@ -5758,31 +5682,16 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "win-ca": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/win-ca/-/win-ca-3.5.0.tgz", - "integrity": "sha512-0TgO/+2iz2pS3OxBy2ikovPHOYyZRdLRxRTT9ze7DpZwEpaahLFOBuac93GM3lYEVzDyf8fXskJjIX/EILvkhQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/win-ca/-/win-ca-3.5.1.tgz", + "integrity": "sha512-RNy9gpBS6cxWHjfbqwBA7odaHyT+YQNhtdpJZwYCFoxB/Dq22oeOZ9YCXMwjhLytKpo7JJMnKdJ/ve7N12zzfQ==", "requires": { "is-electron": "^2.2.0", "make-dir": "^1.3.0", "node-forge": "^1.2.1", "split": "^1.0.1" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/Common/package.json b/Common/package.json index 85f536c3..b1883a9c 100644 --- a/Common/package.json +++ b/Common/package.json @@ -5,27 +5,27 @@ "private": true, "dependencies": { "@aws-sdk/client-s3": "3.637.0", - "@aws-sdk/node-http-handler": "3.374.0", "@aws-sdk/s3-request-presigner": "3.370.0", - "amqplib": "0.8.0", + "@smithy/node-http-handler": "4.0.3", + "amqplib": "0.10.5", + "axios": "1.8.3", "co": "4.6.0", - "config": "2.0.1", - "content-disposition": "0.5.3", - "dnscache": "1.0.1", + "config": "3.3.12", + "content-disposition": "0.5.4", + "dnscache": "1.0.2", "escape-string-regexp": "1.0.5", - "forwarded": "0.1.2", - "ipaddr.js": "1.8.1", - "jsonwebtoken": "9.0.0", - "log4js": "6.4.1", + "forwarded": "0.2.0", + "ipaddr.js": "2.2.0", + "jsonwebtoken": "9.0.2", + "log4js": "6.9.1", "mime": "2.3.1", - "ms": "2.1.1", - "node-cache": "4.2.1", + "ms": "2.1.3", + "node-cache": "5.1.2", "node-statsd": "0.1.1", - "nodemailer": "6.9.13", - "request": "2.88.0", + "nodemailer": "6.10.0", "request-filtering-agent": "1.0.5", - "rhea": "1.0.24", - "uri-js": "4.2.2", - "win-ca": "3.5.0" + "rhea": "3.0.3", + "uri-js": "4.4.1", + "win-ca": "3.5.1" } } diff --git a/Common/sources/activeMQCore.js b/Common/sources/activeMQCore.js index d8353435..101b5b65 100644 --- a/Common/sources/activeMQCore.js +++ b/Common/sources/activeMQCore.js @@ -36,7 +36,7 @@ var container = require('rhea'); var logger = require('./logger'); const operationContext = require('./operationContext'); -const cfgRabbitSocketOptions = config.get('activemq.connectOptions'); +const cfgRabbitSocketOptions = config.util.cloneDeep(config.get('activemq.connectOptions')); var RECONNECT_TIMEOUT = 1000; diff --git a/Common/sources/mailService.js b/Common/sources/mailService.js index 6db4c41e..574022c2 100644 --- a/Common/sources/mailService.js +++ b/Common/sources/mailService.js @@ -35,7 +35,7 @@ const config = require('config'); const nodemailer = require('nodemailer'); -const cfgConnection = config.get('email.connectionConfiguration'); +const cfgConnection = config.util.cloneDeep(config.get('email.connectionConfiguration')); const connectionDefaultSettings = { pool: true, diff --git a/Common/sources/notificationService.js b/Common/sources/notificationService.js index afb146a5..5ba2f481 100644 --- a/Common/sources/notificationService.js +++ b/Common/sources/notificationService.js @@ -37,8 +37,8 @@ const ms = require('ms'); const mailService = require('./mailService'); -const cfgMailServer = config.get('email.smtpServerConfiguration'); -const cfgMailMessageDefaults = config.get('email.contactDefaults'); +const cfgMailServer = config.util.cloneDeep(config.get('email.smtpServerConfiguration')); +const cfgMailMessageDefaults = config.util.cloneDeep(config.get('email.contactDefaults')); const cfgEditorDataStorage = config.get('services.CoAuthoring.server.editorDataStorage'); const cfgEditorStatStorage = config.get('services.CoAuthoring.server.editorStatStorage'); const editorStatStorage = require('./../../DocService/sources/' + (cfgEditorStatStorage || cfgEditorDataStorage)); diff --git a/Common/sources/rabbitMQCore.js b/Common/sources/rabbitMQCore.js index c006d15d..2d720990 100644 --- a/Common/sources/rabbitMQCore.js +++ b/Common/sources/rabbitMQCore.js @@ -37,7 +37,7 @@ var logger = require('./logger'); const operationContext = require('./operationContext'); var cfgRabbitUrl = config.get('rabbitmq.url'); -var cfgRabbitSocketOptions = config.get('rabbitmq.socketOptions'); +var cfgRabbitSocketOptions = config.util.cloneDeep(config.get('rabbitmq.socketOptions')); var RECONNECT_TIMEOUT = 1000; diff --git a/Common/sources/storage-s3.js b/Common/sources/storage-s3.js index d45ce946..5d7ef028 100644 --- a/Common/sources/storage-s3.js +++ b/Common/sources/storage-s3.js @@ -39,7 +39,7 @@ const { S3Client, ListObjectsCommand, HeadObjectCommand} = require("@aws-sdk/cli const { GetObjectCommand, PutObjectCommand, CopyObjectCommand} = require("@aws-sdk/client-s3"); const { DeleteObjectsCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3"); const { getSignedUrl } = require("@aws-sdk/s3-request-presigner"); -const { NodeHttpHandler } = require("@aws-sdk/node-http-handler"); +const { NodeHttpHandler } = require("@smithy/node-http-handler"); const mime = require('mime'); const config = require('config'); const utils = require('./utils'); @@ -47,7 +47,7 @@ const ms = require('ms'); const commonDefines = require('./../../Common/sources/commondefines'); const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute')); -const cfgRequestDefaults = config.get('services.CoAuthoring.requestDefaults'); +const cfgRequestDefaults = config.util.cloneDeepconfig.get('services.CoAuthoring.requestDefaults'); //This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys. const MAX_DELETE_OBJECTS = 1000; diff --git a/Common/sources/taskqueueRabbitMQ.js b/Common/sources/taskqueueRabbitMQ.js index 23808df9..632bb8c0 100644 --- a/Common/sources/taskqueueRabbitMQ.js +++ b/Common/sources/taskqueueRabbitMQ.js @@ -46,11 +46,11 @@ const cfgMaxRedeliveredCount = config.get('FileConverter.converter.maxRedelivere const cfgQueueType = config.get('queue.type'); var cfgVisibilityTimeout = config.get('queue.visibilityTimeout'); var cfgQueueRetentionPeriod = config.get('queue.retentionPeriod'); -var cfgRabbitQueueConvertTask = config.get('rabbitmq.queueconverttask'); -var cfgRabbitQueueConvertResponse = config.get('rabbitmq.queueconvertresponse'); -var cfgRabbitExchangeConvertDead = config.get('rabbitmq.exchangeconvertdead'); -var cfgRabbitQueueConvertDead = config.get('rabbitmq.queueconvertdead'); -var cfgRabbitQueueDelayed = config.get('rabbitmq.queuedelayed'); +var cfgRabbitQueueConvertTask = config.util.cloneDeep(config.get('rabbitmq.queueconverttask')); +var cfgRabbitQueueConvertResponse = config.util.cloneDeep(config.get('rabbitmq.queueconvertresponse')); +var cfgRabbitExchangeConvertDead = config.util.cloneDeep(config.get('rabbitmq.exchangeconvertdead')); +var cfgRabbitQueueConvertDead = config.util.cloneDeep(config.get('rabbitmq.queueconvertdead')); +var cfgRabbitQueueDelayed = config.util.cloneDeep(config.get('rabbitmq.queuedelayed')); var cfgActiveQueueConvertTask = constants.ACTIVEMQ_QUEUE_PREFIX + config.get('activemq.queueconverttask'); var cfgActiveQueueConvertResponse = constants.ACTIVEMQ_QUEUE_PREFIX + config.get('activemq.queueconvertresponse'); var cfgActiveQueueConvertDead = constants.ACTIVEMQ_QUEUE_PREFIX + config.get('activemq.queueconvertdead'); diff --git a/Common/sources/tenantManager.js b/Common/sources/tenantManager.js index 703c81d2..0d8fd3aa 100644 --- a/Common/sources/tenantManager.js +++ b/Common/sources/tenantManager.js @@ -48,7 +48,7 @@ const cfgTenantsFilenameSecret = config.get('tenants.filenameSecret'); const cfgTenantsFilenameLicense = config.get('tenants.filenameLicense'); const cfgTenantsFilenameConfig = config.get('tenants.filenameConfig'); const cfgTenantsDefaultTenant = config.get('tenants.defaultTenant'); -const cfgTenantsCache = config.get('tenants.cache'); +const cfgTenantsCache = config.util.cloneDeep(config.get('tenants.cache')); const cfgSecretInbox = config.get('services.CoAuthoring.secret.inbox'); const cfgSecretOutbox = config.get('services.CoAuthoring.secret.outbox'); const cfgSecretSession = config.get('services.CoAuthoring.secret.session'); diff --git a/Common/sources/utils.js b/Common/sources/utils.js index aa64dffa..0f1d9301 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -41,7 +41,7 @@ var fs = require('fs'); var path = require('path'); const crypto = require('crypto'); var url = require('url'); -var request = require('request'); +var axios = require('axios') var co = require('co'); var URI = require("uri-js"); const escapeStringRegexp = require('escape-string-regexp'); @@ -61,7 +61,8 @@ const util = require('util'); const contentDisposition = require('content-disposition'); const operationContext = require("./operationContext"); -const cfgDnsCache = config.get('dnscache'); +//Clone sealed config objects before passing to external libraries using config.util.cloneDeep +const cfgDnsCache = config.util.cloneDeep(config.get('dnscache')); const cfgIpFilterRules = config.get('services.CoAuthoring.ipfilter.rules'); const cfgIpFilterErrorCode = config.get('services.CoAuthoring.ipfilter.errorcode'); const cfgIpFilterUseForRequest = config.get('services.CoAuthoring.ipfilter.useforrequest'); @@ -73,16 +74,16 @@ const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.al const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires'); const cfgVisibilityTimeout = config.get('queue.visibilityTimeout'); const cfgQueueRetentionPeriod = config.get('queue.retentionPeriod'); -const cfgRequestDefaults = config.get('services.CoAuthoring.requestDefaults'); +const cfgRequestDefaults = config.util.cloneDeep(config.get('services.CoAuthoring.requestDefaults')); const cfgTokenEnableRequestOutbox = config.get('services.CoAuthoring.token.enable.request.outbox'); const cfgTokenOutboxUrlExclusionRegex = config.get('services.CoAuthoring.token.outbox.urlExclusionRegex'); const cfgSecret = config.get('aesEncrypt.secret'); -const cfgAESConfig = config.get('aesEncrypt.config'); +const cfgAESConfig = config.util.cloneDeep(config.get('aesEncrypt.config')); const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent'); const cfgStorageExternalHost = config.get('storage.externalHost'); const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn'); const cfgExternalRequestAction = config.get('externalRequest.action'); -const cfgWinCa = config.get('win-ca'); +const cfgWinCa = config.util.cloneDeep(config.get('win-ca')); ca(cfgWinCa); @@ -323,20 +324,19 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { } function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { - //todo replace deprecated request module const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const maxRedirects = (undefined !== tenTenantRequestDefaults.maxRedirects) ? tenTenantRequestDefaults.maxRedirects : 10; const followRedirect = (undefined !== tenTenantRequestDefaults.followRedirect) ? tenTenantRequestDefaults.followRedirect : true; var redirectsFollowed = 0; - let doRequest = function(curUrl) { + const doRequest = (curUrl) => { return downloadUrlPromiseWithoutRedirect(ctx, curUrl, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) - .catch(function(err) { - let response = err.response; + .catch(err => { + const response = err.response; if (isRedirectResponse(response)) { - let redirectTo = response.caseless.get('location'); if (followRedirect && redirectsFollowed < maxRedirects) { - if (!/^https?:/.test(redirectTo) && err.request) { - redirectTo = url.resolve(err.request.uri.href, redirectTo) + let redirectTo = response.headers.location; + if (!/^https?:/.test(redirectTo)) { + redirectTo = url.resolve(curUrl, redirectTo); } ctx.logger.debug('downloadUrlPromise redirectsFollowed:%d redirectTo: %s', redirectsFollowed, redirectTo); @@ -349,188 +349,252 @@ function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, o }; return doRequest(uri); } -function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { - return new Promise(function (resolve, reject) { - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); - const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); - const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - //IRI to URI - uri = URI.serialize(URI.parse(uri)); - var urlParsed = url.parse(uri); - let sizeLimit = optLimit || Number.MAX_VALUE; - let bufferLength = 0, timeoutId; - let hash = crypto.createHash('sha256'); - //if you expect binary data, you should set encoding: null - let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); - let options = config.util.extendDeep({}, tenTenantRequestDefaults); - Object.assign(options, {uri: urlParsed, encoding: null, timeout: connectionAndInactivity, followRedirect: false}); - if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { - reject(new Error('Block external request. See externalRequest config options')); - return; +async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { + const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); + const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); + const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); + // uri = URI.serialize(URI.parse(uri)); + const sizeLimit = optLimit || Number.MAX_VALUE + + const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; + const options = config.util.cloneDeep(tenTenantRequestDefaults); + if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { + throw new Error('Block external request. See externalRequest config options'); + } + + const headers = { ...options.headers }; + if (opt_Authorization) { + headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; + } + if (opt_headers) { + Object.assign(headers, opt_headers); + } + + const agentOptions = options.agent ? undefined : (https.globalAgent.options || {}); + const axiosConfig = { + url: uri, + method: 'GET', + responseType: 'stream', + headers, + maxRedirects: 0, + timeout: connectionAndInactivity, + validateStatus: () => true, + httpsAgent: uri.protocol === 'https:' + ? new https.Agent(agentOptions) + : undefined, + cancelToken: new axios.CancelToken(cancel => { + if (optTimeout?.wholeCycle) { + setTimeout(() => cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`), ms(optTimeout.wholeCycle)); + } + }) + }; + + try { + const response = await axios(axiosConfig); + const { status, headers } = response; + + if (isRedirectResponse(response)) { + const error = new Error(`Redirect ${status}`); + error.response = response; + throw error; } - if (!options.agent) { - //baseRequest creates new agent(win-ca injects in globalAgent) - options.agentOptions = https.globalAgent.options; + const contentLength = headers['content-length']; + if (contentLength && parseInt(contentLength) > sizeLimit) { + throw new Error('EMSGSIZE: Content-Length exceeds limit'); } - if (!options.headers) { - options.headers = {}; + + return await processResponseStream(ctx, { + response, + sizeLimit, + uri, + opt_streamWriter, + contentLength, + timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null + }); + } catch (err) { + if (axios.isCancel(err)) { + const error = new Error(err.message); + error.code = 'ETIMEDOUT'; + throw error; } - if (opt_Authorization) { - options.headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; - } - if (opt_headers) { - Object.assign(options.headers, opt_headers); - } - let fError = function(err) { - clearTimeout(timeoutId); - reject(err); - } - if (!opt_streamWriter) { - fError = function() {}; - let executed = false; - options.callback = function(err, response, body) { - if (executed) { - return; - } - executed = true; - if (err) { - clearTimeout(timeoutId); - reject(err); - } else { - var contentLength = response.caseless.get('content-length'); - if (contentLength && body.length !== (contentLength - 0)) { - ctx.logger.warn('downloadUrlPromise body size mismatch: uri=%s; content-length=%s; body.length=%d', uri, contentLength, body.length); - } - let sha256 = hash.digest('hex'); - clearTimeout(timeoutId); - resolve({response: response, body: body, sha256: sha256}); - } - }; - } - let fResponse = function(response) { - if (opt_streamWriter) { - //Set-Cookie resets browser session - response.caseless.del('Set-Cookie'); + + if (err.response) { + if (opt_streamWriter && !isRedirectResponse(err.response)) { + return processErrorResponseStream(err.response, { + sizeLimit, + opt_streamWriter, + timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null + }); } - var contentLength = response.caseless.get('content-length'); - if (contentLength && (contentLength - 0) > sizeLimit) { - raiseError(this, 'EMSGSIZE', 'Error response: content-length:' + contentLength); - } else if (response.statusCode !== 200 && response.statusCode !== 206) { - let code = response.statusCode; - let responseHeaders = JSON.stringify(response.headers); - let error = new Error(`Error response: statusCode:${code}; headers:${responseHeaders};`); - error.statusCode = response.statusCode; - error.request = this; - error.response = response; - if (opt_streamWriter && !isRedirectResponse(response)) { - this.off('error', fError); - pipeline(this, opt_streamWriter) - .then(resolve, reject) - .finally(() => { - clearTimeout(timeoutId); - }); - } else { - raiseErrorObj(this, error); - } - } else if (opt_streamWriter) { - this.off('error', fError); - pipeline(this, opt_streamWriter) - .then(resolve, reject) - .finally(() => { - clearTimeout(timeoutId); - }); - } - }; - let fData = function(chunk) { + } + throw err; + } +} + +async function processResponseStream(ctx, { response, sizeLimit, uri, opt_streamWriter, contentLength, timeout }) { + return new Promise((resolve, reject) => { + const hash = crypto.createHash('sha256'); + let buffer = []; + let bufferLength = 0; + let timeoutId; + + const stream = response.data; + + if (timeout) { + timeoutId = setTimeout(() => { + stream.destroy(); + reject(new Error(`ETIMEDOUT: ${timeout}`)); + }, timeout); + } + + stream.on('data', chunk => { hash.update(chunk); bufferLength += chunk.length; if (bufferLength > sizeLimit) { - raiseError(this, 'EMSGSIZE', 'Error response body.length'); + stream.destroy(); + reject(new Error('EMSGSIZE: Response body exceeds limit')); } - } + if (!opt_streamWriter) buffer.push(chunk); + }); - let ro = request.get(options) - .on('response', fResponse) - .on('data', fData) - .on('error', fError); - if (optTimeout && optTimeout.wholeCycle) { - timeoutId = setTimeout(function() { - raiseError(ro, 'ETIMEDOUT', `Error: whole request cycle timeout: ${optTimeout.wholeCycle}`); - }, ms(optTimeout.wholeCycle)); + stream.on('error', reject); + + stream.on('end', () => { + clearTimeout(timeoutId); + const result = { + response, + sha256: hash.digest('hex'), + body: opt_streamWriter ? null : Buffer.concat(buffer) + }; + + if (contentLength && result.body?.length !== parseInt(contentLength)) { + ctx.logger.warn('Body size mismatch: %s (expected %s, got %d)', + uri, contentLength, result.body?.length); + } + + resolve(result); + }); + + if (opt_streamWriter) { + pipeline(stream, opt_streamWriter) + .catch(reject); } }); } -function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_isInJwtToken, opt_headers) { - return new Promise(function(resolve, reject) { - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); - const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); - const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - //IRI to URI - uri = URI.serialize(URI.parse(uri)); - var urlParsed = url.parse(uri); - let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); - let options = config.util.extendDeep({}, tenTenantRequestDefaults); - Object.assign(options, {uri: urlParsed, encoding: 'utf8', timeout: connectionAndInactivity}); - if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { - reject(new Error('Block external request. See externalRequest config options')); - return; + +async function processErrorResponseStream(response, { sizeLimit, opt_streamWriter, timeout }) { + return new Promise((resolve, reject) => { + const hash = crypto.createHash('sha256'); + let bufferLength = 0; + let timeoutId; + + const stream = response.data; + + if (timeout) { + timeoutId = setTimeout(() => { + stream.destroy(); + reject(new Error(`ETIMEDOUT: ${timeout}`)); + }, timeout); } - if (!options.agent) { - //baseRequest creates new agent(win-ca injects in globalAgent) - options.agentOptions = https.globalAgent.options; - } - if (postData) { - options.body = postData; - } - if (!options.headers) { - options.headers = {}; - } - if (opt_Authorization) { - //todo ctx.getCfg - options.headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; - } - if (opt_headers) { - Object.assign(options.headers, opt_headers); - } - if (undefined !== postDataSize) { + + stream.on('data', chunk => { + hash.update(chunk); + bufferLength += chunk.length; + if (bufferLength > sizeLimit) { + stream.destroy(); + reject(new Error('EMSGSIZE')); + } + }); + + stream.on('error', reject); + + stream.on('end', () => { + clearTimeout(timeoutId); + resolve({ + response, + sha256: hash.digest('hex') + }); + }); + + pipeline(stream, opt_streamWriter) + .catch(reject); + }); +} + +async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_isInJwtToken, opt_headers) { + const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); + const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); + const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); + let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); + const wholeCycleTimeout = optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : undefined; + let options = config.util.extendDeep({}, tenTenantRequestDefaults); + Object.assign(options, { + method: 'post', + url: uri, + timeout: connectionAndInactivity, + validateStatus: (status) => status === 200 || status === 204 + }); + if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { + throw new Error('Block external request. See externalRequest config options') + } + if (!options.agent) { + //baseRequest creates new agent(win-ca injects in globalAgent) + options.httpsAgent = new https.Agent(https.globalAgent.options); + } + if (postData) { + options.data = postData; + } else if (postDataStream) { + options.data = postDataStream; + } + options.headers = options.headers || {}; + if (opt_Authorization) { + //todo ctx.getCfg + options.headers[tenTokenOutboxHeader] = `${tenTokenOutboxPrefix}${opt_Authorization}`; + } + if (opt_headers) { + Object.assign(options.headers, opt_headers); + } + if (undefined !== postDataSize) { //If no Content-Length is set, data will automatically be encoded in HTTP Chunked transfer encoding, //so that server knows when the data ends. The Transfer-Encoding: chunked header is added. //https://nodejs.org/api/http.html#requestwritechunk-encoding-callback //issue with Transfer-Encoding: chunked wopi and sharepoint 2019 //https://community.alteryx.com/t5/Dev-Space/Download-Tool-amp-Microsoft-SharePoint-Chunked-Request-Error/td-p/735824 - options.headers['Content-Length'] = postDataSize; + options.headers['Content-Length'] = postDataSize; + } + const cancelTokenSource = axios.CancelToken.source(); + if (wholeCycleTimeout) { + setTimeout(() => { + cancelTokenSource.cancel(`Whole request cycle timeout: ${optTimeout.wholeCycle}`); + }, wholeCycleTimeout); + } + options.cancelToken = cancelTokenSource.token; + try { + const response = await axios(options); + return { + response: { + statusCode: response.status, + headers: response.headers, + body: response.data + }, + body: JSON.stringify(response.data) } - let executed = false; - let ro = request.post(options, function(err, response, body) { - if (executed) { - return; - } - executed = true; - if (err) { - reject(err); - } else { - if (200 === response.statusCode || 204 === response.statusCode) { - resolve({response: response, body: body}); - } else { - let code = response.statusCode; - let responseHeaders = JSON.stringify(response.headers); - let error = new Error(`Error response: statusCode:${code}; headers:${responseHeaders}; body:\r\n${body}`); - error.statusCode = response.statusCode; - error.response = response; - reject(error); - } - } - }); - if (optTimeout && optTimeout.wholeCycle) { - setTimeout(function() { - raiseError(ro, 'ETIMEDOUT', `Error: whole request cycle timeout: ${optTimeout.wholeCycle}`); - }, ms(optTimeout.wholeCycle)); + } catch (error) { + if (axios.isCancel(error)) { + const err = new Error(error.message); + err.code = 'ETIMEDOUT'; + throw err; + } + if (error.response) { + const { status, headers, data } = error.response; + const err = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); + err.statusCode = status; + err.response = error.response; + throw err; } - if (postDataStream && !postData) { - postDataStream.pipe(ro); - } - }); + throw error; + } } exports.postRequestPromise = postRequestPromise; exports.downloadUrlPromise = downloadUrlPromise; diff --git a/DocService/npm-shrinkwrap.json b/DocService/npm-shrinkwrap.json index ed8b504d..42fb3328 100644 --- a/DocService/npm-shrinkwrap.json +++ b/DocService/npm-shrinkwrap.json @@ -121,24 +121,6 @@ "uuid": "^8.3.0" }, "dependencies": { - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, "jws": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", @@ -219,20 +201,20 @@ "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" }, "@jimp/bmp": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.10.tgz", - "integrity": "sha512-1UXRl1Nw1KptZ1r0ANqtXOst9vGH51dq7keVKQzyyTO2lz4dOaezS9StuSTNh+RmiHg/SVPaFRpPfB0S/ln4Kg==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.12.tgz", + "integrity": "sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g==", "requires": { - "@jimp/utils": "^0.22.10", + "@jimp/utils": "^0.22.12", "bmp-js": "^0.1.0" } }, "@jimp/core": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.10.tgz", - "integrity": "sha512-ZKyrehVy6wu1PnBXIUpn/fXmyMRQiVSbvHDubgXz4bfTOao3GiOurKHjByutQIgozuAN6ZHWiSge1dKA+dex3w==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.12.tgz", + "integrity": "sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA==", "requires": { - "@jimp/utils": "^0.22.10", + "@jimp/utils": "^0.22.12", "any-base": "^1.1.0", "buffer": "^5.2.0", "exif-parser": "^0.1.12", @@ -254,29 +236,29 @@ } }, "@jimp/custom": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.10.tgz", - "integrity": "sha512-sPZkUYe1hu0iIgNisjizxPJqq2vaaKvkCkPoXq2U6UV3ZA1si/WVdrg25da3IcGIEV+83AoHgM8TvqlLgrCJsg==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", + "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", "requires": { - "@jimp/core": "^0.22.10" + "@jimp/core": "^0.22.12" } }, "@jimp/gif": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.10.tgz", - "integrity": "sha512-yEX2dSpamvkSx1PPDWGnKeWDrBz0vrCKjVG/cn4Zr68MRRT75tbZIeOrBa+RiUpY3ho5ix7d36LkYvt3qfUIhQ==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.12.tgz", + "integrity": "sha512-y6BFTJgch9mbor2H234VSjd9iwAhaNf/t3US5qpYIs0TSbAvM02Fbc28IaDETj9+4YB4676sz4RcN/zwhfu1pg==", "requires": { - "@jimp/utils": "^0.22.10", + "@jimp/utils": "^0.22.12", "gifwrap": "^0.10.1", "omggif": "^1.0.9" } }, "@jimp/jpeg": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.10.tgz", - "integrity": "sha512-6bu98pAcVN4DY2oiDLC4TOgieX/lZrLd1tombWZOFCN5PBmqaHQxm7IUmT+Wj4faEvh8QSHgVLSA+2JQQRJWVA==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.12.tgz", + "integrity": "sha512-Rq26XC/uQWaQKyb/5lksCTCxXhtY01NJeBN+dQv5yNYedN0i7iYu+fXEoRsfaJ8xZzjoANH8sns7rVP4GE7d/Q==", "requires": { - "@jimp/utils": "^0.22.10", + "@jimp/utils": "^0.22.12", "jpeg-js": "^0.4.4" } }, @@ -286,16 +268,6 @@ "integrity": "sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-blur": { @@ -304,16 +276,6 @@ "integrity": "sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-circle": { @@ -322,16 +284,6 @@ "integrity": "sha512-SWVXx1yiuj5jZtMijqUfvVOJBwOifFn0918ou4ftoHgegc5aHWW5dZbYPjvC9fLpvz7oSlptNl2Sxr1zwofjTg==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-color": { @@ -341,16 +293,6 @@ "requires": { "@jimp/utils": "^0.22.12", "tinycolor2": "^1.6.0" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-contain": { @@ -359,16 +301,6 @@ "integrity": "sha512-Eo3DmfixJw3N79lWk8q/0SDYbqmKt1xSTJ69yy8XLYQj9svoBbyRpSnHR+n9hOw5pKXytHwUW6nU4u1wegHNoQ==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-cover": { @@ -377,16 +309,6 @@ "integrity": "sha512-z0w/1xH/v/knZkpTNx+E8a7fnasQ2wHG5ze6y5oL2dhH1UufNua8gLQXlv8/W56+4nJ1brhSd233HBJCo01BXA==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-crop": { @@ -395,16 +317,6 @@ "integrity": "sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-displace": { @@ -413,16 +325,6 @@ "integrity": "sha512-qpRM8JRicxfK6aPPqKZA6+GzBwUIitiHaZw0QrJ64Ygd3+AsTc7BXr+37k2x7QcyCvmKXY4haUrSIsBug4S3CA==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-dither": { @@ -431,16 +333,6 @@ "integrity": "sha512-jYgGdSdSKl1UUEanX8A85v4+QUm+PE8vHFwlamaKk89s+PXQe7eVE3eNeSZX4inCq63EHL7cX580dMqkoC3ZLw==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-fisheye": { @@ -449,16 +341,6 @@ "integrity": "sha512-LGuUTsFg+fOp6KBKrmLkX4LfyCy8IIsROwoUvsUPKzutSqMJnsm3JGDW2eOmWIS/jJpPaeaishjlxvczjgII+Q==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-flip": { @@ -467,16 +349,6 @@ "integrity": "sha512-m251Rop7GN8W0Yo/rF9LWk6kNclngyjIJs/VXHToGQ6EGveOSTSQaX2Isi9f9lCDLxt+inBIb7nlaLLxnvHX8Q==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-gaussian": { @@ -485,16 +357,6 @@ "integrity": "sha512-sBfbzoOmJ6FczfG2PquiK84NtVGeScw97JsCC3rpQv1PHVWyW+uqWFF53+n3c8Y0P2HWlUjflEla2h/vWShvhg==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-invert": { @@ -503,16 +365,6 @@ "integrity": "sha512-N+6rwxdB+7OCR6PYijaA/iizXXodpxOGvT/smd/lxeXsZ/empHmFFFJ/FaXcYh19Tm04dGDaXcNF/dN5nm6+xQ==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-mask": { @@ -521,16 +373,6 @@ "integrity": "sha512-4AWZg+DomtpUA099jRV8IEZUfn1wLv6+nem4NRJC7L/82vxzLCgXKTxvNvBcNmJjT9yS1LAAmiJGdWKXG63/NA==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-normalize": { @@ -539,16 +381,6 @@ "integrity": "sha512-0So0rexQivnWgnhacX4cfkM2223YdExnJTTy6d06WbkfZk5alHUx8MM3yEzwoCN0ErO7oyqEWRnEkGC+As1FtA==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-print": { @@ -558,16 +390,6 @@ "requires": { "@jimp/utils": "^0.22.12", "load-bmfont": "^1.4.1" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-resize": { @@ -576,16 +398,6 @@ "integrity": "sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-rotate": { @@ -594,16 +406,6 @@ "integrity": "sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-scale": { @@ -612,16 +414,6 @@ "integrity": "sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-shadow": { @@ -630,16 +422,6 @@ "integrity": "sha512-FX8mTJuCt7/3zXVoeD/qHlm4YH2bVqBuWQHXSuBK054e7wFRnRnbSLPUqAwSeYP3lWqpuQzJtgiiBxV3+WWwTg==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugin-threshold": { @@ -648,16 +430,6 @@ "integrity": "sha512-4x5GrQr1a/9L0paBC/MZZJjjgjxLYrqSmWd+e+QfAEPvmRxdRoQ5uKEuNgXnm9/weHQBTnQBQsOY2iFja+XGAw==", "requires": { "@jimp/utils": "^0.22.12" - }, - "dependencies": { - "@jimp/utils": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", - "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", - "requires": { - "regenerator-runtime": "^0.13.3" - } - } } }, "@jimp/plugins": { @@ -690,46 +462,39 @@ } }, "@jimp/png": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.10.tgz", - "integrity": "sha512-RYinU7tZToeeR2g2qAMn42AU+8OUHjXPKZZ9RkmoL4bguA1xyZWaSdr22/FBkmnHhOERRlr02KPDN1OTOYHLDQ==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.12.tgz", + "integrity": "sha512-Mrp6dr3UTn+aLK8ty/dSKELz+Otdz1v4aAXzV5q53UDD2rbB5joKVJ/ChY310B+eRzNxIovbUF1KVrUsYdE8Hg==", "requires": { - "@jimp/utils": "^0.22.10", + "@jimp/utils": "^0.22.12", "pngjs": "^6.0.0" - }, - "dependencies": { - "pngjs": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", - "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==" - } } }, "@jimp/tiff": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.10.tgz", - "integrity": "sha512-OaivlSYzpNTHyH/h7pEtl3A7F7TbsgytZs52GLX/xITW92ffgDgT6PkldIrMrET6ERh/hdijNQiew7IoEEr2og==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.12.tgz", + "integrity": "sha512-E1LtMh4RyJsoCAfAkBRVSYyZDTtLq9p9LUiiYP0vPtXyxX4BiYBUYihTLSBlCQg5nF2e4OpQg7SPrLdJ66u7jg==", "requires": { "utif2": "^4.0.1" } }, "@jimp/types": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.10.tgz", - "integrity": "sha512-u/r+XYzbCx4zZukDmxx8S0er3Yq3iDPI6+31WKX0N18i2qPPJYcn8qwIFurfupRumGvJ8SlGLCgt/T+Y8zzUIw==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.12.tgz", + "integrity": "sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA==", "requires": { - "@jimp/bmp": "^0.22.10", - "@jimp/gif": "^0.22.10", - "@jimp/jpeg": "^0.22.10", - "@jimp/png": "^0.22.10", - "@jimp/tiff": "^0.22.10", + "@jimp/bmp": "^0.22.12", + "@jimp/gif": "^0.22.12", + "@jimp/jpeg": "^0.22.12", + "@jimp/png": "^0.22.12", + "@jimp/tiff": "^0.22.12", "timm": "^1.6.1" } }, "@jimp/utils": { - "version": "0.22.10", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.10.tgz", - "integrity": "sha512-ztlOK9Mm2iLG2AMoabzM4i3WZ/FtshcgsJCbZCRUs/DKoeS2tySRJTnQZ1b7Roq0M4Ce+FUAxnCAcBV0q7PH9w==", + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", + "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", "requires": { "regenerator-runtime": "^0.13.3" } @@ -855,9 +620,9 @@ "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==" }, "@redis/client": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.12.tgz", - "integrity": "sha512-/ZjE18HRzMd80eXIIUIPcH81UoZpwulbo8FmbElrjPqH0QC0SeIKu1BOU49bO5trM5g895kAjhvalt5h77q+4A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", + "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", "requires": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -870,19 +635,19 @@ "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==" }, "@redis/json": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.6.tgz", - "integrity": "sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", + "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==" }, "@redis/search": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.6.tgz", - "integrity": "sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", + "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==" }, "@redis/time-series": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.5.tgz", - "integrity": "sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", + "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==" }, "@socket.io/component-emitter": { "version": "3.1.2", @@ -917,6 +682,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz", "integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -924,21 +697,6 @@ "requires": { "mime-types": "~2.1.34", "negotiator": "0.6.3" - }, - "dependencies": { - "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" - } - } } }, "agent-base": { @@ -964,17 +722,6 @@ } } }, - "ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1032,19 +779,6 @@ "get-intrinsic": "^1.2.1", "is-array-buffer": "^3.0.2", "is-shared-array-buffer": "^1.0.2" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - } } }, "async": { @@ -1058,9 +792,17 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "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==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==" }, "balanced-match": { "version": "1.0.2", @@ -1072,11 +814,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "base64-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-1.0.0.tgz", - "integrity": "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA==" - }, "base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", @@ -1092,11 +829,6 @@ "readable-stream": "^3.4.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, "readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -1115,63 +847,28 @@ "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" }, "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "requires": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", + "qs": "6.13.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "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" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } } } }, @@ -1212,11 +909,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "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==" - }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -1250,17 +942,37 @@ } }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "centra": { @@ -1333,11 +1045,11 @@ } }, "config": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/config/-/config-2.0.1.tgz", - "integrity": "sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.12.tgz", + "integrity": "sha512-Vmx389R/QVM3foxqBzXO8t2tUikYZP64Q6vQxGrsMpREeJc/aWRnPRERXWsYzOHAumx/AOoILWe6nU3ZJL+6Sw==", "requires": { - "json5": "^1.0.1" + "json5": "^2.2.3" } }, "content-disposition": { @@ -1361,9 +1073,9 @@ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, "cookie-signature": { "version": "1.0.6", @@ -1408,33 +1120,47 @@ } }, "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" - }, - "define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "requires": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" }, "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" } } }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1463,7 +1189,7 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" }, "destroy": { "version": "1.2.0", @@ -1503,9 +1229,9 @@ } }, "dmdb": { - "version": "1.0.14280", - "resolved": "https://registry.npmjs.org/dmdb/-/dmdb-1.0.14280.tgz", - "integrity": "sha512-vG6sA4s4Q3kLfO4RDTuA7b+//wNC/5ZEZk3MRHUtCqCcyMWoRaSZ8FWX60FFudaCoIi05kYGf8MlsMsy4HB6JA==", + "version": "1.0.33801", + "resolved": "https://registry.npmjs.org/dmdb/-/dmdb-1.0.33801.tgz", + "integrity": "sha512-lBG+a11PtC0pF3R0x3N+XREsi7rTTT6qQsCmsb9XLNTMwiGa8RAZy0uOxztb3nqC15xcK9IXGiapSWxY2yopHA==", "requires": { "iconv-lite": "^0.5.1", "snappy": "^7.2.0" @@ -1526,15 +1252,20 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "requires": { "safe-buffer": "^5.0.1" } @@ -1553,9 +1284,9 @@ } }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" }, "engine.io": { "version": "6.6.3", @@ -1585,11 +1316,6 @@ "requires": { "ms": "^2.1.3" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -1642,19 +1368,6 @@ "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.11" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - } } }, "es-aggregate-error": { @@ -1670,21 +1383,49 @@ "globalthis": "^1.0.3", "has-property-descriptors": "^1.0.0", "set-function-name": "^2.0.1" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" }, "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" } } }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, "es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", @@ -1720,6 +1461,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1731,36 +1477,36 @@ "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" }, "express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -1768,126 +1514,23 @@ "vary": "~1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, - "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" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, "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==" }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } } } }, - "fakeredis": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fakeredis/-/fakeredis-2.0.0.tgz", - "integrity": "sha1-dS+4MoGazjG+iGaM8TWNbxQ4r8A=", - "requires": { - "redis": "2.6.0-0" - }, - "dependencies": { - "redis": { - "version": "2.6.0-0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.6.0-0.tgz", - "integrity": "sha1-c/Z03T5Uo6dnA9HtJga05gC+B20=", - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.1.0", - "redis-parser": "^1.2.0" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, "file-type": { "version": "16.5.4", "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", @@ -1917,12 +1560,12 @@ } }, "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -1930,14 +1573,6 @@ "unpipe": "~1.0.0" }, "dependencies": { - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1946,16 +1581,16 @@ } }, "follow-redirects": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.8.tgz", - "integrity": "sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==" + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "requires": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" } }, "form-data": { @@ -1979,9 +1614,9 @@ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "function.prototype.name": { "version": "1.1.6", @@ -2013,13 +1648,29 @@ "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, "get-symbol-description": { @@ -2058,12 +1709,9 @@ } }, "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" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, "has": { "version": "1.0.3", @@ -2084,11 +1732,11 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { @@ -2097,16 +1745,24 @@ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" } }, "http-errors": { @@ -2126,25 +1782,10 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, @@ -2226,24 +1867,24 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" } }, "ioredis": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.1.tgz", - "integrity": "sha512-C+IBcMysM6v52pTLItYMeV4Hz7uriGtoJdz7SSBDX6u+zwSYGirLdQh3L7t/OItWITcw3gTFMjJReYUwS4zihg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.0.tgz", + "integrity": "sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==", "requires": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -2264,11 +1905,6 @@ "ms": "2.1.2" } }, - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2289,6 +1925,15 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "requires": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + } + }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -2339,6 +1984,11 @@ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" }, + "is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -2366,6 +2016,11 @@ "has-tostringtag": "^1.0.0" } }, + "is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" + }, "is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -2398,6 +2053,11 @@ "which-typed-array": "^1.1.11" } }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -2406,6 +2066,15 @@ "call-bind": "^1.0.2" } }, + "is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "requires": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + } + }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2461,9 +2130,9 @@ "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==" }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2474,28 +2143,26 @@ "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==" }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "requires": { - "minimist": "^1.2.0" - } + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "requires": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "dependencies": { "semver": { @@ -2509,12 +2176,12 @@ } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, @@ -2527,14 +2194,6 @@ "safe-buffer": "^5.0.1" }, "dependencies": { - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -2569,21 +2228,51 @@ } } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -2597,15 +2286,25 @@ "yallist": "^4.0.0" } }, + "lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==" + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" }, "methods": { "version": "1.1.2", @@ -2618,22 +2317,22 @@ "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==" }, "mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==" }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "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.37.0" + "mime-db": "1.52.0" }, "dependencies": { "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" } } }, @@ -2691,9 +2390,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "mssql": { "version": "9.1.1", @@ -2724,9 +2423,9 @@ } }, "multer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", - "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "requires": { "append-field": "^1.0.0", "busboy": "^0.2.11", @@ -2739,45 +2438,50 @@ } }, "multi-integer-range": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/multi-integer-range/-/multi-integer-range-4.0.7.tgz", - "integrity": "sha512-THuAnyKxIogrhWvHXHMEWxR90TCFcz/RHsnTcGKAOxdOMaNZSKkujOHMC2LZGMc/j+Jdf31FJcL66au/U0mS1Q==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/multi-integer-range/-/multi-integer-range-5.2.0.tgz", + "integrity": "sha512-FFJwl7mUYFizzE6rY86KaiN/aFxHtqWHHdEA4wvYOSCIlmSu6ysNmvU52GOfYQZn8cadi2MgyAppP/8nWHwIlA==" }, "multiparty": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.1.tgz", - "integrity": "sha512-AvESCnNoQlZiOfP9R4mxN8M9csy2L16EIbWIkt3l4FuGti9kXBS8QVzlfyg4HEnarJhrzZilgNFlZtqmoiAIIA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", "requires": { - "fd-slicer": "1.1.0", - "http-errors": "~1.7.0", - "safe-buffer": "5.1.2", + "http-errors": "~1.8.1", + "safe-buffer": "5.2.1", "uid-safe": "2.1.5" }, "dependencies": { "http-errors": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.1.tgz", - "integrity": "sha512-jWEUgtZWGSMba9I1N3gc1HmvpBUaNC9vDdA46yScAdp+C5rdEuKWUBLWTQpW9FwSWSbYYs++b6SDCxf9UEJzfw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.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==" } } }, "mysql2": { - "version": "3.9.8", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.8.tgz", - "integrity": "sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.13.0.tgz", + "integrity": "sha512-M6DIQjTqKeqXH5HLbLMxwcK5XfXHw30u5ap6EZmu7QVmcF/gnh2wS/EOiQ4MTbXz/vQeoXrmycPlVRM00WSslg==", "requires": { + "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^8.0.0", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -2790,11 +2494,6 @@ "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } - }, - "lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==" } } }, @@ -2842,9 +2541,18 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + }, + "object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + } }, "object-keys": { "version": "1.1.1", @@ -2868,9 +2576,9 @@ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -2886,14 +2594,9 @@ } }, "oracledb": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.3.0.tgz", - "integrity": "sha512-fr3U66QxgGXb5cs/ozLBQU50TMbZcBQEWvSaj2rJAXG8KRrsZcGOK8JTlZL1yJHeW8cSjOm6n/wTw3SJksGjDg==" - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.8.0.tgz", + "integrity": "sha512-A4ds4n4xtjPTzk1gwrHWuMeWsEcrScF0GFgVebGrhNpHSAzn6eDwMKcSbakZODKfFcI099iqhmqWsgko8D+7Ww==" }, "pako": { "version": "1.0.11", @@ -2930,31 +2633,24 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "peek-readable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, "pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.14.0.tgz", + "integrity": "sha512-nXbVpyoaXVmdqlKEzToFf37qzyeeh7mbiXsnoWvstSqohj88yaa/I/Rq/HEVn2QPSZEuLIJa/jSpRDyzjEx4FQ==", "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", + "pg-connection-string": "^2.7.0", + "pg-pool": "^3.8.0", + "pg-protocol": "^1.8.0", "pg-types": "^2.1.0", "pgpass": "1.x" } @@ -2966,9 +2662,9 @@ "optional": true }, "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" }, "pg-int8": { "version": "1.0.1", @@ -2976,14 +2672,14 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==" + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz", + "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==" }, "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz", + "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==" }, "pg-types": { "version": "2.2.0", @@ -3019,12 +2715,24 @@ "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", "requires": { "pngjs": "^3.0.0" + }, + "dependencies": { + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + } } }, "pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==" + }, + "possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==" }, "postgres-array": { "version": "2.0.0", @@ -3074,11 +2782,11 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "requires": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" } }, "random-bytes": { @@ -3092,21 +2800,14 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "requires": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - } } }, "readable-stream": { @@ -3124,53 +2825,58 @@ } }, "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", + "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", "requires": { - "readable-stream": "^3.6.0" + "readable-stream": "^4.7.0" }, "dependencies": { "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + }, + "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==" + }, + "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" } } } }, "redis": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.11.tgz", - "integrity": "sha512-kg1Lt4NZLYkAjPOj/WcyIGWfZfnyfKo1Wg9YKVSlzhFwxpFIl3LYI8BWy1Ab963LLDsTz2+OwdsesHKljB3WMQ==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", + "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", "requires": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.12", + "@redis/client": "1.6.0", "@redis/graph": "1.1.1", - "@redis/json": "1.0.6", - "@redis/search": "1.1.6", - "@redis/time-series": "1.0.5" + "@redis/json": "1.0.7", + "@redis/search": "1.2.0", + "@redis/time-series": "1.1.0" } }, - "redis-commands": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", - "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==" - }, "redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" }, - "redis-parser": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-1.3.0.tgz", - "integrity": "sha1-gG6+e7+3005NfB6e8oLvz60EEmo=" - }, "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -3186,15 +2892,10 @@ "set-function-name": "^2.0.0" } }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" }, "rfdc": { "version": "1.3.0", @@ -3212,17 +2913,6 @@ "isarray": "^2.0.5" }, "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - }, "isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -3261,9 +2951,9 @@ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "requires": { "debug": "2.6.9", "depd": "2.0.0", @@ -3285,24 +2975,16 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -3316,14 +2998,27 @@ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "requires": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" + } + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" } }, "set-function-name": { @@ -3337,18 +3032,52 @@ } }, "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "snappy": { @@ -3392,11 +3121,6 @@ "requires": { "ms": "^2.1.3" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -3416,11 +3140,6 @@ "requires": { "ms": "^2.1.3" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -3440,11 +3159,6 @@ "requires": { "ms": "^2.1.3" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -3471,7 +3185,16 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "requires": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + } }, "stoppable": { "version": "1.1.0", @@ -3588,9 +3311,9 @@ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "token-types": { "version": "4.2.1", @@ -3612,12 +3335,12 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "~2.1.24" } }, "typed-array-buffer": { @@ -3628,19 +3351,6 @@ "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1", "is-typed-array": "^1.1.10" - }, - "dependencies": { - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - } } }, "typed-array-byte-length": { @@ -3701,23 +3411,15 @@ } }, "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "utf7": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz", @@ -3760,9 +3462,9 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "whatwg-fetch": { - "version": "3.6.19", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", - "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==" + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" }, "whatwg-url": { "version": "5.0.0", @@ -3785,22 +3487,35 @@ "is-symbol": "^1.0.3" } }, - "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "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-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + } + }, + "which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" } }, "windows-locale": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/windows-locale/-/windows-locale-1.0.1.tgz", - "integrity": "sha512-X8B22Cg9njwV4h3C5j28xmZ2eWaO69j63WhReeglB69LOT3LoqSO4Vb6TTVSfFikh4KQ9qBOJb6+WvR4tVLTfQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/windows-locale/-/windows-locale-1.1.3.tgz", + "integrity": "sha512-0OlMOPNGj7GTB6C7WmqS3o4eydjnoYj0uwot2KJf7E0JUucwYwzkcvCWQwnuOV60WqDMeGJpSankgveNMj5r0g==" }, "ws": { "version": "8.17.1", @@ -3838,15 +3553,14 @@ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmlbuilder2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.0.2.tgz", - "integrity": "sha512-h4MUawGY21CTdhV4xm3DG9dgsqyhDkZvVJBx88beqX8wJs3VgyGQgAn5VreHuae6unTQxh115aMK5InCVmOIKw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz", + "integrity": "sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==", "requires": { "@oozcitak/dom": "1.15.10", "@oozcitak/infra": "1.0.8", "@oozcitak/util": "8.3.8", - "@types/node": "*", - "js-yaml": "3.14.0" + "js-yaml": "3.14.1" } }, "xtend": { diff --git a/DocService/package.json b/DocService/package.json index 412126ef..8af8a244 100644 --- a/DocService/package.json +++ b/DocService/package.json @@ -9,42 +9,38 @@ "prepare4shutdown": "sources/shutdown.js" }, "dependencies": { - "ajv": "8.9.0", "apicache": "1.6.3", - "base64-stream": "1.0.0", - "body-parser": "1.20.1", + "body-parser": "1.20.3", "bottleneck": "2.19.5", - "bytes": "3.0.0", + "bytes": "3.1.2", "co": "4.6.0", - "config": "2.0.1", + "config": "3.3.12", "cron": "1.5.0", - "deep-equal": "1.0.1", - "dmdb": "1.0.14280", + "deep-equal": "2.2.3", + "dmdb": "1.0.33801", "ejs": "3.1.10", "exif-parser": "0.1.12", - "express": "4.19.2", - "fakeredis": "2.0.0", - "ioredis": "5.3.1", + "express": "4.21.2", + "ioredis": "5.6.0", "jimp": "0.22.10", - "jsonwebtoken": "9.0.0", - "jwa": "1.1.6", + "jsonwebtoken": "9.0.2", "mime": "2.3.1", - "mime-db": "1.49.0", - "ms": "2.1.1", + "mime-db": "1.53.0", + "ms": "2.1.3", "mssql": "9.1.1", - "multer": "1.4.3", - "multi-integer-range": "4.0.7", - "multiparty": "4.2.1", - "mysql2": "3.9.8", - "oracledb": "6.3.0", - "pg": "8.11.3", - "redis": "4.6.11", - "retry": "0.12.0", + "multer": "1.4.4", + "multi-integer-range": "5.2.0", + "multiparty": "4.2.3", + "mysql2": "3.13.0", + "oracledb": "6.8.0", + "pg": "8.14.0", + "redis": "4.7.0", + "retry": "0.13.1", "socket.io": "4.8.1", - "underscore": "1.13.1", + "underscore": "1.13.7", "utf7": "1.0.2", - "windows-locale": "1.0.1", - "xmlbuilder2": "3.0.2" + "windows-locale": "1.1.3", + "xmlbuilder2": "3.1.1" }, "pkg": { "scripts": [ diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index febe2ce6..379dd524 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -130,7 +130,7 @@ const cfgTokenSessionAlgorithm = config.get('services.CoAuthoring.token.session. const cfgTokenSessionExpires = config.get('services.CoAuthoring.token.session.expires'); const cfgTokenInboxHeader = config.get('services.CoAuthoring.token.inbox.header'); const cfgTokenInboxPrefix = config.get('services.CoAuthoring.token.inbox.prefix'); -const cfgTokenVerifyOptions = config.get('services.CoAuthoring.token.verifyOptions'); +const cfgTokenVerifyOptions = config.util.cloneDeep(config.get('services.CoAuthoring.token.verifyOptions')); const cfgForceSaveEnable = config.get('services.CoAuthoring.autoAssembly.enable'); const cfgForceSaveInterval = config.get('services.CoAuthoring.autoAssembly.interval'); const cfgQueueRetentionPeriod = config.get('queue.retentionPeriod'); @@ -150,7 +150,7 @@ const cfgForceSaveUsingButtonWithoutChanges = config.get('services.CoAuthoring.s //todo tenant const cfgExpDocumentsCron = config.get('services.CoAuthoring.expire.documentsCron'); const cfgRefreshLockInterval = ms(config.get('wopi.refreshLockInterval')); -const cfgSocketIoConnection = config.get('services.CoAuthoring.socketio.connection'); +const cfgSocketIoConnection = config.util.cloneDeep(config.get('services.CoAuthoring.socketio.connection')); const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult'); const cfgTableChanges = config.get('services.CoAuthoring.sql.tableChanges'); diff --git a/DocService/sources/databaseConnectors/baseConnector.js b/DocService/sources/databaseConnectors/baseConnector.js index 1668a230..28cbecc7 100644 --- a/DocService/sources/databaseConnectors/baseConnector.js +++ b/DocService/sources/databaseConnectors/baseConnector.js @@ -50,7 +50,7 @@ const configSql = config.get('services.CoAuthoring.sql'); const cfgTableResult = configSql.get('tableResult'); const cfgTableChanges = configSql.get('tableChanges'); const maxPacketSize = configSql.get('max_allowed_packet'); // The default size for a query to the database is 1Mb - 1 (because it does not write 1048575, but writes 1048574) -const cfgBottleneckGetChanges = config.get('bottleneck.getChanges'); +const cfgBottleneckGetChanges = config.util.cloneDeep(config.get('bottleneck.getChanges')); const dbType = configSql.get('type'); const reservoirMaximum = cfgBottleneckGetChanges.reservoirIncreaseMaximum || cfgBottleneckGetChanges.reservoirRefreshAmount; diff --git a/DocService/sources/databaseConnectors/damengConnector.js b/DocService/sources/databaseConnectors/damengConnector.js index 84fa4733..bedd1be4 100644 --- a/DocService/sources/databaseConnectors/damengConnector.js +++ b/DocService/sources/databaseConnectors/damengConnector.js @@ -43,7 +43,7 @@ const cfgDbUser = configSql.get('dbUser'); const cfgDbPass = configSql.get('dbPass'); const cfgConnectionLimit = configSql.get('connectionlimit'); const cfgTableResult = configSql.get('tableResult'); -const cfgDamengExtraOptions = configSql.get('damengExtraOptions'); +const cfgDamengExtraOptions = config.util.cloneDeep(configSql.get('damengExtraOptions')); const forceClosingCountdownMs = 2000; // dmdb driver separates PoolAttributes and ConnectionAttributes. diff --git a/DocService/sources/databaseConnectors/mssqlConnector.js b/DocService/sources/databaseConnectors/mssqlConnector.js index 8f745743..4ec872b4 100644 --- a/DocService/sources/databaseConnectors/mssqlConnector.js +++ b/DocService/sources/databaseConnectors/mssqlConnector.js @@ -53,7 +53,7 @@ const connectionConfiguration = { min: 0 } }; -const additionalOptions = configSql.get('msSqlExtraOptions'); +const additionalOptions = config.util.cloneDeep(configSql.get('msSqlExtraOptions')); const configuration = utils.deepMergeObjects({}, connectionConfiguration, additionalOptions); const placeholderPrefix = 'ph_'; diff --git a/DocService/sources/databaseConnectors/mysqlConnector.js b/DocService/sources/databaseConnectors/mysqlConnector.js index 1c2103b5..d22a0b27 100644 --- a/DocService/sources/databaseConnectors/mysqlConnector.js +++ b/DocService/sources/databaseConnectors/mysqlConnector.js @@ -51,7 +51,7 @@ const connectionConfiguration = { flags : '-FOUND_ROWS' }; -const additionalOptions = configSql.get('mysqlExtraOptions'); +const additionalOptions = config.util.cloneDeep(configSql.get('mysqlExtraOptions')); const configuration = Object.assign({}, connectionConfiguration, additionalOptions); let queryTimeout = undefined; if (configuration.queryTimeout) { diff --git a/DocService/sources/databaseConnectors/oracleConnector.js b/DocService/sources/databaseConnectors/oracleConnector.js index 153f1fc3..09813971 100644 --- a/DocService/sources/databaseConnectors/oracleConnector.js +++ b/DocService/sources/databaseConnectors/oracleConnector.js @@ -49,7 +49,7 @@ const connectionConfiguration = { poolMin: 0, poolMax: configSql.get('connectionlimit') }; -const additionalOptions = configSql.get('oracleExtraOptions'); +const additionalOptions = config.util.cloneDeep(configSql.get('oracleExtraOptions')); const configuration = Object.assign({}, connectionConfiguration, additionalOptions); const forceClosingCountdownMs = 2000; let pool = null; diff --git a/DocService/sources/databaseConnectors/postgreConnector.js b/DocService/sources/databaseConnectors/postgreConnector.js index 329bfa74..17fb18d6 100644 --- a/DocService/sources/databaseConnectors/postgreConnector.js +++ b/DocService/sources/databaseConnectors/postgreConnector.js @@ -40,7 +40,7 @@ const operationContext = require('../../../Common/sources/operationContext'); const config = require('config'); var configSql = config.get('services.CoAuthoring.sql'); const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult'); -var pgPoolExtraOptions = configSql.get('pgPoolExtraOptions'); +var pgPoolExtraOptions = config.util.cloneDeep(configSql.get('pgPoolExtraOptions')); const cfgEditor = config.get('services.CoAuthoring.editor'); let connectionConfig = { diff --git a/DocService/sources/pubsubRabbitMQ.js b/DocService/sources/pubsubRabbitMQ.js index dcb33c03..c23718bb 100644 --- a/DocService/sources/pubsubRabbitMQ.js +++ b/DocService/sources/pubsubRabbitMQ.js @@ -42,8 +42,8 @@ var rabbitMQCore = require('./../../Common/sources/rabbitMQCore'); var activeMQCore = require('./../../Common/sources/activeMQCore'); const cfgQueueType = config.get('queue.type'); -const cfgRabbitExchangePubSub = config.get('rabbitmq.exchangepubsub'); -const cfgRabbitQueuePubsub = config.get('rabbitmq.queuepubsub'); +const cfgRabbitExchangePubSub = config.util.cloneDeep(config.get('rabbitmq.exchangepubsub')); +const cfgRabbitQueuePubsub = config.util.cloneDeep(config.get('rabbitmq.queuepubsub')); var cfgActiveTopicPubSub = constants.ACTIVEMQ_TOPIC_PREFIX + config.get('activemq.topicpubsub'); function initRabbit(pubsub, callback) { diff --git a/FileConverter/npm-shrinkwrap.json b/FileConverter/npm-shrinkwrap.json index 57a5f4e6..4070f9d5 100644 --- a/FileConverter/npm-shrinkwrap.json +++ b/FileConverter/npm-shrinkwrap.json @@ -13,9 +13,9 @@ } }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "co": { "version": "4.6.0", @@ -23,11 +23,11 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "config": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/config/-/config-2.0.1.tgz", - "integrity": "sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.12.tgz", + "integrity": "sha512-Vmx389R/QVM3foxqBzXO8t2tUikYZP64Q6vQxGrsMpREeJc/aWRnPRERXWsYzOHAumx/AOoILWe6nU3ZJL+6Sw==", "requires": { - "json5": "^1.0.1" + "json5": "^2.2.3" } }, "cross-spawn": { @@ -51,12 +51,9 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "requires": { - "minimist": "^1.2.0" - } + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "lcid": { "version": "3.1.1", @@ -66,10 +63,10 @@ "invert-kv": "^3.0.0" } }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "path-key": { "version": "3.1.1", diff --git a/FileConverter/package.json b/FileConverter/package.json index 8c53ccee..141a1b62 100644 --- a/FileConverter/package.json +++ b/FileConverter/package.json @@ -6,10 +6,11 @@ "bin": "sources/convertermaster.js", "dependencies": { "@expo/spawn-async": "1.7.2", - "bytes": "3.0.0", + "bytes": "3.1.2", "co": "4.6.0", - "config": "2.0.1", - "lcid": "3.1.1" + "config": "3.3.12", + "lcid": "3.1.1", + "ms": "2.1.3" }, "pkg": { "scripts": [ diff --git a/FileConverter/sources/converter.js b/FileConverter/sources/converter.js index 8c8a0133..61f32fe6 100644 --- a/FileConverter/sources/converter.js +++ b/FileConverter/sources/converter.js @@ -64,7 +64,7 @@ const cfgPresentationThemesDir = config.get('FileConverter.converter.presentatio const cfgX2tPath = config.get('FileConverter.converter.x2tPath'); const cfgDocbuilderPath = config.get('FileConverter.converter.docbuilderPath'); const cfgArgs = config.get('FileConverter.converter.args'); -const cfgSpawnOptions = config.get('FileConverter.converter.spawnOptions'); +const cfgSpawnOptions = config.util.cloneDeep(config.get('FileConverter.converter.spawnOptions')); const cfgErrorFiles = config.get('FileConverter.converter.errorfiles'); const cfgInputLimits = config.get('FileConverter.converter.inputLimits'); const cfgStreamWriterBufferSize = config.get('FileConverter.converter.streamWriterBufferSize'); @@ -74,7 +74,7 @@ const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles const cfgForgottenFilesName = config.get('services.CoAuthoring.server.forgottenfilesname'); const cfgNewFileTemplate = config.get('services.CoAuthoring.server.newFileTemplate'); const cfgEditor = config.get('services.CoAuthoring.editor'); -const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent'); +const cfgRequesFilteringAgent = config.util.cloneDeep(config.get('services.CoAuthoring.request-filtering-agent')); const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn'); const cfgExternalRequestAction = config.get('externalRequest.action'); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d4915a7e..64452840 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -5,66 +5,68 @@ "requires": true, "dependencies": { "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "requires": { - "@babel/highlight": "^7.18.6" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { - "version": "7.21.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.7.tgz", - "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true }, "@babel/core": { - "version": "7.21.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", - "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", + "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.9", + "@babel/types": "^7.26.9", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "semver": { @@ -76,28 +78,29 @@ } }, "@babel/generator": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz", - "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "dev": true, "requires": { - "@babel/types": "^7.21.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" } }, "@babel/helper-compilation-targets": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", - "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "requires": { - "@babel/compat-data": "^7.21.5", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "dependencies": { "semver": { @@ -108,158 +111,69 @@ } } }, - "@babel/helper-environment-visitor": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", - "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", - "dev": true - }, "@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "requires": { - "@babel/types": "^7.21.4" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" } }, "@babel/helper-module-transforms": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", - "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" } }, "@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true }, - "@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", - "dev": true, - "requires": { - "@babel/types": "^7.21.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, "@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true }, "@babel/helpers": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", - "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", + "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", "dev": true, "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9" } }, "@babel/parser": { - "version": "7.21.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", - "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", - "dev": true + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "dev": true, + "requires": { + "@babel/types": "^7.26.9" + } }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -288,6 +202,24 @@ "@babel/helper-plugin-utils": "^7.12.13" } }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -307,12 +239,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.25.9" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -369,6 +301,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -379,220 +320,65 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.25.9" } }, "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" } }, "@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", "dev": true, "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - } - }, - "@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", - "dev": true, - "requires": { - "@babel/types": "^7.25.6", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true - }, - "@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - } - }, - "@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.25.6" - } - }, - "@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - } - }, - "@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "@babel/types": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", - "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" } }, "@bcoe/v8-coverage": { @@ -621,16 +407,16 @@ "dev": true }, "@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "dependencies": { @@ -665,37 +451,37 @@ } }, "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -789,74 +575,74 @@ } }, "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.7.0" } }, "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" } }, "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "requires": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" } }, "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" } }, "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -864,13 +650,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -923,66 +709,66 @@ } }, "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "requires": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1017,12 +803,6 @@ "supports-color": "^7.1.0" } }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1069,12 +849,12 @@ } }, "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1113,50 +893,42 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@kessler/tableify": { @@ -1165,9 +937,9 @@ "integrity": "sha512-e4psVV9Fe2eBfS9xK2rzQ9lE5xS4tARm7EJzDb6sVZy3F+EMyHJ67i0NdBVR9BRyQx7YhogMCbB6R1QwXuBxMg==" }, "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "@sindresorhus/is": { @@ -1176,21 +948,21 @@ "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==" }, "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "requires": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" } }, "@szmarczak/http-timer": { @@ -1202,9 +974,9 @@ } }, "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "requires": { "@babel/parser": "^7.20.7", @@ -1215,18 +987,18 @@ } }, "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -1234,18 +1006,18 @@ } }, "@types/babel__traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.5.tgz", - "integrity": "sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "requires": { "@types/node": "*" @@ -1257,67 +1029,59 @@ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" }, "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "requires": { "@types/istanbul-lib-report": "*" } }, "@types/node": { - "version": "18.16.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz", - "integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "dev": true, + "requires": { + "undici-types": "~6.20.0" + } }, "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1327,16 +1091,6 @@ "type-fest": "^0.21.3" } }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1351,6 +1105,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" }, @@ -1358,25 +1113,11 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true } } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, "array-buffer-byte-length": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", @@ -1386,21 +1127,6 @@ "is-array-buffer": "^3.0.1" } }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==" - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, "arraybuffer.prototype.slice": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", @@ -1415,36 +1141,21 @@ "is-shared-array-buffer": "^1.0.2" } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, "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==" }, "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "requires": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1491,12 +1202,33 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -1506,32 +1238,35 @@ } }, "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" } }, "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -1540,76 +1275,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "bower-config": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-1.4.3.tgz", - "integrity": "sha512-MVyyUk3d1S7d2cl6YISViwJBc2VXCkxF5AUFykvN0PQj5FsUiMNSgAYTso18oRFfyZ6XEtjrgg9MAaufHbOwNw==", - "requires": { - "graceful-fs": "^4.1.3", - "minimist": "^0.2.1", - "mout": "^1.0.0", - "osenv": "^0.1.3", - "untildify": "^2.1.0", - "wordwrap": "^0.0.3" - }, - "dependencies": { - "minimist": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.4.tgz", - "integrity": "sha512-Pkrrm8NjyQ8yVt8Am9M+yUt74zE3iokhzbG1bFVNjLB92vwM71hf40RkEsryg98BujhVOncKm/C1xROxZ030LQ==" - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1619,43 +1284,16 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" } }, "bser": { @@ -1673,22 +1311,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, "cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -1738,132 +1360,29 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001482", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz", - "integrity": "sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ==", + "version": "1.0.30001703", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz", + "integrity": "sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==", "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, "char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true }, - "check-dependencies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/check-dependencies/-/check-dependencies-1.1.0.tgz", - "integrity": "sha512-GDrbGzzJ6Gc6tQh87HBMGhrJ4UWIlR9MKJwgvlrJyj/gWvTYYb2jQetKbajt/EYK5Y8/4g7gH2LEvq8GdUWTag==", - "requires": { - "bower-config": "^1.4.0", - "chalk": "^2.1.0", - "findup-sync": "^2.0.0", - "lodash.camelcase": "^4.3.0", - "minimist": "^1.2.0", - "semver": "^5.4.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true }, "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1899,24 +1418,16 @@ "dev": true }, "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -1924,17 +1435,8 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -1942,15 +1444,55 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "cross-env": { "version": "7.0.3", @@ -1983,24 +1525,6 @@ } } }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, "decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -2017,9 +1541,9 @@ } }, "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true }, "deep-extend": { @@ -2058,48 +1582,6 @@ "object-keys": "^1.1.1" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2107,15 +1589,15 @@ "dev": true }, "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, "electron-to-chromium": { - "version": "1.4.384", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.384.tgz", - "integrity": "sha512-I97q0MmRAAqj53+a8vZsDkEXBZki+ehYAOPzwtQzALip52aEp2+BJqHFtTlsfjoqVZYwPpHC8wM6MbsSZQ/Eqw==", + "version": "1.5.114", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.114.tgz", + "integrity": "sha512-DFptFef3iktoKlFQK/afbo274/XNWD00Am0xa7M8FZUepHlHT8PEuiNBoRfFHbH1okqN58AlhbJ4QTkcnXorjA==", "dev": true }, "emittery": { @@ -2210,25 +1692,21 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "execa": { "version": "5.1.1", @@ -2250,142 +1728,20 @@ "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true }, "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "requires": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" } }, "fast-json-stable-stringify": { @@ -2403,32 +1759,6 @@ "bser": "2.1.1" } }, - "file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=" - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -2439,45 +1769,6 @@ "path-exists": "^4.0.0" } }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha512-z8Nrwhi6wzxNMIbxlrTzuUW6KWuKkogZ/7OdDVq+0+kxn77KUH1nipx8iU6suqkHqc4y6n7a9A8IpmxY/pTjWg==", - "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" - }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2486,41 +1777,21 @@ "is-callable": "^1.1.3" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", - "requires": { - "for-in": "^1.0.1" - } - }, "form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==" }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, @@ -2600,20 +1871,11 @@ "get-intrinsic": "^1.1.1" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getobject": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", - "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==" - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2623,28 +1885,6 @@ "path-is-absolute": "^1.0.0" } }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2690,203 +1930,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" }, - "grunt": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.3.tgz", - "integrity": "sha512-mKwmo4X2d8/4c/BmcOETHek675uOqw0RuA/zy12jaspWqvTp4+ZeQF1W+OTpcbncnaBsfbQJ6l0l4j+Sn/GmaQ==", - "requires": { - "dateformat": "~3.0.3", - "eventemitter2": "~0.4.13", - "exit": "~0.1.2", - "findup-sync": "~0.3.0", - "glob": "~7.1.6", - "grunt-cli": "~1.4.3", - "grunt-known-options": "~2.0.0", - "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.14.0", - "minimatch": "~3.0.4", - "mkdirp": "~1.0.4", - "nopt": "~3.0.6", - "rimraf": "~3.0.2" - }, - "dependencies": { - "grunt-cli": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", - "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", - "requires": { - "grunt-known-options": "~2.0.0", - "interpret": "~1.1.0", - "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" - }, - "dependencies": { - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - } - } - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "grunt-banner": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/grunt-banner/-/grunt-banner-0.6.0.tgz", - "integrity": "sha1-P4eQIdEj+linuloLb7a+QStYhaw=", - "requires": { - "chalk": "^1.1.0" - } - }, - "grunt-check-dependencies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-check-dependencies/-/grunt-check-dependencies-1.0.0.tgz", - "integrity": "sha1-UYiVh8V+gn3enN9pt1CuCy+IHFA=", - "requires": { - "check-dependencies": "^1.0.1", - "lodash.clonedeep": "^4.5.0" - } - }, - "grunt-contrib-clean": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.0.tgz", - "integrity": "sha512-g5ZD3ORk6gMa5ugZosLDQl3dZO7cI3R14U75hTM+dVLVxdMNJCPVmwf9OUt4v4eWgpKKWWoVK9DZc1amJp4nQw==", - "requires": { - "async": "^2.6.1", - "rimraf": "^2.6.2" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "requires": { - "lodash": "^4.17.14" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "grunt-contrib-copy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", - "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", - "requires": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" - } - }, - "grunt-known-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", - "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==" - }, - "grunt-legacy-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", - "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.19" - } - }, - "grunt-legacy-log-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", - "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", - "requires": { - "chalk": "~4.1.0", - "lodash": "~4.17.19" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "grunt-legacy-util": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", - "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", - "requires": { - "async": "~3.2.0", - "exit": "~0.1.2", - "getobject": "~1.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.21", - "underscore.string": "~3.3.5", - "which": "~2.0.2" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "grunt-mkdir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-mkdir/-/grunt-mkdir-1.1.0.tgz", - "integrity": "sha512-FRE17OYVveNbVJFX8GPGa5bzH2ZiAdBx3q0Kwk2Dg6l+TzLGaTdufUxiUWUbS2MERFacnmXZwDDOR5ZbYW0o+Q==" - }, - "grunt-stripcomments": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/grunt-stripcomments/-/grunt-stripcomments-0.7.2.tgz", - "integrity": "sha1-c4t3Z2Nnu/EmiJrpEJFRsB9a7w4=", - "requires": { - "chalk": "^1.1.3" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2895,14 +1938,6 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2911,7 +1946,8 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-property-descriptors": { "version": "1.0.1", @@ -2939,35 +1975,6 @@ "has-symbols": "^1.0.2" } }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -2983,19 +1990,6 @@ } } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==" - }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -3027,18 +2021,10 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "requires": { "pkg-dir": "^4.2.0", @@ -3055,6 +2041,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3063,7 +2050,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ini": { "version": "1.3.8", @@ -3080,38 +2068,6 @@ "side-channel": "^1.0.4" } }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==" - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -3144,11 +2100,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -3162,24 +2113,6 @@ "has": "^1.0.3" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -3188,33 +2121,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3227,37 +2133,11 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -3266,14 +2146,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -3283,14 +2155,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "requires": { - "is-unc-path": "^1.0.0" - } - }, "is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -3329,14 +2193,6 @@ "which-typed-array": "^1.1.11" } }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "requires": { - "unc-path-regex": "^0.1.2" - } - }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -3345,61 +2201,46 @@ "call-bind": "^1.0.2" } }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true }, "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "dependencies": { "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true } } }, "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "dependencies": { @@ -3426,18 +2267,18 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "source-map": { @@ -3449,9 +2290,9 @@ } }, "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -3459,111 +2300,51 @@ } }, "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "jest-cli": "^29.7.0" } }, "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "requires": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } } }, "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3588,13 +2369,53 @@ "supports-color": "^7.1.0" } }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "yocto-queue": "^0.1.0" + "has-flag": "^4.0.0" + } + } + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "supports-color": { @@ -3609,31 +2430,31 @@ } }, "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3712,15 +2533,15 @@ } }, "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "dependencies": { "ansi-styles": { @@ -3754,25 +2575,25 @@ } }, "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "dependencies": { "ansi-styles": { @@ -3806,41 +2627,41 @@ } }, "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" } }, "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true }, "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3891,25 +2712,25 @@ } }, "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "dependencies": { "ansi-styles": { @@ -3943,18 +2764,18 @@ } }, "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4033,14 +2854,14 @@ } }, "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.7.0" } }, "jest-pnp-resolver": { @@ -4050,23 +2871,23 @@ "dev": true }, "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true }, "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -4103,40 +2924,40 @@ } }, "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" } }, "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4160,15 +2981,6 @@ "supports-color": "^7.1.0" } }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4181,31 +2993,31 @@ } }, "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4241,34 +3053,31 @@ } }, "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "dependencies": { "ansi-styles": { @@ -4290,23 +3099,11 @@ "supports-color": "^7.1.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true }, "supports-color": { "version": "7.2.0", @@ -4316,22 +3113,16 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -4370,17 +3161,17 @@ } }, "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "dependencies": { "ansi-styles": { @@ -4420,18 +3211,18 @@ } }, "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "dependencies": { @@ -4466,13 +3257,13 @@ } }, "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4498,15 +3289,16 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true }, "json-buffer": { @@ -4548,11 +3340,6 @@ "json-buffer": "3.0.1" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4577,11 +3364,11 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "got": { @@ -4603,9 +3390,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -4626,112 +3413,22 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { - "ms": "2.1.2" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "liftup": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", - "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", - "requires": { - "extend": "^3.0.2", - "findup-sync": "^4.0.0", - "fined": "^1.2.0", - "flagged-respawn": "^1.0.1", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.1", - "rechoir": "^0.7.0", - "resolve": "^1.19.0" - }, - "dependencies": { - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "requires": { - "fill-range": "^7.1.1" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "findup-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", - "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^4.0.2", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==" } } }, @@ -4777,21 +3474,6 @@ "p-locate": "^4.1.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, "lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -4815,30 +3497,22 @@ } }, "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "requires": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "dependencies": { "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true } } }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "requires": { - "kind-of": "^6.0.2" - } - }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -4848,19 +3522,6 @@ "tmpl": "1.0.5" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -4872,26 +3533,6 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -4916,58 +3557,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mout": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/mout/-/mout-1.2.4.tgz", - "integrity": "sha512-mZb9uOruMWgn/fw28DG4/yE3Kehfk1zKCLhuDU2O3vlKdnBBr4XaOCqVTflJ5aODavGUPqFHZgrFX3NJVuxGhQ==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4995,19 +3584,11 @@ "dev": true }, "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5026,9 +3607,9 @@ "dev": true }, "normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==" }, "npm-run-all": { "version": "4.1.5", @@ -5078,9 +3659,9 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -5131,34 +3712,6 @@ "path-key": "^3.0.0" } }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -5169,14 +3722,6 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, "object.assign": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", @@ -5188,38 +3733,11 @@ "object-keys": "^1.1.1" } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -5233,37 +3751,18 @@ "mimic-fn": "^2.1.0" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { @@ -5273,6 +3772,17 @@ "dev": true, "requires": { "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } } }, "p-try": { @@ -5281,16 +3791,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -5303,16 +3803,6 @@ "lines-and-columns": "^1.1.6" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5322,7 +3812,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", @@ -5335,19 +3826,6 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" - }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -5357,15 +3835,16 @@ } }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "pidtree": { "version": "0.3.1", @@ -5378,9 +3857,9 @@ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" }, "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true }, "pkg-dir": { @@ -5392,18 +3871,13 @@ "find-up": "^4.0.0" } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -5427,9 +3901,9 @@ } }, "pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true }, "quick-lru": { @@ -5456,9 +3930,9 @@ } }, "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, "read-pkg": { @@ -5471,23 +3945,6 @@ "path-type": "^3.0.0" } }, - "rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", - "requires": { - "resolve": "^1.9.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, "regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -5498,16 +3955,6 @@ "set-function-name": "^2.0.0" } }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5538,30 +3985,16 @@ "resolve-from": "^5.0.0" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true }, "responselike": { @@ -5572,19 +4005,6 @@ "lowercase-keys": "^3.0.0" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, "safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -5603,14 +4023,6 @@ } } }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, "safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -5621,11 +4033,6 @@ "is-regex": "^1.1.4" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", @@ -5662,27 +4069,6 @@ "has-property-descriptors": "^1.0.0" } }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5731,120 +4117,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -5863,11 +4135,6 @@ } } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" - }, "spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -5896,14 +4163,6 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==" }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } - }, "split-text-to-chunks": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split-text-to-chunks/-/split-text-to-chunks-1.0.0.tgz", @@ -5913,11 +4172,6 @@ "minimist": "^1.2.0" } }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -5935,25 +4189,6 @@ } } }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -6049,14 +4284,6 @@ "es-abstract": "^1.22.1" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -6075,20 +4302,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "tablemark": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tablemark/-/tablemark-3.0.0.tgz", - "integrity": "sha512-7N05gRK7t6B4g8AtedUsKoKtPjplmUjOPr/V4kVB+7U3yGiB3WvKqMTTQzVCZyhfZUXgQFp9YyN9ZgC52uCPKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tablemark/-/tablemark-3.1.0.tgz", + "integrity": "sha512-IwO6f0SEzp1Z+zqz/7ANUmeEac4gaNlknWyj/S9aSg11wZmWYnLeyI/xXvEOU88BYUIf8y30y0wxB58xIKrVlQ==", "requires": { "sentence-case": "^3.0.4", "split-text-to-chunks": "^1.0.0" @@ -6116,54 +4338,10 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "type-detect": { "version": "4.0.8", @@ -6231,88 +4409,25 @@ "which-boxed-primitive": "^1.0.2" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==" - }, - "underscore.string": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", - "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", - "requires": { - "sprintf-js": "^1.1.1", - "util-deprecate": "^1.0.2" - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } + "undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true }, "universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } - } - }, - "untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", - "requires": { - "os-homedir": "^1.0.0" - } - }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" } }, "upper-case-first": { @@ -6323,38 +4438,15 @@ "tslib": "^2.0.3" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "requires": { - "homedir-polyfill": "^1.0.1" + "convert-source-map": "^2.0.0" } }, "validate-npm-package-license": { @@ -6412,11 +4504,6 @@ "has-tostringtag": "^1.0.0" } }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -6457,7 +4544,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write-file-atomic": { "version": "4.0.2", diff --git a/package.json b/package.json index 00506422..6201acf5 100644 --- a/package.json +++ b/package.json @@ -3,72 +3,15 @@ "version": "1.0.1", "homepage": "https://www.onlyoffice.com", "private": true, - "grunt": { - "copy": { - "server": { - "expand": true, - "src": [ - "./**/sources/*.js", - "./Common/package.json", - "./DocService/package.json", - "./DocService/public/healthcheck.docx", - "./FileConverter/package.json", - "./FileConverter/bin/DoctRenderer.config", - "./Metrics/package.json", - "./Common/config/*.json", - "./Common/config/log4js/*.json", - "./Metrics/config/config.js" - ], - "dest": "./build/server" - } - }, - "develop-copy": { - "server": {} - }, - "clean": { - "options": { - "force": true - }, - "server": "./build/server" - }, - "mkdir": { - "server": { - "options": { - "create": [ - "./build/server" - ] - } - } - } - }, - "postprocess": { - "src": [ - "./build/server/**/sources/*.js" - ], - "dest": "./" - }, - "npm": [ - "./build/server/Common", - "./build/server/DocService", - "./build/server/FileConverter", - "./build/server/Metrics" - ], "dependencies": { - "grunt": "1.5.3", - "grunt-banner": "0.6.0", - "grunt-check-dependencies": "1.0.0", - "grunt-contrib-clean": "2.0.0", - "grunt-contrib-copy": "1.0.0", - "grunt-mkdir": "1.1.0", - "grunt-stripcomments": "0.7.2", "license-downloader": "1.0.8", "license-report": "6.5.0", "npm-run-all": "4.1.5" }, "devDependencies": { - "@jest/globals": "29.5.0", + "@jest/globals": "29.7.0", "cross-env": "7.0.3", - "jest": "29.5.0" + "jest": "29.7.0" }, "scripts": { "perf-expired": "cd ./DocService&& cross-env NODE_ENV=development-windows NODE_CONFIG_DIR=../Common/config node ../tests/perf/checkFileExpire.js", diff --git a/tests/unit/utils.tests.js b/tests/unit/utils.tests.js index 08880c0c..4dbc3d4f 100644 --- a/tests/unit/utils.tests.js +++ b/tests/unit/utils.tests.js @@ -42,7 +42,7 @@ const minimumIterationsByteLength = 4; describe('AES encryption & decryption', function () { test('Iterations range', async function () { - const configuration = config.get('aesEncrypt.config'); + const configuration = config.util.cloneDeep(config.get('aesEncrypt.config')); const encrypted = await utils.encryptPassword(ctx, 'secretstring'); const { iterationsByteLength = 5 } = configuration; From 294c2d1162fc871b8b63856da932368bd9c92463 Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Wed, 19 Mar 2025 12:20:44 +0300 Subject: [PATCH 02/17] [bug] Fix typo --- Common/sources/storage-s3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/sources/storage-s3.js b/Common/sources/storage-s3.js index 5d7ef028..66b18076 100644 --- a/Common/sources/storage-s3.js +++ b/Common/sources/storage-s3.js @@ -47,7 +47,7 @@ const ms = require('ms'); const commonDefines = require('./../../Common/sources/commondefines'); const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute')); -const cfgRequestDefaults = config.util.cloneDeepconfig.get('services.CoAuthoring.requestDefaults'); +const cfgRequestDefaults = config.util.cloneDeep(config.get('services.CoAuthoring.requestDefaults')); //This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys. const MAX_DELETE_OBJECTS = 1000; From fb6e053c968c6835938fbebbe0ebab5616198fde Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Wed, 19 Mar 2025 20:02:31 +0300 Subject: [PATCH 03/17] [npm] fix proxy, url parsing and http agent --- Common/sources/utils.js | 117 +++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 0f1d9301..cb91f1bd 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -55,6 +55,7 @@ const commonDefines = require('./commondefines'); const forwarded = require('forwarded'); const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent } = require("request-filtering-agent"); const https = require('https'); +const http = require('http'); const ca = require('win-ca/api'); const util = require('util'); @@ -274,7 +275,7 @@ function raiseErrorObj(ro, error) { ro.emit('error', error); } function isRedirectResponse(response) { - return response && response.statusCode >= 300 && response.statusCode < 400 && response.caseless.has('location'); + return response && response.status >= 300 && response.status < 400 && Object.keys(response.headers).some(key => key.toLowerCase() === 'location'); } function isAllowDirectRequest(ctx, uri, isInJwtToken) { @@ -296,28 +297,42 @@ function isAllowDirectRequest(ctx, uri, isInJwtToken) { function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { let res = false; const tenExternalRequestAction = ctx.getCfg('externalRequest.action', cfgExternalRequestAction); - const tenRequesFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); + const tenRequestFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); if (isAllowDirectRequest(ctx, uri, isInJwtToken)) { res = true; } else if (tenExternalRequestAction.allow) { res = true; if (tenExternalRequestAction.blockPrivateIP) { - const agentOptions = Object.assign({}, https.globalAgent.options, tenRequesFilteringAgent); - options.agent = getRequestFilterAgent(uri, agentOptions); - } - if (tenExternalRequestAction.proxyUrl) { - options.proxy = tenExternalRequestAction.proxyUrl; + const agentOptions = { + ...https.globalAgent.options, + ...tenRequestFilteringAgent + }; + + if (tenExternalRequestAction.proxyUrl) { + const proxyUrl = tenExternalRequestAction.proxyUrl; + const parsedProxyUrl = url.parse(proxyUrl); + + agentOptions.host = parsedProxyUrl.hostname; + agentOptions.port = parsedProxyUrl.port; + agentOptions.protocol = parsedProxyUrl.protocol; + } + + if (uri.startsWith('https:')) { + options.httpsAgent = new RequestFilteringHttpsAgent(agentOptions); + } else { + options.httpAgent = new RequestFilteringHttpAgent(agentOptions); + } } if (tenExternalRequestAction.proxyUser?.username) { - let user = tenExternalRequestAction.proxyUser.username; - let pass = tenExternalRequestAction.proxyUser.password; - options.headers = {'proxy-authorization': `${user}:${pass}`}; + const user = tenExternalRequestAction.proxyUser.username; + const pass = tenExternalRequestAction.proxyUser.password || ''; + options.headers['proxy-authorization'] = `${user}:${pass}`; } if (tenExternalRequestAction.proxyHeaders) { - if (!options.headers) { - options.headers = {}; - } - Object.assign(options.headers, tenExternalRequestAction.proxyHeaders); + options.headers = { + ...options.headers, + ...tenExternalRequestAction.proxyHeaders + }; } } return res; @@ -353,15 +368,24 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - // uri = URI.serialize(URI.parse(uri)); const sizeLimit = optLimit || Number.MAX_VALUE - + uri = URI.serialize(URI.parse(uri)); const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; const options = config.util.cloneDeep(tenTenantRequestDefaults); if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { throw new Error('Block external request. See externalRequest config options'); } + const protocol = new URL(uri).protocol; + if (!options.httpsAgent && !options.httpAgent) { + const agentOptions = { ...https.globalAgent.options }; + if (protocol === 'https:') { + options.httpsAgent = new https.Agent(agentOptions); + } else if (protocol === 'http:') { + options.httpAgent = new http.Agent(agentOptions); + } + } + const headers = { ...options.headers }; if (opt_Authorization) { headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; @@ -370,8 +394,8 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, Object.assign(headers, opt_headers); } - const agentOptions = options.agent ? undefined : (https.globalAgent.options || {}); const axiosConfig = { + ...options, url: uri, method: 'GET', responseType: 'stream', @@ -379,31 +403,29 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, maxRedirects: 0, timeout: connectionAndInactivity, validateStatus: () => true, - httpsAgent: uri.protocol === 'https:' - ? new https.Agent(agentOptions) - : undefined, cancelToken: new axios.CancelToken(cancel => { if (optTimeout?.wholeCycle) { setTimeout(() => cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`), ms(optTimeout.wholeCycle)); } - }) + }), }; try { const response = await axios(axiosConfig); const { status, headers } = response; - if (isRedirectResponse(response)) { - const error = new Error(`Redirect ${status}`); + if (status !== 200 && status !== 206) { + const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)};`); + error.statusCode = status; error.response = response; throw error; } - + const contentLength = headers['content-length']; if (contentLength && parseInt(contentLength) > sizeLimit) { - throw new Error('EMSGSIZE: Content-Length exceeds limit'); + throw new Error('EMSGSIZE: Error response: content-length:' + contentLength); } - + return await processResponseStream(ctx, { response, sizeLimit, @@ -416,18 +438,19 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, if (axios.isCancel(err)) { const error = new Error(err.message); error.code = 'ETIMEDOUT'; - throw error; - } - - if (err.response) { - if (opt_streamWriter && !isRedirectResponse(err.response)) { - return processErrorResponseStream(err.response, { - sizeLimit, - opt_streamWriter, - timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null - }); + throw error; + } + + if (err.response) { + if (opt_streamWriter && !isRedirectResponse(err.response)) { + delete err.response.headers['set-cookie']; + return processErrorResponseStream(err.response, { + sizeLimit, + opt_streamWriter, + timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null + }); + } } - } throw err; } } @@ -453,7 +476,7 @@ async function processResponseStream(ctx, { response, sizeLimit, uri, opt_stream bufferLength += chunk.length; if (bufferLength > sizeLimit) { stream.destroy(); - reject(new Error('EMSGSIZE: Response body exceeds limit')); + throw new Error('EMSGSIZE: Error response body.length'); } if (!opt_streamWriter) buffer.push(chunk); }); @@ -468,12 +491,12 @@ async function processResponseStream(ctx, { response, sizeLimit, uri, opt_stream body: opt_streamWriter ? null : Buffer.concat(buffer) }; - if (contentLength && result.body?.length !== parseInt(contentLength)) { - ctx.logger.warn('Body size mismatch: %s (expected %s, got %d)', + if (!opt_streamWriter && contentLength && result.body?.length !== parseInt(contentLength)) { + ctx.logger.warn('Body size mismatch: %s (expected %s, got %d)', uri, contentLength, result.body?.length); } - resolve(result); + resolve(opt_streamWriter ? undefined : result); }); if (opt_streamWriter) { @@ -528,6 +551,7 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); const wholeCycleTimeout = optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : undefined; + uri = URI.serialize(URI.parse(uri)); let options = config.util.extendDeep({}, tenTenantRequestDefaults); Object.assign(options, { method: 'post', @@ -538,9 +562,14 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { throw new Error('Block external request. See externalRequest config options') } - if (!options.agent) { - //baseRequest creates new agent(win-ca injects in globalAgent) - options.httpsAgent = new https.Agent(https.globalAgent.options); + const protocol = new URL(uri).protocol; + if (!options.httpsAgent && !options.httpAgent) { + const agentOptions = { ...https.globalAgent.options }; + if (protocol === 'https:') { + options.httpsAgent = new https.Agent(agentOptions); + } else if (protocol === 'http:') { + options.httpAgent = new http.Agent(agentOptions); + } } if (postData) { options.data = postData; From ff9405f8bed0fb89c81fb021c274c0a328359adf Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Thu, 20 Mar 2025 17:27:39 +0300 Subject: [PATCH 04/17] [test] Add tests for downloadUrlPromise --- Common/sources/utils.js | 2 +- tests/jest.config.js | 4 +- tests/unit/request.tests.js | 407 ++++++++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+), 2 deletions(-) create mode 100644 tests/unit/request.tests.js diff --git a/Common/sources/utils.js b/Common/sources/utils.js index cb91f1bd..d2ff34ec 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -41,7 +41,7 @@ var fs = require('fs'); var path = require('path'); const crypto = require('crypto'); var url = require('url'); -var axios = require('axios') +var axios = require('axios'); var co = require('co'); var URI = require("uri-js"); const escapeStringRegexp = require('escape-string-regexp'); diff --git a/tests/jest.config.js b/tests/jest.config.js index 2f3ba967..06b1f86a 100644 --- a/tests/jest.config.js +++ b/tests/jest.config.js @@ -120,7 +120,9 @@ module.exports = { // ], // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: {}, + moduleNameMapper: { + '^axios$': '../../Common/node_modules/axios/dist/node/axios.cjs', + }, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader // modulePathIgnorePatterns: [], diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js new file mode 100644 index 00000000..a7cb7c6f --- /dev/null +++ b/tests/unit/request.tests.js @@ -0,0 +1,407 @@ +// Required modules +const { describe, test, expect, beforeEach, afterAll, jest } = require('@jest/globals'); +const { Readable, Writable } = require('stream'); +// Setup mocks for axios +jest.mock('axios'); +const axios = require('axios'); +const operationContext = require('../../Common/sources/operationContext'); +const utils = require('../../Common/sources/utils'); + +// Mock axios CancelToken as both a constructor and an object with source method +const cancelFn = jest.fn(); +axios.CancelToken = jest.fn().mockImplementation((executor) => { + // Execute the function passed to CancelToken constructor with our cancel function + if (typeof executor === 'function') { + executor(cancelFn); + } + return { cancel: cancelFn }; +}); + +// Also mock the source method +axios.CancelToken.source = jest.fn().mockReturnValue({ + token: 'mock-token', + cancel: jest.fn() +}); + +// Create operation context for tests +const ctx = new operationContext.Context(); + +// Helper functions for creating test streams +const createMockStream = (data) => { + // Convert string to Buffer if it's not already a buffer + const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data || JSON.stringify({ success: true }), 'utf8'); + // Create a Readable stream from buffer data + return Readable.from(bufferData); +}; + +const createMockWriter = () => { + const chunks = []; + return new Writable({ + write(chunk, encoding, callback) { + chunks.push(chunk); + callback(); + } + }); +}; + +// Common test parameters +const commonTestParams = { + uri: 'https://example.com/api/data', + timeout: 5000, + limit: 1024 * 1024, // 1MB + authorization: 'Bearer token123', + filterPrivate: true, + headers: { 'Accept': 'application/json' } +}; + +// Creates common parameter assertion +const createParamAssertion = (uri) => { + return expect.objectContaining({ + url: uri || commonTestParams.uri, + timeout: commonTestParams.timeout, + maxContentLength: commonTestParams.limit, + responseType: 'stream', + headers: expect.objectContaining({ + 'Accept': 'application/json', + 'Authorization': commonTestParams.authorization + }) + }); +}; + +describe('HTTP Request Functionality', () => { + beforeEach(() => { + // Reset all mocks before each test + jest.clearAllMocks(); + }); + + afterAll(() => { + // Clean up all mocks + jest.restoreAllMocks(); + }); + + describe('downloadUrlPromise', () => { + test('properly handles content streaming', async () => { + // Create mock data + const mockData = 'Sample data content'; + + // Mock successful response with stream + const mockResponse = { + status: 200, + headers: { + 'content-type': 'text/plain', + 'content-length': String(Buffer.byteLength(mockData, 'utf8')) + }, + data: createMockStream(mockData) + }; + + // Setup axios mock - axios() is used directly in the code, not axios.get() + axios.mockImplementation((config) => { + console.log('Mock axios called with config:', JSON.stringify(config, null, 2)); + return Promise.resolve(mockResponse); + }); + + // Create a proper writable stream for testing + const mockStreamWriter = createMockWriter(); + + // Test version with stream writer (returns undefined) + const resultWithStreamWriter = await utils.downloadUrlPromise( + ctx, + 'https://example.com/file', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + mockStreamWriter + ); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + + // With stream writer, the function returns undefined + expect(resultWithStreamWriter).toBeUndefined(); + }); + + test('returns complete response without stream writer', async () => { + // Create mock data + const mockData = JSON.stringify({ data: 'test content' }); + + // Mock successful response with stream + const mockResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(mockData, 'utf8')) + }, + data: createMockStream(mockData) + }; + + // Reset mocks and setup new behavior + jest.clearAllMocks(); + axios.mockImplementation(() => Promise.resolve(mockResponse)); + + // Call function without stream writer + const result = await utils.downloadUrlPromise( + ctx, + 'https://example.com/data', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null // No stream writer + ); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + + // Verify full response object is returned + expect(result).toBeDefined(); + expect(result).toHaveProperty('response', mockResponse); + expect(result).toHaveProperty('sha256'); + expect(result).toHaveProperty('body'); + expect(result.sha256).toMatch(/^[a-f0-9]{64}$/i); + expect(Buffer.isBuffer(result.body)).toBe(true); + }); + + test('throws error on non-200 status codes', async () => { + // Create error data + const errorData = JSON.stringify({ error: 'Not found' }); + + // Mock error response with stream + const mockErrorResponse = { + status: 404, + statusText: 'Not Found', + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(errorData, 'utf8')) + }, + data: createMockStream(errorData) + }; + + // Reset mocks and setup new behavior for error + jest.clearAllMocks(); + axios.mockImplementation(() => Promise.resolve(mockErrorResponse)); + + // Call function and expect it to throw + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/not-found', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + )).rejects.toThrow(/Error response: statusCode:404/); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + }); + + test('throws error when content-length exceeds limit', async () => { + // Create large data (but mock only returns the header) + const mockResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': '2097152' // 2MB (greater than 1MB limit) + }, + data: createMockStream('{}') // actual data is irrelevant, header check happens first + }; + + // Reset mocks and setup new behavior + jest.clearAllMocks(); + axios.mockImplementation(() => Promise.resolve(mockResponse)); + + // Call function with a 1MB limit and expect it to throw + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/large-file', + commonTestParams.timeout, + 1024 * 1024, // 1MB limit + null, + false, + null, + null + )).rejects.toThrow(/EMSGSIZE: Error response: content-length/); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + }); + + test('follows redirects correctly', async () => { + // Create a counter to track calls + let callCount = 0; + + // Mock redirect response + const redirectResponse = { + status: 302, + headers: { + location: 'https://example.com/redirected' + } + }; + + // Mock success response after redirect + const successData = JSON.stringify({ success: true }); + const successResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(successData, 'utf8')) + }, + data: createMockStream(successData) + }; + + // Reset mocks and implement redirect then success + jest.clearAllMocks(); + axios.mockImplementation(() => { + if (callCount === 0) { + callCount++; + // First call - simulate redirect by throwing error with response + const err = new Error('Redirect'); + err.response = redirectResponse; + return Promise.reject(err); + } else { + // Second call - return success + return Promise.resolve(successResponse); + } + }); + + // Call function with original URL + const result = await utils.downloadUrlPromise( + ctx, + 'https://example.com/original', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + ); + + // Verify axios was called twice (once for original, once for redirect) + expect(axios).toHaveBeenCalledTimes(2); + + // Verify the result is from the successful redirect + expect(result).toBeDefined(); + expect(result).toHaveProperty('response'); + expect(result).toHaveProperty('sha256'); + expect(result.response.status).toBe(200); + }); + + test('handles network errors correctly', async () => { + // Reset mocks and implement network error + jest.clearAllMocks(); + axios.mockImplementation(() => { + const err = new Error('Network Error'); + return Promise.reject(err); + }); + + // Call function and expect network error + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/network-error', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + )).rejects.toThrow('Network Error'); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + }); + + test('handles binary data correctly', async () => { + // Create binary data (simple buffer with pattern of bytes) + const binaryData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); // PNG file signature + + // Mock successful response with binary stream + const mockResponse = { + status: 200, + headers: { + 'content-type': 'image/png', + 'content-length': String(binaryData.length) + }, + data: createMockStream(binaryData) + }; + + // Reset mocks and setup for binary data + jest.clearAllMocks(); + axios.mockImplementation(() => Promise.resolve(mockResponse)); + + // Call function without stream writer + const result = await utils.downloadUrlPromise( + ctx, + 'https://example.com/image.png', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + ); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + + // Verify binary data is preserved correctly + expect(result).toBeDefined(); + expect(result).toHaveProperty('body'); + expect(Buffer.isBuffer(result.body)).toBe(true); + expect(result.body.length).toBe(binaryData.length); + // Verify the content matches the original binary data + expect(Buffer.compare(result.body, binaryData)).toBe(0); + }); + + test('handles timeout correctly', async () => { + // Reset mocks + jest.clearAllMocks(); + + // Setup axios mock to simulate a timeout by triggering the CancelToken cancel function + axios.mockImplementation((config) => { + // Explicitly check for timeout config + expect(config).toHaveProperty('timeout'); + expect(config).toHaveProperty('cancelToken'); + + // Return a promise that never resolves - the cancel function + // will be called by setTimeout in the implementation + return new Promise(() => { + // setTimeout is used in the real implementation, but we don't need to do anything here + // as the cancelFn mock will be called by the code under test + }); + }); + + // Mock Implementation will call canceFn after "timeout" - simulate this + cancelFn.mockImplementation((message) => { + // This is what happens when the timeout occurs and cancel is called + const err = new Error(message || 'ETIMEDOUT: timeout'); + err.isCancel = true; // axios sets this flag + throw err; + }); + + // Call function and expect timeout error + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/slow-response', + { connection: '100ms', inactivity: '100ms', wholeCycle: '200ms' }, // short timeout + commonTestParams.limit, + null, + false, + null, + null + )).rejects.toThrow(/ETIMEDOUT/); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + + // Verify timeout was properly configured + expect(axios).toHaveBeenCalledWith(expect.objectContaining({ + timeout: expect.any(Number), + cancelToken: expect.anything() + })); + }); + }); +}); \ No newline at end of file From 7d8425c062e85532ac87c4895070d5828f293dc2 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Tue, 25 Mar 2025 13:40:33 +0300 Subject: [PATCH 05/17] [test] Add tests for downloadUrlPromise, postRequestPromise --- Common/config/default.json | 3 +- Common/sources/utils.js | 13 +- package.json | 1 + tests/unit/request.tests.js | 405 +++++++++++++++++++++++++++++++----- 4 files changed, 369 insertions(+), 53 deletions(-) diff --git a/Common/config/default.json b/Common/config/default.json index 9c51012f..29bea340 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -320,7 +320,8 @@ "User-Agent": "Node.js/6.13", "Connection": "Keep-Alive" }, - "decompress": true + "decompress": true, + "rejectUnauthorized": true }, "autoAssembly": { "enable": false, diff --git a/Common/sources/utils.js b/Common/sources/utils.js index d2ff34ec..8bfd5921 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -372,13 +372,13 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, uri = URI.serialize(URI.parse(uri)); const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; const options = config.util.cloneDeep(tenTenantRequestDefaults); - if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { + if (!exports.addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { throw new Error('Block external request. See externalRequest config options'); } const protocol = new URL(uri).protocol; if (!options.httpsAgent && !options.httpAgent) { - const agentOptions = { ...https.globalAgent.options }; + const agentOptions = { ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false? false : true}; if (protocol === 'https:') { options.httpsAgent = new https.Agent(agentOptions); } else if (protocol === 'http:') { @@ -393,7 +393,7 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, if (opt_headers) { Object.assign(headers, opt_headers); } - + const axiosConfig = { ...options, url: uri, @@ -405,7 +405,9 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, validateStatus: () => true, cancelToken: new axios.CancelToken(cancel => { if (optTimeout?.wholeCycle) { - setTimeout(() => cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`), ms(optTimeout.wholeCycle)); + setTimeout(() => { + cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); + }, ms(optTimeout.wholeCycle)); } }), }; @@ -564,7 +566,7 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi } const protocol = new URL(uri).protocol; if (!options.httpsAgent && !options.httpAgent) { - const agentOptions = { ...https.globalAgent.options }; + const agentOptions = { ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false? false : true}; if (protocol === 'https:') { options.httpsAgent = new https.Agent(agentOptions); } else if (protocol === 'http:') { @@ -627,6 +629,7 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi } exports.postRequestPromise = postRequestPromise; exports.downloadUrlPromise = downloadUrlPromise; +exports.addExternalRequestOptions = addExternalRequestOptions; exports.mapAscServerErrorToOldError = function(error) { var res = -1; switch (error) { diff --git a/package.json b/package.json index 6201acf5..f203fb6b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "integration tests with server instance": "cd ./DocService && jest integration/withServerInstance --inject-globals=false --config=../tests/jest.config.js", "integration database tests": "cd ./DocService && jest integration/databaseTests --inject-globals=false --config=../tests/jest.config.js", "tests": "cd ./DocService && jest --inject-globals=false --config=../tests/jest.config.js", + "tests:dev": "cd ./DocService && jest --inject-globals=false --config=../tests/jest.config.js --watch", "install:Common": "npm ci --prefix ./Common", "install:DocService": "npm ci --prefix ./DocService", "install:FileConverter": "npm ci --prefix ./FileConverter", diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index a7cb7c6f..31948c43 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -2,26 +2,15 @@ const { describe, test, expect, beforeEach, afterAll, jest } = require('@jest/globals'); const { Readable, Writable } = require('stream'); // Setup mocks for axios +const axiosReal = require('axios'); jest.mock('axios'); const axios = require('axios'); const operationContext = require('../../Common/sources/operationContext'); const utils = require('../../Common/sources/utils'); -// Mock axios CancelToken as both a constructor and an object with source method -const cancelFn = jest.fn(); -axios.CancelToken = jest.fn().mockImplementation((executor) => { - // Execute the function passed to CancelToken constructor with our cancel function - if (typeof executor === 'function') { - executor(cancelFn); - } - return { cancel: cancelFn }; -}); - -// Also mock the source method -axios.CancelToken.source = jest.fn().mockReturnValue({ - token: 'mock-token', - cancel: jest.fn() -}); +// Assign real CancelToken from the imported axiosReal to the mocked axios +axios.CancelToken = axiosReal.CancelToken; +axios.CancelToken.source = axiosReal.CancelToken.source; // Create operation context for tests const ctx = new operationContext.Context(); @@ -47,9 +36,9 @@ const createMockWriter = () => { // Common test parameters const commonTestParams = { uri: 'https://example.com/api/data', - timeout: 5000, + timeout: { wholeCycle: '500ms', connectionAndInactivity: '200s' }, limit: 1024 * 1024, // 1MB - authorization: 'Bearer token123', + authorization: 'token123', filterPrivate: true, headers: { 'Accept': 'application/json' } }; @@ -357,51 +346,373 @@ describe('HTTP Request Functionality', () => { }); test('handles timeout correctly', async () => { - // Reset mocks - jest.clearAllMocks(); - - // Setup axios mock to simulate a timeout by triggering the CancelToken cancel function + jest.useFakeTimers(); + // Mock a never-resolving request axios.mockImplementation((config) => { - // Explicitly check for timeout config - expect(config).toHaveProperty('timeout'); - expect(config).toHaveProperty('cancelToken'); - - // Return a promise that never resolves - the cancel function - // will be called by setTimeout in the implementation - return new Promise(() => { - // setTimeout is used in the real implementation, but we don't need to do anything here - // as the cancelFn mock will be called by the code under test + return new Promise((_, reject) => { + if (config.cancelToken) { + config.cancelToken.promise.then(cancel => { + reject(new axiosReal.Cancel(cancel.message)); + }); + } }); }); + + const promise = utils.downloadUrlPromise( + ctx, + 'https://example.com/timeout-test', + { wholeCycle: '500ms', connectionAndInactivity: '200s' }, + 1024, + null, + false, + null, + null + ); + + // Fast-forward exactly 1 second + jest.advanceTimersByTime(1000); + await Promise.resolve(); // Flush pending promises + + await expect(promise).rejects.toThrow('ETIMEDOUT: 500ms'); + + jest.useRealTimers(); + }); + + test('throws an error on max redirects limit reached', async () => { + // Create a counter to track calls + let callCount = 0; - // Mock Implementation will call canceFn after "timeout" - simulate this - cancelFn.mockImplementation((message) => { - // This is what happens when the timeout occurs and cancel is called - const err = new Error(message || 'ETIMEDOUT: timeout'); - err.isCancel = true; // axios sets this flag - throw err; + // Mock redirect response + const redirectResponse = { + status: 302, + headers: { + location: 'https://example.com/redirected' + } + }; + + // Mock success response after redirect + const successData = JSON.stringify({ success: true }); + const successResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(successData, 'utf8')) + }, + data: createMockStream(successData) + }; + + // Reset mocks and implement redirect then success + jest.clearAllMocks(); + axios.mockImplementation(() => { + if (callCount < 12) { + callCount++; + // First call - simulate redirect by throwing error with response + const err = new Error('Redirect'); + err.response = redirectResponse; + return Promise.reject(err); + } else { + // Second call - return success + return Promise.resolve(successResponse); + } }); - // Call function and expect timeout error + // Call function with original URL await expect(utils.downloadUrlPromise( ctx, - 'https://example.com/slow-response', - { connection: '100ms', inactivity: '100ms', wholeCycle: '200ms' }, // short timeout + 'https://example.com/original', + commonTestParams.timeout, commonTestParams.limit, null, false, null, null - )).rejects.toThrow(/ETIMEDOUT/); + )).rejects.toThrow('Redirect'); + + expect(axios).toHaveBeenCalledTimes(11); + }); + + test('should block external request', async () => { + + const addExternalRequestOptionsMock = jest.spyOn(utils, 'addExternalRequestOptions'); + + addExternalRequestOptionsMock.mockReturnValue(false); + + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/original', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + )).rejects.toThrow('Block external request. See externalRequest config options'); + + addExternalRequestOptionsMock.mockRestore(); + }); + + test('should throw error on redirect with followRedirect=false', async () => { + let callCount = 0; + + // Mock redirect response + const redirectResponse = { + status: 302, + headers: { + location: 'https://example.com/redirected' + } + }; + + // Mock success response after redirect + const successData = JSON.stringify({ success: true }); + const successResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(successData, 'utf8')) + }, + data: createMockStream(successData) + }; + + // Reset mocks and implement redirect then success + jest.clearAllMocks(); + axios.mockImplementation(() => { + if (callCount < 2) { + callCount++; + // First call - simulate redirect by throwing error with response + const err = new Error('Redirect'); + err.response = redirectResponse; + return Promise.reject(err); + } else { + // Second call - return success + return Promise.resolve(successResponse); + } + }); + + const ctx = { + getCfg: function(key, _) { + switch (key) { + case 'services.CoAuthoring.requestDefaults': + return { + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, + "decompress": true, + "rejectUnauthorized": true, + "followRedirect": false + } + case 'services.CoAuthoring.token.outbox.header': + return "Authorization"; + case 'services.CoAuthoring.token.outbox.prefix': + return "Bearer "; + case 'externalRequest.action': + return { + "allow": true, + "blockPrivateIP": true, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": { + } + }; + case 'services.CoAuthoring.request-filtering-agent': + return { + "allowPrivateIPAddress": false, + "allowMetaIPAddress": false + } + case 'externalRequest.directIfIn': + return { + "allowList": [], + "jwtToken": true + } + } + }, + logger: { + debug: function() {}, + } + } + + await expect(utils.downloadUrlPromise( + ctx, + 'https://example.com/original', + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null, + null + )).rejects.toThrow('Redirect'); + }); + }); + + describe('postRequestPromise', () => { + test('properly sends post data and returns response', async () => { + // Mock successful response + const mockData = { success: true }; + const mockResponse = { + status: 200, + headers: { 'content-type': 'application/json' }, + data: mockData + }; + + // Setup axios mock + axios.mockImplementation(() => Promise.resolve(mockResponse)); + + // Call the function + const result = await utils.postRequestPromise( + ctx, + 'https://example.com/data', + { key: 'value' }, + null, + null, + commonTestParams.timeout, + commonTestParams.authorization, + false, + null + ); + + // Verify axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith(expect.objectContaining({ + method: 'post', + url: 'https://example.com/data', + data: { key: 'value' }, + validateStatus: expect.any(Function), + timeout: expect.any(Number), + })); + + expect(result).toBeDefined(); + expect(result).toHaveProperty('response'); + expect(result.response.statusCode).toBe(200); + expect(result.response.body).toBe(mockData); + }); + + + test('handles timeout and cancels request', async () => { + // Mock cancellation + const cancelMessage = 'Whole request cycle timeout: 500ms'; + axios.mockImplementation(() => { + const error = new Error(cancelMessage); + error.code = 'ETIMEDOUT'; + throw error; + }); + + // Call function and expect it to throw ETIMEDOUT error + await expect(utils.postRequestPromise( + ctx, + 'https://example.com/data', + { key: 'value' }, + null, + null, + commonTestParams.timeout, + commonTestParams.authorization, + false, + null + )).rejects.toThrowError(cancelMessage); // Verify axios was called expect(axios).toHaveBeenCalledTimes(1); - - // Verify timeout was properly configured - expect(axios).toHaveBeenCalledWith(expect.objectContaining({ - timeout: expect.any(Number), - cancelToken: expect.anything() - })); }); - }); + + test('throws error for non-200 status codes', async () => { + // Create mock error data + const errorData = JSON.stringify({ error: 'Not found' }); + const mockErrorResponse = { + status: 404, + statusText: 'Not Found', + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(errorData, 'utf8')) + }, + data: errorData + }; + + // Setup axios mock + axios.mockImplementation(() => Promise.reject({ response: mockErrorResponse })); + + // Call function and expect it to throw error + await expect(utils.postRequestPromise( + ctx, + 'https://example.com/not-found', + { key: 'value' }, + null, + null, + commonTestParams.timeout, + commonTestParams.authorization, + false, + null + )).rejects.toThrowError(/Error response: statusCode:404/); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + }); + + test('handles post data stream correctly', async () => { + // Mock successful response with stream + const mockData = 'Sample streamed content'; + const mockResponse = { + status: 200, + headers: { + 'content-type': 'application/json', + 'content-length': String(Buffer.byteLength(mockData, 'utf8')) + }, + data: mockData + }; + + // Setup axios mock + axios.mockImplementation(() => Promise.resolve(mockResponse)); + + // Call the function with postDataStream + const result = await utils.postRequestPromise( + ctx, + 'https://example.com/upload', + null, + mockData, + null, + commonTestParams.timeout, + commonTestParams.authorization, + false, + null + ); + + expect(axios).toHaveBeenCalledWith(expect.objectContaining({ + method: 'post', + url: 'https://example.com/upload', + headers: expect.objectContaining({ + 'Authorization': 'Bearer token123' + }), + data: mockData, + validateStatus: expect.any(Function), + timeout: expect.any(Number), + })); + + // Verify result + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(result.response.body).toBe(mockData); + }); + + test('handles network errors correctly', async () => { + // Mock network error + const networkError = new Error('Network Error'); + axios.mockImplementation(() => Promise.reject(networkError)); + + // Call function and expect it to throw network error + await expect(utils.postRequestPromise( + ctx, + 'https://example.com/network-error', + { key: 'value' }, + null, + null, + commonTestParams.timeout, + commonTestParams.authorization, + false, + null + )).rejects.toThrowError('Network Error'); + + // Verify axios was called + expect(axios).toHaveBeenCalledTimes(1); + }); + }) }); \ No newline at end of file From ee1fca912af9527ede4af865aa380297d1ea3fbe Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Wed, 26 Mar 2025 14:34:17 +0300 Subject: [PATCH 06/17] [test] Add requestSSRF.tests.js for SSRF request to denied IP --- tests/unit/requestSSRF.tests.js | 116 ++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/unit/requestSSRF.tests.js diff --git a/tests/unit/requestSSRF.tests.js b/tests/unit/requestSSRF.tests.js new file mode 100644 index 00000000..a6e3ae55 --- /dev/null +++ b/tests/unit/requestSSRF.tests.js @@ -0,0 +1,116 @@ +const GOOD_HOST = '127.0.0.1'; +const BAD_HOST = '127.0.0.2'; + +const GOOD_PORT = 4668; +const GOOD_PORT_REDIRECT = 4667; +const BAD_PORT = 4669; + +process.env['NODE_CONFIG'] = JSON.stringify({ + "services": { + "CoAuthoring": { + "request-filtering-agent": { + "allowPrivateIPAddress": false, + "allowMetaIPAddress": false, + "allowIPAddressList": [ + GOOD_HOST + ] + } + } + } +}); + +// Required modules +const { describe, test, expect, beforeAll, afterAll, it, jest } = require('@jest/globals'); +const http = require('http'); + +const operationContext = require('../../Common/sources/operationContext'); +const utils = require('../../Common/sources/utils'); + + +// Common test parameters +const commonTestParams = { + uri: `http://${GOOD_HOST}:${GOOD_PORT}`, + timeout: 5000, + limit: 1024 * 1024, // 1MB + authorization: 'Bearer token123', + filterPrivate: true, + headers: { 'Accept': 'application/json' } +}; +const ctx = operationContext.global; + +describe('Server-Side Request Forgery (SSRF)', () => { + let goodServer, goodServerRedirect, badServer; + + beforeAll(() => { + + goodServer = http.createServer(function (req, res) { + res.write('good'); + res.end(); + }).listen(GOOD_PORT); + + goodServerRedirect = http.createServer(function (req, res) { + console.log(`Received request for: ${req.url}`); + + // Set redirect status code (301 for permanent redirect, 302 for temporary) + res.statusCode = 302; + + // Set the Location header to the redirect destination + res.setHeader('Location', `http://${BAD_HOST}:${BAD_PORT}`); + + // You can add other headers if needed + res.setHeader('Content-Type', 'text/plain'); + + // Send a brief message in the body (optional) + res.end(`Redirecting to http://${BAD_HOST}:${BAD_PORT}`); + }).listen(GOOD_PORT_REDIRECT); + + badServer = http.createServer(function (req, res) { + res.write('bad'); + res.end(); + }).listen(BAD_PORT); + }) + + afterAll(() => { + goodServer.close(); + goodServerRedirect.close(); + badServer.close(); + }); + + it('should fetch', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `http://${GOOD_HOST}:${GOOD_PORT}`, + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null + ); + + expect(result.body.toString()).toBe('good'); + }); + + it('should not fetch: denied ip', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `http://${BAD_HOST}:${BAD_PORT}`, + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null + )).rejects.toThrow(); + }); + + it('should not fetch: redirect to denied ip', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `http://${GOOD_HOST}:${GOOD_PORT_REDIRECT}`, + commonTestParams.timeout, + commonTestParams.limit, + null, + false, + null + )).rejects.toThrow(); + }); +}); \ No newline at end of file From 04021115cf0ef279013177de0eeda2cac51b5728 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Mon, 31 Mar 2025 13:42:00 +0300 Subject: [PATCH 07/17] [refactor] Rewrite functions using axios --- Common/sources/utils.js | 76 +- npm-shrinkwrap.json | 418 ++++++++++ package.json | 3 +- .../withServerInstance/request.tests.js | 772 ++++++++++++++++++ tests/unit/request.tests.js | 718 ---------------- 5 files changed, 1219 insertions(+), 768 deletions(-) create mode 100644 tests/integration/withServerInstance/request.tests.js delete mode 100644 tests/unit/request.tests.js diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 8bfd5921..85848393 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -338,37 +338,13 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { return res; } -function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); - const maxRedirects = (undefined !== tenTenantRequestDefaults.maxRedirects) ? tenTenantRequestDefaults.maxRedirects : 10; - const followRedirect = (undefined !== tenTenantRequestDefaults.followRedirect) ? tenTenantRequestDefaults.followRedirect : true; - var redirectsFollowed = 0; - const doRequest = (curUrl) => { - return downloadUrlPromiseWithoutRedirect(ctx, curUrl, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) - .catch(err => { - const response = err.response; - if (isRedirectResponse(response)) { - if (followRedirect && redirectsFollowed < maxRedirects) { - let redirectTo = response.headers.location; - if (!/^https?:/.test(redirectTo)) { - redirectTo = url.resolve(curUrl, redirectTo); - } - - ctx.logger.debug('downloadUrlPromise redirectsFollowed:%d redirectTo: %s', redirectsFollowed, redirectTo); - redirectsFollowed++; - return doRequest(redirectTo); - } - } - throw err; - }); - }; - return doRequest(uri); -} -async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { +async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - const sizeLimit = optLimit || Number.MAX_VALUE + const maxRedirects = (undefined !== tenTenantRequestDefaults.maxRedirects) ? tenTenantRequestDefaults.maxRedirects : 10; + const followRedirect = (undefined !== tenTenantRequestDefaults.followRedirect) ? tenTenantRequestDefaults.followRedirect : true; + const sizeLimit = optLimit || Number.MAX_VALUE; uri = URI.serialize(URI.parse(uri)); const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; const options = config.util.cloneDeep(tenTenantRequestDefaults); @@ -393,16 +369,16 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, if (opt_headers) { Object.assign(headers, opt_headers); } - + const axiosConfig = { ...options, url: uri, method: 'GET', responseType: 'stream', headers, - maxRedirects: 0, + maxRedirects: followRedirect ? maxRedirects : 0, timeout: connectionAndInactivity, - validateStatus: () => true, + validateStatus: (status) => status >= 200 && status < 300, cancelToken: new axios.CancelToken(cancel => { if (optTimeout?.wholeCycle) { setTimeout(() => { @@ -415,8 +391,7 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, try { const response = await axios(axiosConfig); const { status, headers } = response; - - if (status !== 200 && status !== 206) { + if (![200, 206].includes(status)) { const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)};`); error.statusCode = status; error.response = response; @@ -427,7 +402,7 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, if (contentLength && parseInt(contentLength) > sizeLimit) { throw new Error('EMSGSIZE: Error response: content-length:' + contentLength); } - + return await processResponseStream(ctx, { response, sizeLimit, @@ -440,19 +415,19 @@ async function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, if (axios.isCancel(err)) { const error = new Error(err.message); error.code = 'ETIMEDOUT'; - throw error; - } + throw error; + } - if (err.response) { - if (opt_streamWriter && !isRedirectResponse(err.response)) { - delete err.response.headers['set-cookie']; - return processErrorResponseStream(err.response, { - sizeLimit, - opt_streamWriter, - timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null - }); - } + if (err.response) { + if (opt_streamWriter && !isRedirectResponse(err.response)) { + delete err.response.headers['set-cookie']; + return processErrorResponseStream(err.response, { + sizeLimit, + opt_streamWriter, + timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null + }); } + } throw err; } } @@ -554,7 +529,7 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); const wholeCycleTimeout = optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : undefined; uri = URI.serialize(URI.parse(uri)); - let options = config.util.extendDeep({}, tenTenantRequestDefaults); + let options = { ...tenTenantRequestDefaults }; Object.assign(options, { method: 'post', url: uri, @@ -562,11 +537,14 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi validateStatus: (status) => status === 200 || status === 204 }); if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { - throw new Error('Block external request. See externalRequest config options') + throw new Error('Block external request. See externalRequest config options'); } const protocol = new URL(uri).protocol; if (!options.httpsAgent && !options.httpAgent) { - const agentOptions = { ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false? false : true}; + const agentOptions = { + ...https.globalAgent.options, + rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false ? false : true + }; if (protocol === 'https:') { options.httpsAgent = new https.Agent(agentOptions); } else if (protocol === 'http:') { @@ -616,7 +594,7 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi const err = new Error(error.message); err.code = 'ETIMEDOUT'; throw err; - } + } if (error.response) { const { status, headers, data } = error.response; const err = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 64452840..54189366 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1082,6 +1082,16 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1127,6 +1137,12 @@ "is-array-buffer": "^3.0.1" } }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, "arraybuffer.prototype.slice": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", @@ -1275,6 +1291,24 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1311,6 +1345,12 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, "cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -1443,12 +1483,39 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true + }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -1525,6 +1592,15 @@ } } }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1582,6 +1658,18 @@ "object-keys": "^1.1.1" } }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "dev": true + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -1594,6 +1682,12 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, "electron-to-chromium": { "version": "1.5.114", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.114.tgz", @@ -1612,6 +1706,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true + }, "eol": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", @@ -1697,6 +1797,12 @@ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1708,6 +1814,12 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -1744,6 +1856,44 @@ "jest-util": "^29.7.0" } }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1759,6 +1909,21 @@ "bser": "2.1.1" } }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -1782,6 +1947,18 @@ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==" }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2006,6 +2183,27 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + } + } + }, "http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -2021,6 +2219,15 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -2068,6 +2275,12 @@ "side-channel": "^1.0.4" } }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -3522,17 +3735,56 @@ "tmpl": "1.0.5" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true + }, "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==" }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -3557,12 +3809,24 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -3733,6 +3997,15 @@ "object-keys": "^1.1.1" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3803,6 +4076,12 @@ "lines-and-columns": "^1.1.6" } }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3826,6 +4105,12 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -3900,17 +4185,51 @@ "sisteransi": "^1.0.5" } }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, "pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4023,6 +4342,12 @@ } } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -4033,11 +4358,46 @@ "is-regex": "^1.1.4" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "sentence-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", @@ -4048,6 +4408,18 @@ "upper-case-first": "^2.0.2" } }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, "set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -4069,6 +4441,12 @@ "has-property-descriptors": "^1.0.0" } }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4189,6 +4567,12 @@ } } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -4338,6 +4722,12 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -4355,6 +4745,16 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, "typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", @@ -4420,6 +4820,12 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true + }, "update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -4438,6 +4844,12 @@ "tslib": "^2.0.3" } }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true + }, "v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -4458,6 +4870,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, "visit-values": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/visit-values/-/visit-values-2.0.0.tgz", diff --git a/package.json b/package.json index f203fb6b..10b2d7cd 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "devDependencies": { "@jest/globals": "29.7.0", "cross-env": "7.0.3", - "jest": "29.7.0" + "jest": "29.7.0", + "express": "4.17.1" }, "scripts": { "perf-expired": "cd ./DocService&& cross-env NODE_ENV=development-windows NODE_CONFIG_DIR=../Common/config node ../tests/perf/checkFileExpire.js", diff --git a/tests/integration/withServerInstance/request.tests.js b/tests/integration/withServerInstance/request.tests.js new file mode 100644 index 00000000..179e2f54 --- /dev/null +++ b/tests/integration/withServerInstance/request.tests.js @@ -0,0 +1,772 @@ +const { describe, test, expect, beforeAll, afterAll } = require('@jest/globals'); +const { Writable, Readable } = require('stream'); +const http = require('http'); +const express = require('express'); +const operationContext = require('../../../Common/sources/operationContext'); +const utils = require('../../../Common/sources/utils'); +const fs = require('fs').promises; +const path = require('path'); + +// Create operation context for tests +const ctx = new operationContext.Context(); + +// Test server setup +let server; +let testServer; +const PORT = 3456; +const BASE_URL = `http://localhost:${PORT}`; + +// Helper to create a writable stream for testing +const createMockWriter = () => { + const chunks = []; + return new Writable({ + write(chunk, encoding, callback) { + chunks.push(chunk); + callback(); + } + }); +}; + +const getStatusCode = (response) => response.statusCode || response.status; + +function createMockContext(overrides = {}) { + const defaultCtx = { + getCfg: function(key, _) { + switch (key) { + case 'services.CoAuthoring.requestDefaults': + return { + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, + "decompress": true, + "rejectUnauthorized": true, + "followRedirect": false + }; + case 'services.CoAuthoring.token.outbox.header': + return "Authorization"; + case 'services.CoAuthoring.token.outbox.prefix': + return "Bearer "; + case 'externalRequest.action': + return { + "allow": true, + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + }; + case 'services.CoAuthoring.request-filtering-agent': + return { + "allowPrivateIPAddress": false, + "allowMetaIPAddress": false + }; + case 'externalRequest.directIfIn': + return { + "allowList": [], + "jwtToken": true + }; + default: + return undefined; + } + }, + logger: { + debug: function() {}, + } + }; + + // Return a mock context with overridden values if any + return { + ...defaultCtx, + getCfg: function(key, _) { + // Return the override if it exists + if (overrides[key]) { + return overrides[key]; + } + // Otherwise, return the default behavior + return defaultCtx.getCfg(key, _); + } + }; +} + +describe('HTTP Request Integration Tests', () => { + beforeAll(async () => { + // Setup test Express server + const app = express(); + + // Basic endpoint that returns JSON + app.get('/api/data', (req, res) => { + res.json({ success: true }); + }); + + // Endpoint that streams data + app.get('/api/stream', (req, res) => { + res.setHeader('content-type', 'application/octet-stream'); + res.setHeader('content-length', '1024'); + const buffer = Buffer.alloc(1024); + res.send(buffer); + }); + + // Endpoint that simulates timeout + app.get('/api/timeout', (req, res) => { + // Never send response to trigger timeout + return; + }); + + // Endpoint that redirects + app.get('/api/redirect', (req, res) => { + res.redirect('/api/data'); + }); + + // Endpoint that returns error + app.get('/api/error', (req, res) => { + res.status(500).json({ error: 'Internal Server Error' }); + }); + + // POST endpoint + app.post('/api/post', express.json(), (req, res) => { + res.json({ received: req.body }); + }); + + // POST endpoint that times out + app.post('/api/timeout', express.json(), (req, res) => { + // Never send response to trigger timeout + return; + }); + + app.get('/api/binary', (req, res) => { + // PNG file signature as binary data + const binaryData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); + res.setHeader('content-type', 'image/png'); + res.setHeader('content-length', binaryData.length); + res.send(binaryData); + }); + + + // Large file endpoint + app.get('/api/large', (req, res) => { + res.setHeader('content-length', '2097152'); // 2MB + res.setHeader('content-type', 'application/octet-stream'); + const buffer = Buffer.alloc(2097152); + res.send(buffer); + }); + + // Start server + server = http.createServer(app); + await new Promise(resolve => server.listen(PORT, resolve)); + }); + + afterAll(async () => { + // Cleanup server + await new Promise(resolve => server.close(resolve)); + }); + + describe('downloadUrlPromise', () => { + test('successfully downloads JSON data', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/data`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + }); + + test('handles streaming with writer', async () => { + const mockStreamWriter = createMockWriter(); + + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/stream`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + mockStreamWriter + ); + + expect(result).toBeUndefined(); + }); + + test('throws error on timeout', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/timeout`, + { wholeCycle: '1s', connectionAndInactivity: '500ms' }, + 1024 * 1024, + null, + false, + null, + null + )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|timeout of 500ms exceeded)/); + }); + + test('throws error on wholeCycle timeout', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/timeout`, + { wholeCycle: '1s', connectionAndInactivity: '5000ms' }, + 1024 * 1024, + null, + false, + null, + null + )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|ETIMEDOUT: 1s|whole request cycle timeout: 1s)/); + }); + + test('follows redirects correctly', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/redirect`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + }); + + test(`doesn't follow redirects(maxRedirects=0)`, async () => { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, + "decompress": true, + "rejectUnauthorized": false, + "followRedirect": true, + "maxRedirects": 0 + }, + }); + + try { + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/redirect`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // Old implementation path + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(302); + } catch (error) { + // New implementation path (Axios) + expect(error.message).toMatch(/(?:Request failed with status code 302|Error response: statusCode:302)/); + } + }); + + test(`doesn't follow redirects(followRedirect=false)`, async () => { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, + "decompress": true, + "rejectUnauthorized": false, + "followRedirect": false, + "maxRedirects": 100 + }, + }); + + try { + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/redirect`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // Old implementation path + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(302); + } catch (error) { + // New implementation path (Axios) + expect(error.message).toMatch(/(?:Request failed with status code 302|Error response: statusCode:302)/); + } + }); + + test('throws error on server error', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/error`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + )).rejects.toThrow(/(?:Error response: statusCode:500|Request failed with status code 500)/); + }); + + test('throws error when content-length exceeds limit', async () => { + await expect(utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/large`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + )).rejects.toThrow('Error response: content-length:2097152'); + }); + }); + + test('handles binary data correctly', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/binary`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // Expected binary data (PNG file signature) + const expectedData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); + + expect(result).toBeDefined(); + expect(result.response).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(result.response.headers['content-type']).toBe('image/png'); + + // Verify binary data + expect(Buffer.isBuffer(result.body)).toBe(true); + expect(result.body.length).toBe(expectedData.length); + expect(Buffer.compare(result.body, expectedData)).toBe(0); + }); + + test('handles binary data with stream writer', async () => { + const chunks = []; + const mockStreamWriter = new Writable({ + write(chunk, encoding, callback) { + chunks.push(chunk); + callback(); + } + }); + + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/binary`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + mockStreamWriter + ); + + // Combine chunks and verify + const receivedData = Buffer.concat(chunks); + const expectedData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); + + expect(Buffer.isBuffer(receivedData)).toBe(true); + expect(receivedData.length).toBe(expectedData.length); + expect(Buffer.compare(receivedData, expectedData)).toBe(0); + }); + + test('block external requests', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": false, // Block all external requests + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + } + }); + + await expect(utils.downloadUrlPromise( + mockCtx, + 'https://example.com/test', + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + )).rejects.toThrow('Block external request. See externalRequest config options'); + }); + + test('allows request to external url in allowlist', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": false, // Block external requests by default + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + }, + 'externalRequest.directIfIn': { + "allowList": [`${BASE_URL}`], // Allow our test server + "jwtToken": false + } + }); + + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/data`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + }); + + test('allows request when URL is in JWT token', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": false, // Block external requests by default + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + }, + 'externalRequest.directIfIn': { + "allowList": [], // Empty allowlist + "jwtToken": true // Allow URLs from JWT token + } + }); + + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/data`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + true, // Indicate URL is from JWT token + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + }); + + test('request with proxy configuration', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": true, + "blockPrivateIP": true, + "proxyUrl": "http://proxy.example.com:8080", + "proxyUser": { + "username": "testuser", + "password": "testpass" + }, + "proxyHeaders": { + "X-Custom-Header": "test-value" + } + } + }); + + try { + await utils.downloadUrlPromise( + mockCtx, + 'https://example.com/test', + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + fail('Expected request to fail'); + } catch (error) { + // Different error structures between implementations + const headers = error.config?.headers || error.request?._headers || error._headers; + if (headers) { + expect(headers).toEqual( + expect.objectContaining({ + 'proxy-authorization': expect.stringContaining('testuser:testpass'), + 'X-Custom-Header': 'test-value' + }) + ); + } + // If headers aren't available, at least verify the error occurred + expect(error).toBeDefined(); + } + }); + + describe('postRequestPromise', () => { + test('successfully posts data', async () => { + const postData = JSON.stringify({ test: 'data' }); + + const result = await utils.postRequestPromise( + ctx, + `${BASE_URL}/api/post`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); + }); + + test('handles timeout during post', async () => { + const postData = JSON.stringify({ test: 'data' }); + + await expect(utils.postRequestPromise( + ctx, + `${BASE_URL}/api/timeout`, + postData, + null, + postData.length, + { wholeCycle: '1s', connectionAndInactivity: '500ms' }, + null, + false, + { 'Content-Type': 'application/json' } + )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|timeout of 500ms exceeded)/); + }); + + test('handles post with Authorization header', async () => { + const postData = JSON.stringify({ test: 'data' }); + const authToken = 'test-auth-token'; + + const result = await utils.postRequestPromise( + ctx, + `${BASE_URL}/api/post`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + authToken, + false, + { 'Content-Type': 'application/json' } + ); + + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); + }); + + test('handles post with custom headers', async () => { + const postData = JSON.stringify({ test: 'data' }); + const customHeaders = { + 'X-Custom-Header': 'test-value', + 'Content-Type': 'application/json' + }; + + const result = await utils.postRequestPromise( + ctx, + `${BASE_URL}/api/post`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + customHeaders + ); + + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); + }); + + test('handles post with stream data', async () => { + const postData = JSON.stringify({ test: 'stream-data' }); + const postStream = new Readable({ + read() { + this.push(postData); + this.push(null); + } + }); + + const result = await utils.postRequestPromise( + ctx, + `${BASE_URL}/api/post`, + null, + postStream, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(JSON.parse(result.body)).toEqual({ received: { test: 'stream-data' } }); + }); + + test('throws error on wholeCycle timeout during post', async () => { + const postData = JSON.stringify({ test: 'data' }); + + await expect(utils.postRequestPromise( + ctx, + `${BASE_URL}/api/timeout`, + postData, + null, + postData.length, + { wholeCycle: '1s', connectionAndInactivity: '5s' }, + null, + false, + { 'Content-Type': 'application/json' } + )).rejects.toThrow(/(?:ETIMEDOUT|ESOCKETTIMEDOUT|whole request cycle timeout: 1s|Whole request cycle timeout: 1s)/); + }); + + test('blocks external post requests when configured', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": false, + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + } + }); + + const postData = JSON.stringify({ test: 'data' }); + + await expect(utils.postRequestPromise( + mockCtx, + 'https://example.com/api/post', + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + { 'Content-Type': 'application/json' } + )).rejects.toThrow('Block external request. See externalRequest config options'); + }); + + test('allows post request when URL is in JWT token', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": false, + "blockPrivateIP": false, + "proxyUrl": "", + "proxyUser": { + "username": "", + "password": "" + }, + "proxyHeaders": {} + }, + 'externalRequest.directIfIn': { + "allowList": [], + "jwtToken": true + } + }); + + const postData = JSON.stringify({ test: 'data' }); + + const result = await utils.postRequestPromise( + mockCtx, + `${BASE_URL}/api/post`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + true, // Indicate URL is from JWT token + { 'Content-Type': 'application/json' } + ); + + expect(result).toBeDefined(); + expect(result.response.statusCode).toBe(200); + expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); + }); + + test('handles post with proxy configuration', async () => { + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": true, + "blockPrivateIP": true, + "proxyUrl": "http://proxy.example.com:8080", + "proxyUser": { + "username": "testuser", + "password": "testpass" + }, + "proxyHeaders": { + "X-Custom-Proxy-Header": "test-value" + } + } + }); + + const postData = JSON.stringify({ test: 'data' }); + + try { + await utils.postRequestPromise( + mockCtx, + 'https://example.com/api/post', + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + fail('Expected request to fail'); + } catch (error) { + // Different error structures between implementations + const headers = error.config?.headers || error.request?._headers || error._headers; + if (headers) { + expect(headers).toEqual( + expect.objectContaining({ + 'proxy-authorization': expect.stringContaining('testuser:testpass'), + 'X-Custom-Proxy-Header': 'test-value', + 'Content-Type': 'application/json' + }) + ); + } + // If headers aren't available, at least verify the error occurred + expect(error).toBeDefined(); + } + }); + }); +}); \ No newline at end of file diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js deleted file mode 100644 index 31948c43..00000000 --- a/tests/unit/request.tests.js +++ /dev/null @@ -1,718 +0,0 @@ -// Required modules -const { describe, test, expect, beforeEach, afterAll, jest } = require('@jest/globals'); -const { Readable, Writable } = require('stream'); -// Setup mocks for axios -const axiosReal = require('axios'); -jest.mock('axios'); -const axios = require('axios'); -const operationContext = require('../../Common/sources/operationContext'); -const utils = require('../../Common/sources/utils'); - -// Assign real CancelToken from the imported axiosReal to the mocked axios -axios.CancelToken = axiosReal.CancelToken; -axios.CancelToken.source = axiosReal.CancelToken.source; - -// Create operation context for tests -const ctx = new operationContext.Context(); - -// Helper functions for creating test streams -const createMockStream = (data) => { - // Convert string to Buffer if it's not already a buffer - const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data || JSON.stringify({ success: true }), 'utf8'); - // Create a Readable stream from buffer data - return Readable.from(bufferData); -}; - -const createMockWriter = () => { - const chunks = []; - return new Writable({ - write(chunk, encoding, callback) { - chunks.push(chunk); - callback(); - } - }); -}; - -// Common test parameters -const commonTestParams = { - uri: 'https://example.com/api/data', - timeout: { wholeCycle: '500ms', connectionAndInactivity: '200s' }, - limit: 1024 * 1024, // 1MB - authorization: 'token123', - filterPrivate: true, - headers: { 'Accept': 'application/json' } -}; - -// Creates common parameter assertion -const createParamAssertion = (uri) => { - return expect.objectContaining({ - url: uri || commonTestParams.uri, - timeout: commonTestParams.timeout, - maxContentLength: commonTestParams.limit, - responseType: 'stream', - headers: expect.objectContaining({ - 'Accept': 'application/json', - 'Authorization': commonTestParams.authorization - }) - }); -}; - -describe('HTTP Request Functionality', () => { - beforeEach(() => { - // Reset all mocks before each test - jest.clearAllMocks(); - }); - - afterAll(() => { - // Clean up all mocks - jest.restoreAllMocks(); - }); - - describe('downloadUrlPromise', () => { - test('properly handles content streaming', async () => { - // Create mock data - const mockData = 'Sample data content'; - - // Mock successful response with stream - const mockResponse = { - status: 200, - headers: { - 'content-type': 'text/plain', - 'content-length': String(Buffer.byteLength(mockData, 'utf8')) - }, - data: createMockStream(mockData) - }; - - // Setup axios mock - axios() is used directly in the code, not axios.get() - axios.mockImplementation((config) => { - console.log('Mock axios called with config:', JSON.stringify(config, null, 2)); - return Promise.resolve(mockResponse); - }); - - // Create a proper writable stream for testing - const mockStreamWriter = createMockWriter(); - - // Test version with stream writer (returns undefined) - const resultWithStreamWriter = await utils.downloadUrlPromise( - ctx, - 'https://example.com/file', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - mockStreamWriter - ); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - - // With stream writer, the function returns undefined - expect(resultWithStreamWriter).toBeUndefined(); - }); - - test('returns complete response without stream writer', async () => { - // Create mock data - const mockData = JSON.stringify({ data: 'test content' }); - - // Mock successful response with stream - const mockResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(mockData, 'utf8')) - }, - data: createMockStream(mockData) - }; - - // Reset mocks and setup new behavior - jest.clearAllMocks(); - axios.mockImplementation(() => Promise.resolve(mockResponse)); - - // Call function without stream writer - const result = await utils.downloadUrlPromise( - ctx, - 'https://example.com/data', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null // No stream writer - ); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - - // Verify full response object is returned - expect(result).toBeDefined(); - expect(result).toHaveProperty('response', mockResponse); - expect(result).toHaveProperty('sha256'); - expect(result).toHaveProperty('body'); - expect(result.sha256).toMatch(/^[a-f0-9]{64}$/i); - expect(Buffer.isBuffer(result.body)).toBe(true); - }); - - test('throws error on non-200 status codes', async () => { - // Create error data - const errorData = JSON.stringify({ error: 'Not found' }); - - // Mock error response with stream - const mockErrorResponse = { - status: 404, - statusText: 'Not Found', - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(errorData, 'utf8')) - }, - data: createMockStream(errorData) - }; - - // Reset mocks and setup new behavior for error - jest.clearAllMocks(); - axios.mockImplementation(() => Promise.resolve(mockErrorResponse)); - - // Call function and expect it to throw - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/not-found', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - )).rejects.toThrow(/Error response: statusCode:404/); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - - test('throws error when content-length exceeds limit', async () => { - // Create large data (but mock only returns the header) - const mockResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': '2097152' // 2MB (greater than 1MB limit) - }, - data: createMockStream('{}') // actual data is irrelevant, header check happens first - }; - - // Reset mocks and setup new behavior - jest.clearAllMocks(); - axios.mockImplementation(() => Promise.resolve(mockResponse)); - - // Call function with a 1MB limit and expect it to throw - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/large-file', - commonTestParams.timeout, - 1024 * 1024, // 1MB limit - null, - false, - null, - null - )).rejects.toThrow(/EMSGSIZE: Error response: content-length/); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - - test('follows redirects correctly', async () => { - // Create a counter to track calls - let callCount = 0; - - // Mock redirect response - const redirectResponse = { - status: 302, - headers: { - location: 'https://example.com/redirected' - } - }; - - // Mock success response after redirect - const successData = JSON.stringify({ success: true }); - const successResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(successData, 'utf8')) - }, - data: createMockStream(successData) - }; - - // Reset mocks and implement redirect then success - jest.clearAllMocks(); - axios.mockImplementation(() => { - if (callCount === 0) { - callCount++; - // First call - simulate redirect by throwing error with response - const err = new Error('Redirect'); - err.response = redirectResponse; - return Promise.reject(err); - } else { - // Second call - return success - return Promise.resolve(successResponse); - } - }); - - // Call function with original URL - const result = await utils.downloadUrlPromise( - ctx, - 'https://example.com/original', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - ); - - // Verify axios was called twice (once for original, once for redirect) - expect(axios).toHaveBeenCalledTimes(2); - - // Verify the result is from the successful redirect - expect(result).toBeDefined(); - expect(result).toHaveProperty('response'); - expect(result).toHaveProperty('sha256'); - expect(result.response.status).toBe(200); - }); - - test('handles network errors correctly', async () => { - // Reset mocks and implement network error - jest.clearAllMocks(); - axios.mockImplementation(() => { - const err = new Error('Network Error'); - return Promise.reject(err); - }); - - // Call function and expect network error - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/network-error', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - )).rejects.toThrow('Network Error'); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - - test('handles binary data correctly', async () => { - // Create binary data (simple buffer with pattern of bytes) - const binaryData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); // PNG file signature - - // Mock successful response with binary stream - const mockResponse = { - status: 200, - headers: { - 'content-type': 'image/png', - 'content-length': String(binaryData.length) - }, - data: createMockStream(binaryData) - }; - - // Reset mocks and setup for binary data - jest.clearAllMocks(); - axios.mockImplementation(() => Promise.resolve(mockResponse)); - - // Call function without stream writer - const result = await utils.downloadUrlPromise( - ctx, - 'https://example.com/image.png', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - ); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - - // Verify binary data is preserved correctly - expect(result).toBeDefined(); - expect(result).toHaveProperty('body'); - expect(Buffer.isBuffer(result.body)).toBe(true); - expect(result.body.length).toBe(binaryData.length); - // Verify the content matches the original binary data - expect(Buffer.compare(result.body, binaryData)).toBe(0); - }); - - test('handles timeout correctly', async () => { - jest.useFakeTimers(); - // Mock a never-resolving request - axios.mockImplementation((config) => { - return new Promise((_, reject) => { - if (config.cancelToken) { - config.cancelToken.promise.then(cancel => { - reject(new axiosReal.Cancel(cancel.message)); - }); - } - }); - }); - - const promise = utils.downloadUrlPromise( - ctx, - 'https://example.com/timeout-test', - { wholeCycle: '500ms', connectionAndInactivity: '200s' }, - 1024, - null, - false, - null, - null - ); - - // Fast-forward exactly 1 second - jest.advanceTimersByTime(1000); - await Promise.resolve(); // Flush pending promises - - await expect(promise).rejects.toThrow('ETIMEDOUT: 500ms'); - - jest.useRealTimers(); - }); - - test('throws an error on max redirects limit reached', async () => { - // Create a counter to track calls - let callCount = 0; - - // Mock redirect response - const redirectResponse = { - status: 302, - headers: { - location: 'https://example.com/redirected' - } - }; - - // Mock success response after redirect - const successData = JSON.stringify({ success: true }); - const successResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(successData, 'utf8')) - }, - data: createMockStream(successData) - }; - - // Reset mocks and implement redirect then success - jest.clearAllMocks(); - axios.mockImplementation(() => { - if (callCount < 12) { - callCount++; - // First call - simulate redirect by throwing error with response - const err = new Error('Redirect'); - err.response = redirectResponse; - return Promise.reject(err); - } else { - // Second call - return success - return Promise.resolve(successResponse); - } - }); - - // Call function with original URL - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/original', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - )).rejects.toThrow('Redirect'); - - expect(axios).toHaveBeenCalledTimes(11); - }); - - test('should block external request', async () => { - - const addExternalRequestOptionsMock = jest.spyOn(utils, 'addExternalRequestOptions'); - - addExternalRequestOptionsMock.mockReturnValue(false); - - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/original', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - )).rejects.toThrow('Block external request. See externalRequest config options'); - - addExternalRequestOptionsMock.mockRestore(); - }); - - test('should throw error on redirect with followRedirect=false', async () => { - let callCount = 0; - - // Mock redirect response - const redirectResponse = { - status: 302, - headers: { - location: 'https://example.com/redirected' - } - }; - - // Mock success response after redirect - const successData = JSON.stringify({ success: true }); - const successResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(successData, 'utf8')) - }, - data: createMockStream(successData) - }; - - // Reset mocks and implement redirect then success - jest.clearAllMocks(); - axios.mockImplementation(() => { - if (callCount < 2) { - callCount++; - // First call - simulate redirect by throwing error with response - const err = new Error('Redirect'); - err.response = redirectResponse; - return Promise.reject(err); - } else { - // Second call - return success - return Promise.resolve(successResponse); - } - }); - - const ctx = { - getCfg: function(key, _) { - switch (key) { - case 'services.CoAuthoring.requestDefaults': - return { - "headers": { - "User-Agent": "Node.js/6.13", - "Connection": "Keep-Alive" - }, - "decompress": true, - "rejectUnauthorized": true, - "followRedirect": false - } - case 'services.CoAuthoring.token.outbox.header': - return "Authorization"; - case 'services.CoAuthoring.token.outbox.prefix': - return "Bearer "; - case 'externalRequest.action': - return { - "allow": true, - "blockPrivateIP": true, - "proxyUrl": "", - "proxyUser": { - "username": "", - "password": "" - }, - "proxyHeaders": { - } - }; - case 'services.CoAuthoring.request-filtering-agent': - return { - "allowPrivateIPAddress": false, - "allowMetaIPAddress": false - } - case 'externalRequest.directIfIn': - return { - "allowList": [], - "jwtToken": true - } - } - }, - logger: { - debug: function() {}, - } - } - - await expect(utils.downloadUrlPromise( - ctx, - 'https://example.com/original', - commonTestParams.timeout, - commonTestParams.limit, - null, - false, - null, - null - )).rejects.toThrow('Redirect'); - }); - }); - - describe('postRequestPromise', () => { - test('properly sends post data and returns response', async () => { - // Mock successful response - const mockData = { success: true }; - const mockResponse = { - status: 200, - headers: { 'content-type': 'application/json' }, - data: mockData - }; - - // Setup axios mock - axios.mockImplementation(() => Promise.resolve(mockResponse)); - - // Call the function - const result = await utils.postRequestPromise( - ctx, - 'https://example.com/data', - { key: 'value' }, - null, - null, - commonTestParams.timeout, - commonTestParams.authorization, - false, - null - ); - - // Verify axios was called with the correct configuration - expect(axios).toHaveBeenCalledWith(expect.objectContaining({ - method: 'post', - url: 'https://example.com/data', - data: { key: 'value' }, - validateStatus: expect.any(Function), - timeout: expect.any(Number), - })); - - expect(result).toBeDefined(); - expect(result).toHaveProperty('response'); - expect(result.response.statusCode).toBe(200); - expect(result.response.body).toBe(mockData); - }); - - - test('handles timeout and cancels request', async () => { - // Mock cancellation - const cancelMessage = 'Whole request cycle timeout: 500ms'; - axios.mockImplementation(() => { - const error = new Error(cancelMessage); - error.code = 'ETIMEDOUT'; - throw error; - }); - - // Call function and expect it to throw ETIMEDOUT error - await expect(utils.postRequestPromise( - ctx, - 'https://example.com/data', - { key: 'value' }, - null, - null, - commonTestParams.timeout, - commonTestParams.authorization, - false, - null - )).rejects.toThrowError(cancelMessage); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - - test('throws error for non-200 status codes', async () => { - // Create mock error data - const errorData = JSON.stringify({ error: 'Not found' }); - const mockErrorResponse = { - status: 404, - statusText: 'Not Found', - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(errorData, 'utf8')) - }, - data: errorData - }; - - // Setup axios mock - axios.mockImplementation(() => Promise.reject({ response: mockErrorResponse })); - - // Call function and expect it to throw error - await expect(utils.postRequestPromise( - ctx, - 'https://example.com/not-found', - { key: 'value' }, - null, - null, - commonTestParams.timeout, - commonTestParams.authorization, - false, - null - )).rejects.toThrowError(/Error response: statusCode:404/); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - - test('handles post data stream correctly', async () => { - // Mock successful response with stream - const mockData = 'Sample streamed content'; - const mockResponse = { - status: 200, - headers: { - 'content-type': 'application/json', - 'content-length': String(Buffer.byteLength(mockData, 'utf8')) - }, - data: mockData - }; - - // Setup axios mock - axios.mockImplementation(() => Promise.resolve(mockResponse)); - - // Call the function with postDataStream - const result = await utils.postRequestPromise( - ctx, - 'https://example.com/upload', - null, - mockData, - null, - commonTestParams.timeout, - commonTestParams.authorization, - false, - null - ); - - expect(axios).toHaveBeenCalledWith(expect.objectContaining({ - method: 'post', - url: 'https://example.com/upload', - headers: expect.objectContaining({ - 'Authorization': 'Bearer token123' - }), - data: mockData, - validateStatus: expect.any(Function), - timeout: expect.any(Number), - })); - - // Verify result - expect(result).toBeDefined(); - expect(result.response.statusCode).toBe(200); - expect(result.response.body).toBe(mockData); - }); - - test('handles network errors correctly', async () => { - // Mock network error - const networkError = new Error('Network Error'); - axios.mockImplementation(() => Promise.reject(networkError)); - - // Call function and expect it to throw network error - await expect(utils.postRequestPromise( - ctx, - 'https://example.com/network-error', - { key: 'value' }, - null, - null, - commonTestParams.timeout, - commonTestParams.authorization, - false, - null - )).rejects.toThrowError('Network Error'); - - // Verify axios was called - expect(axios).toHaveBeenCalledTimes(1); - }); - }) -}); \ No newline at end of file From 37b2b61cc73711b5edfb361213382a9f0c85de27 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Thu, 3 Apr 2025 17:36:14 +0300 Subject: [PATCH 08/17] [feature] Add requestDefault parameters --- Common/config/default.json | 4 +- Common/sources/utils.js | 25 ++ .../withServerInstance/request.tests.js | 277 +++++++++++++++++- 3 files changed, 303 insertions(+), 3 deletions(-) diff --git a/Common/config/default.json b/Common/config/default.json index 29bea340..7597e968 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -320,8 +320,8 @@ "User-Agent": "Node.js/6.13", "Connection": "Keep-Alive" }, - "decompress": true, - "rejectUnauthorized": true + "gzip": true, + "rejectUnauthorized": true }, "autoAssembly": { "enable": false, diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 85848393..a55440ec 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -296,6 +296,7 @@ function isAllowDirectRequest(ctx, uri, isInJwtToken) { } function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { let res = false; + const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenExternalRequestAction = ctx.getCfg('externalRequest.action', cfgExternalRequestAction); const tenRequestFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); if (isAllowDirectRequest(ctx, uri, isInJwtToken)) { @@ -316,6 +317,10 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { agentOptions.port = parsedProxyUrl.port; agentOptions.protocol = parsedProxyUrl.protocol; } + + if (tenTenantRequestDefaults.forever !== undefined) { + agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; + } if (uri.startsWith('https:')) { options.httpsAgent = new RequestFilteringHttpsAgent(agentOptions); @@ -348,6 +353,11 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat uri = URI.serialize(URI.parse(uri)); const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; const options = config.util.cloneDeep(tenTenantRequestDefaults); + if (options.gzip !== undefined && !options.gzip) { + options.headers = options.headers || {}; + options.headers['Accept-Encoding'] = 'identity'; + delete options.gzip; + } if (!exports.addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { throw new Error('Block external request. See externalRequest config options'); } @@ -355,6 +365,9 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat const protocol = new URL(uri).protocol; if (!options.httpsAgent && !options.httpAgent) { const agentOptions = { ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false? false : true}; + if (tenTenantRequestDefaults.forever !== undefined) { + agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; + } if (protocol === 'https:') { options.httpsAgent = new https.Agent(agentOptions); } else if (protocol === 'http:') { @@ -536,6 +549,13 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi timeout: connectionAndInactivity, validateStatus: (status) => status === 200 || status === 204 }); + + if (options.gzip !== undefined && !options.gzip) { + options.headers = options.headers || {}; + options.headers['Accept-Encoding'] = 'identity'; + delete options.gzip; + } + if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { throw new Error('Block external request. See externalRequest config options'); } @@ -545,6 +565,11 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false ? false : true }; + + if (tenTenantRequestDefaults.forever !== undefined) { + agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; + } + if (protocol === 'https:') { options.httpsAgent = new https.Agent(agentOptions); } else if (protocol === 'http:') { diff --git a/tests/integration/withServerInstance/request.tests.js b/tests/integration/withServerInstance/request.tests.js index 179e2f54..0ff42804 100644 --- a/tests/integration/withServerInstance/request.tests.js +++ b/tests/integration/withServerInstance/request.tests.js @@ -152,6 +152,35 @@ describe('HTTP Request Integration Tests', () => { const buffer = Buffer.alloc(2097152); res.send(buffer); }); + app.get('/api/headers', (req, res) => { + // Ensure you're only sending headers, which won't contain circular references + res.json({ headers: req.headers }); + }); + + // Endpoint that returns connection header info + app.get('/api/connection', (req, res) => { + res.json({ + connection: req.headers.connection, + keepAlive: req.headers.connection?.toLowerCase() === 'keep-alive' + }); + }); + + // Endpoint that returns only the accept-encoding header + app.get('/api/accept-encoding', (req, res) => { + res.json({ + acceptEncoding: req.headers['accept-encoding'] || null + }); + }); + + // Endpoint that returns only the connection header + app.get('/api/connection-header', (req, res) => { + const connectionHeader = req.headers['connection'] || ''; + res.json({ + connection: connectionHeader, + keepAlive: connectionHeader.toLowerCase() === 'keep-alive' + }); + }); + // Start server server = http.createServer(app); @@ -336,6 +365,163 @@ describe('HTTP Request Integration Tests', () => { null )).rejects.toThrow('Error response: content-length:2097152'); }); + + test('enables compression when gzip is true', async () => { + // Setup a simple server that captures headers + let capturedHeaders = {}; + const app = express(); + app.get('/test', (req, res) => { + capturedHeaders = { + acceptEncoding: req.headers['accept-encoding'] + }; + res.json({ success: true }); + }); + + const testServer = http.createServer(app); + const testPort = PORT + 1000; + await new Promise(resolve => testServer.listen(testPort, resolve)); + + try { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { "User-Agent": "Node.js/6.13" }, + gzip: true, + rejectUnauthorized: false + } + }); + + await utils.downloadUrlPromise( + mockCtx, + `http://localhost:${testPort}/test`, + { wholeCycle: '2s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // When gzip is true, 'accept-encoding' should include 'gzip' + expect(capturedHeaders.acceptEncoding).toBeDefined(); + expect(capturedHeaders.acceptEncoding).toMatch(/gzip/i); + } finally { + await new Promise(resolve => testServer.close(resolve)); + } + }); + + test('disables compression when gzip is false', async () => { + // Setup a simple server that captures headers + let capturedHeaders = {}; + const app = express(); + app.get('/test', (req, res) => { + capturedHeaders = { + acceptEncoding: req.headers['accept-encoding'] + }; + res.json({ success: true }); + }); + + const testServer = http.createServer(app); + const testPort = PORT + 1001; + await new Promise(resolve => testServer.listen(testPort, resolve)); + + try { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { "User-Agent": "Node.js/6.13" }, + gzip: false, + rejectUnauthorized: false + } + }); + + await utils.downloadUrlPromise( + mockCtx, + `http://localhost:${testPort}/test`, + { wholeCycle: '2s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(capturedHeaders.acceptEncoding === 'identity' || capturedHeaders.acceptEncoding === undefined).toBe(true); + } finally { + await new Promise(resolve => testServer.close(resolve)); + } + }); + + test('enables keep-alive when forever is true', async () => { + // Setup a simple server that captures headers + let capturedHeaders = {}; + const app = express(); + app.get('/test', (req, res) => { + capturedHeaders = { + connection: req.headers['connection'] + }; + res.json({ success: true }); + }); + + const testServer = http.createServer(app); + const testPort = PORT + 1002; + await new Promise(resolve => testServer.listen(testPort, resolve)); + + try { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { "User-Agent": "Node.js/6.13" }, + forever: true, + rejectUnauthorized: false + } + }); + + await utils.downloadUrlPromise( + mockCtx, + `http://localhost:${testPort}/test`, + { wholeCycle: '2s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // When forever is true, connection should be 'keep-alive' + expect(capturedHeaders.connection?.toLowerCase()).toMatch(/keep-alive/i); + } finally { + await new Promise(resolve => testServer.close(resolve)); + } + }); + + test('disables keep-alive when forever is false', async () => { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { + "User-Agent": "Node.js/6.13" + }, + forever: false, + rejectUnauthorized: false + } + }); + + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/connection-header`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + const responseData = JSON.parse(result.body.toString()); + + // When forever is false, connection should NOT be 'keep-alive' + // Note: Different HTTP clients might handle this differently, + // so we're checking that keepAlive is false + expect(responseData.keepAlive).toBe(false); + }); }); test('handles binary data correctly', async () => { @@ -768,5 +954,94 @@ describe('HTTP Request Integration Tests', () => { expect(error).toBeDefined(); } }); + + test('applies gzip setting to POST requests', async () => { + // Setup a simple server that captures headers + let capturedHeaders = {}; + const app = express(); + app.post('/test', express.json(), (req, res) => { + capturedHeaders = { + acceptEncoding: req.headers['accept-encoding'] + }; + res.json({ success: true }); + }); + + const testServer = http.createServer(app); + const testPort = PORT + 1003; + await new Promise(resolve => testServer.listen(testPort, resolve)); + + try { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { "User-Agent": "Node.js/6.13" }, + gzip: false, + rejectUnauthorized: false + } + }); + + const postData = JSON.stringify({ test: 'data' }); + + await utils.postRequestPromise( + mockCtx, + `http://localhost:${testPort}/test`, + postData, + null, + postData.length, + { wholeCycle: '2s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + + expect(capturedHeaders.acceptEncoding === 'identity' || capturedHeaders.acceptEncoding === undefined).toBe(true); + } finally { + await new Promise(resolve => testServer.close(resolve)); + } + }); + + test('applies forever setting to POST requests', async () => { + // Setup a simple server that captures headers + let capturedHeaders = {}; + const app = express(); + app.post('/test', express.json(), (req, res) => { + capturedHeaders = { + connection: req.headers['connection'] + }; + res.json({ success: true }); + }); + + const testServer = http.createServer(app); + const testPort = PORT + 1004; + await new Promise(resolve => testServer.listen(testPort, resolve)); + + try { + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: { "User-Agent": "Node.js/6.13" }, + forever: true, + rejectUnauthorized: false + } + }); + + const postData = JSON.stringify({ test: 'data' }); + + await utils.postRequestPromise( + mockCtx, + `http://localhost:${testPort}/test`, + postData, + null, + postData.length, + { wholeCycle: '2s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + + // When forever is true, connection should be 'keep-alive' + expect(capturedHeaders.connection?.toLowerCase()).toMatch(/keep-alive/i); + } finally { + await new Promise(resolve => testServer.close(resolve)); + } + }); }); -}); \ No newline at end of file +}); From d08820469aa4dda4a7eaf24ef5cde4acfb4fbdaf Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Mon, 14 Apr 2025 17:41:56 +0300 Subject: [PATCH 09/17] [feature] Refactor downloadUrlPromise --- Common/config/default.json | 11 +- Common/sources/utils.js | 234 ++++++++++------- DocService/sources/canvasservice.js | 11 +- .../withServerInstance/request.tests.js | 248 ++++++++++++------ 4 files changed, 318 insertions(+), 186 deletions(-) diff --git a/Common/config/default.json b/Common/config/default.json index 7597e968..6462e77c 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -316,13 +316,12 @@ "forceSaveUsingButtonWithoutChanges": false }, "requestDefaults": { - "headers": { - "User-Agent": "Node.js/6.13", - "Connection": "Keep-Alive" - }, - "gzip": true, + "headers": { + "User-Agent": "Node.js/6.13", + "Connection": "Keep-Alive" + }, "rejectUnauthorized": true - }, + }, "autoAssembly": { "enable": false, "interval": "5m", diff --git a/Common/sources/utils.js b/Common/sources/utils.js index a55440ec..6e1ed5ab 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -36,6 +36,8 @@ require("tls").DEFAULT_ECDH_CURVE = "auto"; const { pipeline } = require('node:stream/promises'); +const { buffer } = require('node:stream/consumers'); +const { Transform } = require('stream'); var config = require('config'); var fs = require('fs'); var path = require('path'); @@ -108,10 +110,6 @@ function getIpFilterRule(address) { } const pemfileCache = new NodeCache({stdTTL: ms(cfgExpPemStdTtl) / 1000, checkperiod: ms(cfgExpPemCheckPeriod) / 1000, errorOnMissing: false, useClones: true}); -function getRequestFilterAgent(url, options) { - return url.startsWith("https") ? new RequestFilteringHttpsAgent(options) : new RequestFilteringHttpAgent(options); -} - exports.getConvertionTimeout = function(opt_ctx) { if (opt_ctx) { const tenVisibilityTimeout = opt_ctx.getCfg('queue.visibilityTimeout', cfgVisibilityTimeout); @@ -275,7 +273,8 @@ function raiseErrorObj(ro, error) { ro.emit('error', error); } function isRedirectResponse(response) { - return response && response.status >= 300 && response.status < 400 && Object.keys(response.headers).some(key => key.toLowerCase() === 'location'); + //All header names are lower cased and can be accessed using the bracket notation. + return response && response.status >= 300 && response.status < 400 && !!response.headers['location']; } function isAllowDirectRequest(ctx, uri, isInJwtToken) { @@ -294,9 +293,8 @@ function isAllowDirectRequest(ctx, uri, isInJwtToken) { } return res; } -function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { +function addExternalRequestOptions(ctx, uri, isInJwtToken, options, httpAgentOptions, httpsAgentOptions) { let res = false; - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenExternalRequestAction = ctx.getCfg('externalRequest.action', cfgExternalRequestAction); const tenRequestFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); if (isAllowDirectRequest(ctx, uri, isInJwtToken)) { @@ -304,34 +302,28 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { } else if (tenExternalRequestAction.allow) { res = true; if (tenExternalRequestAction.blockPrivateIP) { - const agentOptions = { - ...https.globalAgent.options, + options.httpsAgent = new RequestFilteringHttpsAgent({ + ...httpsAgentOptions, ...tenRequestFilteringAgent - }; - - if (tenExternalRequestAction.proxyUrl) { - const proxyUrl = tenExternalRequestAction.proxyUrl; - const parsedProxyUrl = url.parse(proxyUrl); - - agentOptions.host = parsedProxyUrl.hostname; - agentOptions.port = parsedProxyUrl.port; - agentOptions.protocol = parsedProxyUrl.protocol; - } - - if (tenTenantRequestDefaults.forever !== undefined) { - agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; - } - - if (uri.startsWith('https:')) { - options.httpsAgent = new RequestFilteringHttpsAgent(agentOptions); - } else { - options.httpAgent = new RequestFilteringHttpAgent(agentOptions); - } + }); + options.httpAgent = new RequestFilteringHttpAgent({ + ...httpAgentOptions, + ...tenRequestFilteringAgent + }); } + if (tenExternalRequestAction.proxyUrl) { + const proxyUrl = tenExternalRequestAction.proxyUrl; + const parsedProxyUrl = url.parse(proxyUrl); + + options.proxy.host = parsedProxyUrl.hostname; + options.proxy.port = parsedProxyUrl.port; + options.proxy.protocol = parsedProxyUrl.protocol; + } + if (tenExternalRequestAction.proxyUser?.username) { - const user = tenExternalRequestAction.proxyUser.username; - const pass = tenExternalRequestAction.proxyUser.password || ''; - options.headers['proxy-authorization'] = `${user}:${pass}`; + //This will set an `Proxy-Authorization` header, overwriting any existing + //`Proxy-Authorization` custom headers you have set using `headers`. + options.proxy.auth = tenExternalRequestAction.proxyUser; } if (tenExternalRequestAction.proxyHeaders) { options.headers = { @@ -342,37 +334,59 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options) { } return res; } - -async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) { +/* + * @param {object} options - The options object to modify. + */ +function changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions) { + if (false === options.followRedirect) { + options.maxRedirects = 0; + } + if (false === options.gzip) { + options.headers = { ...options.headers, 'Accept-Encoding': 'identity' }; + delete options.gzip; + } + if (options.forever !== undefined) { + httpAgentOptions.keepAlive = !!options.forever; + httpsAgentOptions.keepAlive = !!options.forever; + } +} +/* + * Download a URL and return the response. + * @param {operationContext.Context} ctx - The operation context. + * @param {string} uri - The URL to download. + * @param {object} optTimeout - Optional timeout configuration. + * @param {number} optLimit - Optional limit on the size of the response. + * @param {string} opt_Authorization - Optional authorization header. + * @param {boolean} opt_filterPrivate - Optional flag to filter private requests. + * @param {object} opt_headers - Optional headers to include in the request. + * @param {boolean} opt_returnStream - Optional flag to return stream. + * @returns {Promise<{response: axios.AxiosResponse, sha256: string|null, body: Buffer|null, stream: NodeJS.ReadableStream|null}>} - A promise that resolves to object containing response, sha256 hash, and body (null if opt_streamWriter is provided). + */ +async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_returnStream) { const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - const maxRedirects = (undefined !== tenTenantRequestDefaults.maxRedirects) ? tenTenantRequestDefaults.maxRedirects : 10; - const followRedirect = (undefined !== tenTenantRequestDefaults.followRedirect) ? tenTenantRequestDefaults.followRedirect : true; - const sizeLimit = optLimit || Number.MAX_VALUE; + let sizeLimit = optLimit || Number.MAX_VALUE; uri = URI.serialize(URI.parse(uri)); - const connectionAndInactivity = optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined; const options = config.util.cloneDeep(tenTenantRequestDefaults); - if (options.gzip !== undefined && !options.gzip) { - options.headers = options.headers || {}; - options.headers['Accept-Encoding'] = 'identity'; - delete options.gzip; + + //baseRequest creates new agent(win-ca injects in globalAgent) + const httpsAgentOptions = { ...https.globalAgent.options, ...options}; + const httpAgentOptions = { ...http.globalAgent.options, ...options}; + changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); + + if (optTimeout.connectionAndInactivity) { + httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); + httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); } - if (!exports.addExternalRequestOptions(ctx, uri, opt_filterPrivate, options)) { + + if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options, httpAgentOptions, httpsAgentOptions)) { throw new Error('Block external request. See externalRequest config options'); } - const protocol = new URL(uri).protocol; - if (!options.httpsAgent && !options.httpAgent) { - const agentOptions = { ...https.globalAgent.options, rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false? false : true}; - if (tenTenantRequestDefaults.forever !== undefined) { - agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; - } - if (protocol === 'https:') { - options.httpsAgent = new https.Agent(agentOptions); - } else if (protocol === 'http:') { - options.httpAgent = new http.Agent(agentOptions); - } + if (!options.httpsAgent || !options.httpAgent) { + options.httpsAgent = new https.Agent(httpsAgentOptions); + options.httpAgent = new http.Agent(httpAgentOptions); } const headers = { ...options.headers }; @@ -389,18 +403,16 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat method: 'GET', responseType: 'stream', headers, - maxRedirects: followRedirect ? maxRedirects : 0, - timeout: connectionAndInactivity, validateStatus: (status) => status >= 200 && status < 300, - cancelToken: new axios.CancelToken(cancel => { - if (optTimeout?.wholeCycle) { - setTimeout(() => { - cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); - }, ms(optTimeout.wholeCycle)); - } - }), + signal: optTimeout.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, + // cancelToken: new axios.CancelToken(cancel => { + // if (optTimeout?.wholeCycle) { + // setTimeout(() => { + // cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); + // }, ms(optTimeout.wholeCycle)); + // } + // }), }; - try { const response = await axios(axiosConfig); const { status, headers } = response; @@ -413,34 +425,31 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat const contentLength = headers['content-length']; if (contentLength && parseInt(contentLength) > sizeLimit) { - throw new Error('EMSGSIZE: Error response: content-length:' + contentLength); - } - - return await processResponseStream(ctx, { - response, - sizeLimit, - uri, - opt_streamWriter, - contentLength, - timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null - }); - } catch (err) { - if (axios.isCancel(err)) { - const error = new Error(err.message); - error.code = 'ETIMEDOUT'; + // Close the stream to prevent downloading + const error = new Error('EMSGSIZE: Error response: content-length:' + contentLength); + error.code = 'EMSGSIZE'; + response.data.destroy(error); throw error; } - - if (err.response) { - if (opt_streamWriter && !isRedirectResponse(err.response)) { - delete err.response.headers['set-cookie']; - return processErrorResponseStream(err.response, { - sizeLimit, - opt_streamWriter, - timeout: optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : null - }); - } + const limitedStream = new SizeLimitStream(optLimit); + if (opt_returnStream) { + // When returning a stream, we'll return the response for the caller to handle streaming + // The content-length check is already done above + return { response, sha256: null, body: null, stream: response.data.pipe(limitedStream) }; } + + const body = await pipeline(response.data, limitedStream, buffer); + const sha256 = crypto.createHash('sha256').update(body).digest('hex'); + return { response, sha256, body, stream: null }; + } catch (err) { + if('ERR_CANCELED' === err.code) { + err.code = 'ETIMEDOUT'; + } + // if (axios.isCancel(err)) { + // const error = new Error(err.message); + // error.code = 'ETIMEDOUT'; + // throw error; + // } throw err; } } @@ -551,12 +560,11 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi }); if (options.gzip !== undefined && !options.gzip) { - options.headers = options.headers || {}; - options.headers['Accept-Encoding'] = 'identity'; + options.headers = { ...options.headers, 'Accept-Encoding': 'identity' }; delete options.gzip; } - if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options)) { + if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options, http.globalAgent.options, https.globalAgent.options)) { throw new Error('Block external request. See externalRequest config options'); } const protocol = new URL(uri).protocol; @@ -632,7 +640,6 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi } exports.postRequestPromise = postRequestPromise; exports.downloadUrlPromise = downloadUrlPromise; -exports.addExternalRequestOptions = addExternalRequestOptions; exports.mapAscServerErrorToOldError = function(error) { var res = -1; switch (error) { @@ -1306,6 +1313,47 @@ function getMonthDiff(d1, d2) { return months; } exports.getMonthDiff = getMonthDiff; + +/** + * A Transform stream that limits the size of data passing through it. + * It will throw an EMSGSIZE error if the size exceeds the limit. + * + * @class SizeLimitStream + * @extends {Transform} + */ +class SizeLimitStream extends Transform { + /** + * Creates an instance of SizeLimitStream. + * @param {number} sizeLimit - Maximum size in bytes that can pass through the stream + * @memberof SizeLimitStream + */ + constructor(sizeLimit) { + super(); + this.sizeLimit = sizeLimit; + this.bytesReceived = 0; + } + + /** + * Transform implementation that tracks the bytes received and enforces the size limit + * + * @param {Buffer|string} chunk - The chunk of data to process + * @param {string} encoding - The encoding of the chunk if it's a string + * @param {Function} callback - Called when processing is complete + * @memberof SizeLimitStream + */ + _transform(chunk, encoding, callback) { + this.bytesReceived += chunk.length; + + if (this.sizeLimit && this.bytesReceived > this.sizeLimit) { + const error = new Error(`EMSGSIZE: Response too large: ${this.bytesReceived} bytes (limit: ${this.sizeLimit} bytes)`); + error.code = 'EMSGSIZE'; + callback(error); + return; + } + + callback(null, chunk); + } +} exports.getLicensePeriod = function(startDate, now) { startDate = new Date(startDate.getTime());//clone startDate.addMonths(getMonthDiff(startDate, now)); diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index 845dcab8..95fca8e0 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -34,6 +34,8 @@ const crypto = require('crypto'); var pathModule = require('path'); var urlModule = require('url'); +const { pipeline } = require('node:stream/promises'); +const { buffer } = require('node:stream/consumers'); var co = require('co'); const ms = require('ms'); const retry = require('retry'); @@ -1746,7 +1748,14 @@ exports.downloadFile = function(req, res) { headers['Range'] = req.get('Range'); } - yield utils.downloadUrlPromise(ctx, url, tenDownloadTimeout, tenDownloadMaxBytes, authorization, isInJwtToken, headers, res); + const { response, stream } = yield utils.downloadUrlPromise(ctx, url, tenDownloadTimeout, tenDownloadMaxBytes, authorization, isInJwtToken, headers, true); + //Set-Cookie resets browser session + delete response.headers['set-cookie']; + // Set the response headers to match the target response + res.set(response.headers); + + // Use pipeline to pipe the response data to the client + yield pipeline(stream, res); } if (clientStatsD) { diff --git a/tests/integration/withServerInstance/request.tests.js b/tests/integration/withServerInstance/request.tests.js index 0ff42804..c137f0c8 100644 --- a/tests/integration/withServerInstance/request.tests.js +++ b/tests/integration/withServerInstance/request.tests.js @@ -1,6 +1,8 @@ const { describe, test, expect, beforeAll, afterAll } = require('@jest/globals'); const { Writable, Readable } = require('stream'); +const { buffer } = require('node:stream/consumers'); const http = require('http'); +const https = require('https'); const express = require('express'); const operationContext = require('../../../Common/sources/operationContext'); const utils = require('../../../Common/sources/utils'); @@ -16,16 +18,6 @@ let testServer; const PORT = 3456; const BASE_URL = `http://localhost:${PORT}`; -// Helper to create a writable stream for testing -const createMockWriter = () => { - const chunks = []; - return new Writable({ - write(chunk, encoding, callback) { - chunks.push(chunk); - callback(); - } - }); -}; const getStatusCode = (response) => response.statusCode || response.status; @@ -101,14 +93,6 @@ describe('HTTP Request Integration Tests', () => { res.json({ success: true }); }); - // Endpoint that streams data - app.get('/api/stream', (req, res) => { - res.setHeader('content-type', 'application/octet-stream'); - res.setHeader('content-length', '1024'); - const buffer = Buffer.alloc(1024); - res.send(buffer); - }); - // Endpoint that simulates timeout app.get('/api/timeout', (req, res) => { // Never send response to trigger timeout @@ -144,17 +128,18 @@ describe('HTTP Request Integration Tests', () => { res.send(binaryData); }); - // Large file endpoint app.get('/api/large', (req, res) => { - res.setHeader('content-length', '2097152'); // 2MB res.setHeader('content-type', 'application/octet-stream'); - const buffer = Buffer.alloc(2097152); - res.send(buffer); + res.send(Buffer.alloc(2*1024*1024));//2MB }); - app.get('/api/headers', (req, res) => { - // Ensure you're only sending headers, which won't contain circular references - res.json({ headers: req.headers }); + + // Large file endpoint with truly no content-length header + app.get('/api/large-chunked', (req, res) => { + res.setHeader('content-type', 'application/octet-stream'); + res.setHeader('transfer-encoding', 'chunked'); + res.write(Buffer.alloc(2*1024*1024)); + res.end(); }); // Endpoint that returns connection header info @@ -180,7 +165,29 @@ describe('HTTP Request Integration Tests', () => { keepAlive: connectionHeader.toLowerCase() === 'keep-alive' }); }); - + + // Endpoint that mirrors whole request - handles any HTTP method + app.use('/api/mirror', express.json(), express.urlencoded({ extended: true }), (req, res) => { + // Create a mirror response object with all request details + const mirror = { + method: req.method, + url: req.url, + path: req.path, + query: req.query, + params: req.params, + headers: req.headers, + body: req.body, + protocol: req.protocol, + ip: req.ip, + hostname: req.hostname, + originalUrl: req.originalUrl, + xhr: req.xhr, + secure: req.secure + }; + + // Send the mirror response back + res.json(mirror); + }); // Start server server = http.createServer(app); @@ -210,47 +217,43 @@ describe('HTTP Request Integration Tests', () => { expect(JSON.parse(result.body.toString())).toEqual({ success: true }); }); - test('handles streaming with writer', async () => { - const mockStreamWriter = createMockWriter(); - - const result = await utils.downloadUrlPromise( - ctx, - `${BASE_URL}/api/stream`, - { wholeCycle: '5s', connectionAndInactivity: '3s' }, - 1024 * 1024, - null, - false, - null, - mockStreamWriter - ); - - expect(result).toBeUndefined(); - }); - test('throws error on timeout', async () => { - await expect(utils.downloadUrlPromise( - ctx, - `${BASE_URL}/api/timeout`, - { wholeCycle: '1s', connectionAndInactivity: '500ms' }, - 1024 * 1024, - null, - false, - null, - null - )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|timeout of 500ms exceeded)/); + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/timeout`, + { wholeCycle: '1s', connectionAndInactivity: '500ms' }, + 1024 * 1024, + null, + false, + null, + null + ); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('canceled'); + expect(error.code).toBe('ETIMEDOUT'); + } }); test('throws error on wholeCycle timeout', async () => { - await expect(utils.downloadUrlPromise( - ctx, - `${BASE_URL}/api/timeout`, - { wholeCycle: '1s', connectionAndInactivity: '5000ms' }, - 1024 * 1024, - null, - false, - null, - null - )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|ETIMEDOUT: 1s|whole request cycle timeout: 1s)/); + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/timeout`, + { wholeCycle: '1s', connectionAndInactivity: '5000ms' }, + 1024 * 1024, + null, + false, + null, + null + ); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('canceled'); + expect(error.code).toBe('ETIMEDOUT'); + } + }); test('follows redirects correctly', async () => { @@ -354,16 +357,74 @@ describe('HTTP Request Integration Tests', () => { }); test('throws error when content-length exceeds limit', async () => { - await expect(utils.downloadUrlPromise( - ctx, - `${BASE_URL}/api/large`, - { wholeCycle: '5s', connectionAndInactivity: '3s' }, - 1024 * 1024, - null, - false, - null, - null - )).rejects.toThrow('Error response: content-length:2097152'); + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/large`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null + ); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('EMSGSIZE:'); + expect(error.code).toBe('EMSGSIZE'); + } + + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/large-chunked`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null + ); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('EMSGSIZE:'); + expect(error.code).toBe('EMSGSIZE'); + } + }); + + test('throws error when content-length exceeds limit with stream', async () => { + try { + const {stream} = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/large`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + true + ); + const receivedData = await buffer(stream); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('EMSGSIZE:'); + expect(error.code).toBe('EMSGSIZE'); + } + try { + const {stream} = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/large-chunked`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + true + ); + const receivedData = await buffer(stream); + fail('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('EMSGSIZE:'); + expect(error.code).toBe('EMSGSIZE'); + } }); test('enables compression when gzip is true', async () => { @@ -522,6 +583,31 @@ describe('HTTP Request Integration Tests', () => { // so we're checking that keepAlive is false expect(responseData.keepAlive).toBe(false); }); + + test('test requestDefaults', async () => { + const defaultHeaders = {"user-agent": "Node.js/6.13"}; + const mockCtx = createMockContext({ + 'services.CoAuthoring.requestDefaults': { + headers: defaultHeaders + } + }); + let customHeaders = {"custom-header": "test-value", "set-cookie": ["cookie"]}; + let customQueryParams = {"custom-query-param": "value"}; + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/mirror?${new URLSearchParams(customQueryParams).toString()}`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + customHeaders + ); + expect(result).toBeDefined(); + expect(result.response.status).toBe(200); + const body = JSON.parse(result.body); + expect(body.headers).toMatchObject({...defaultHeaders, ...customHeaders}); + expect(body.query).toMatchObject(customQueryParams); + }); }); test('handles binary data correctly', async () => { @@ -551,15 +637,7 @@ describe('HTTP Request Integration Tests', () => { }); test('handles binary data with stream writer', async () => { - const chunks = []; - const mockStreamWriter = new Writable({ - write(chunk, encoding, callback) { - chunks.push(chunk); - callback(); - } - }); - - await utils.downloadUrlPromise( + const { stream } = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/binary`, { wholeCycle: '5s', connectionAndInactivity: '3s' }, @@ -567,11 +645,9 @@ describe('HTTP Request Integration Tests', () => { null, false, null, - mockStreamWriter + true ); - - // Combine chunks and verify - const receivedData = Buffer.concat(chunks); + const receivedData = await buffer(stream); const expectedData = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); expect(Buffer.isBuffer(receivedData)).toBe(true); From 9b73f4e711115b017b62fd01a68bc488cc5ee7ed Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Tue, 15 Apr 2025 15:26:09 +0300 Subject: [PATCH 10/17] [feature] Move requests.tests in /unit --- .../{integration/withServerInstance => unit}/request.tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/{integration/withServerInstance => unit}/request.tests.js (99%) diff --git a/tests/integration/withServerInstance/request.tests.js b/tests/unit/request.tests.js similarity index 99% rename from tests/integration/withServerInstance/request.tests.js rename to tests/unit/request.tests.js index c137f0c8..3246d21a 100644 --- a/tests/integration/withServerInstance/request.tests.js +++ b/tests/unit/request.tests.js @@ -4,8 +4,8 @@ const { buffer } = require('node:stream/consumers'); const http = require('http'); const https = require('https'); const express = require('express'); -const operationContext = require('../../../Common/sources/operationContext'); -const utils = require('../../../Common/sources/utils'); +const operationContext = require('../../Common/sources/operationContext'); +const utils = require('../../Common/sources/utils'); const fs = require('fs').promises; const path = require('path'); From 92a907cbd88710f5a571c7bdc44879121752c234 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Tue, 15 Apr 2025 22:41:42 +0300 Subject: [PATCH 11/17] [feature] Refactor tests, proxy, timeouts --- Common/sources/utils.js | 117 ++------- tests/unit/request.tests.js | 494 +++++++++++++++++++++++++++--------- 2 files changed, 389 insertions(+), 222 deletions(-) diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 6e1ed5ab..942087c3 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -315,9 +315,11 @@ function addExternalRequestOptions(ctx, uri, isInJwtToken, options, httpAgentOpt const proxyUrl = tenExternalRequestAction.proxyUrl; const parsedProxyUrl = url.parse(proxyUrl); - options.proxy.host = parsedProxyUrl.hostname; - options.proxy.port = parsedProxyUrl.port; - options.proxy.protocol = parsedProxyUrl.protocol; + options.proxy = { + host: parsedProxyUrl.hostname, + port: parsedProxyUrl.port, + protocol: parsedProxyUrl.protocol + }; } if (tenExternalRequestAction.proxyUser?.username) { @@ -375,10 +377,10 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat const httpAgentOptions = { ...http.globalAgent.options, ...options}; changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); - if (optTimeout.connectionAndInactivity) { - httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - } + // if (optTimeout.connectionAndInactivity) { + // httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); + // httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); + // } if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options, httpAgentOptions, httpsAgentOptions)) { throw new Error('Block external request. See externalRequest config options'); @@ -405,6 +407,7 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat headers, validateStatus: (status) => status >= 200 && status < 300, signal: optTimeout.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, + timeout: optTimeout.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, // cancelToken: new axios.CancelToken(cancel => { // if (optTimeout?.wholeCycle) { // setTimeout(() => { @@ -444,106 +447,16 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat } catch (err) { if('ERR_CANCELED' === err.code) { err.code = 'ETIMEDOUT'; + } else if(['ECONNABORTED', 'ECONNRESET'].includes(err.code)) { + err.code = 'ESOCKETTIMEDOUT'; + } + if (err.status){ + err.statusCode = err.status; } - // if (axios.isCancel(err)) { - // const error = new Error(err.message); - // error.code = 'ETIMEDOUT'; - // throw error; - // } throw err; } } -async function processResponseStream(ctx, { response, sizeLimit, uri, opt_streamWriter, contentLength, timeout }) { - return new Promise((resolve, reject) => { - const hash = crypto.createHash('sha256'); - let buffer = []; - let bufferLength = 0; - let timeoutId; - - const stream = response.data; - - if (timeout) { - timeoutId = setTimeout(() => { - stream.destroy(); - reject(new Error(`ETIMEDOUT: ${timeout}`)); - }, timeout); - } - - stream.on('data', chunk => { - hash.update(chunk); - bufferLength += chunk.length; - if (bufferLength > sizeLimit) { - stream.destroy(); - throw new Error('EMSGSIZE: Error response body.length'); - } - if (!opt_streamWriter) buffer.push(chunk); - }); - - stream.on('error', reject); - - stream.on('end', () => { - clearTimeout(timeoutId); - const result = { - response, - sha256: hash.digest('hex'), - body: opt_streamWriter ? null : Buffer.concat(buffer) - }; - - if (!opt_streamWriter && contentLength && result.body?.length !== parseInt(contentLength)) { - ctx.logger.warn('Body size mismatch: %s (expected %s, got %d)', - uri, contentLength, result.body?.length); - } - - resolve(opt_streamWriter ? undefined : result); - }); - - if (opt_streamWriter) { - pipeline(stream, opt_streamWriter) - .catch(reject); - } - }); -} - -async function processErrorResponseStream(response, { sizeLimit, opt_streamWriter, timeout }) { - return new Promise((resolve, reject) => { - const hash = crypto.createHash('sha256'); - let bufferLength = 0; - let timeoutId; - - const stream = response.data; - - if (timeout) { - timeoutId = setTimeout(() => { - stream.destroy(); - reject(new Error(`ETIMEDOUT: ${timeout}`)); - }, timeout); - } - - stream.on('data', chunk => { - hash.update(chunk); - bufferLength += chunk.length; - if (bufferLength > sizeLimit) { - stream.destroy(); - reject(new Error('EMSGSIZE')); - } - }); - - stream.on('error', reject); - - stream.on('end', () => { - clearTimeout(timeoutId); - resolve({ - response, - sha256: hash.digest('hex') - }); - }); - - pipeline(stream, opt_streamWriter) - .catch(reject); - }); -} - async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_isInJwtToken, opt_headers) { const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index 3246d21a..bb776ce3 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -15,9 +15,13 @@ const ctx = new operationContext.Context(); // Test server setup let server; let testServer; +let proxyServer; const PORT = 3456; const BASE_URL = `http://localhost:${PORT}`; - +const PROXY_PORT = PORT + 2000; +const PROXY_URL = `http://localhost:${PROXY_PORT}`; +// Track requests going through the proxy +const proxiedRequests = []; const getStatusCode = (response) => response.statusCode || response.status; @@ -83,7 +87,7 @@ function createMockContext(overrides = {}) { }; } -describe('HTTP Request Integration Tests', () => { +describe('HTTP Request Unit Tests', () => { beforeAll(async () => { // Setup test Express server const app = express(); @@ -108,6 +112,46 @@ describe('HTTP Request Integration Tests', () => { app.get('/api/error', (req, res) => { res.status(500).json({ error: 'Internal Server Error' }); }); + // Endpoint that simulates a slow response headers + app.get('/api/slow-headers', (req, res) => { + // Delay sending headers + setTimeout(() => { + res.json({ success: true }); + }, 2000); // 2 seconds delay before sending any response + }); + + + // Endpoint that simulates partial response with incomplete body + app.get('/api/partial-response', (req, res) => { + // Send headers immediately + res.setHeader('Content-Type', 'application/json'); + // Start sending data + res.write('{"start": "This response'); + + // But never finish the response (simulates a server that hangs after starting to send data) + // This should trigger the wholeCycle timeout + }); + + + // Endpoint that simulates slow/chunked response with inactivity periods + app.get('/api/slow-body', (req, res) => { + // Send headers immediately + res.setHeader('Content-Type', 'application/json'); + res.write('{"part1": "First part of the response",'); + + // Delay between chunks (simulates inactivity during response body transmission) + setTimeout(() => { + res.write('"part2": "Second part of the response",'); + // Final delay - this delay is longer than the connectionAndInactivity timeout should be + setTimeout(() => { + res.write('"part3": "third part",'); + setTimeout(() => { + res.write('"part4": "Final part"}'); + res.end(); + }, 2000); + }, 1000); + }, 1000); + }); // POST endpoint app.post('/api/post', express.json(), (req, res) => { @@ -192,11 +236,214 @@ describe('HTTP Request Integration Tests', () => { // Start server server = http.createServer(app); await new Promise(resolve => server.listen(PORT, resolve)); + + // Setup proxy server + const proxyApp = express(); + proxyApp.use((req, res, next) => { + // Record request details + const requestInfo = { + method: req.method, + url: req.url, + headers: req.headers, + body: '' + }; + proxiedRequests.push(requestInfo); + + // Collect body data if present + req.on('data', chunk => { + requestInfo.body += chunk.toString(); + }); + + // Validate proxy authentication + const authHeader = req.headers['proxy-authorization']; + if (!authHeader || !authHeader.startsWith('Basic ')) { + res.status(407).set('Proxy-Authenticate', 'Basic').send('Proxy authentication required'); + return; + } + + // Decode and verify credentials + const base64Credentials = authHeader.split(' ')[1]; + const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8'); + const [username, password] = credentials.split(':'); + + // Expected credentials from config (will be overridden by test-specific values) + const expectedUsername = 'proxyuser'; + const expectedPassword = 'proxypass'; + + if (username !== expectedUsername || password !== expectedPassword) { + res.status(407).set('Proxy-Authenticate', 'Basic').send('Invalid proxy credentials'); + return; + } + + // Forward the request + const targetUrl = new URL(req.url); + const options = { + hostname: targetUrl.hostname, + port: targetUrl.port || (targetUrl.protocol === 'https:' ? 443 : 80), + path: targetUrl.pathname + targetUrl.search, + method: req.method, + headers: { ...req.headers } + }; + + const proxyReq = http.request(options, (proxyRes) => { + // Copy status code + res.statusCode = proxyRes.statusCode; + + // Copy headers + Object.keys(proxyRes.headers).forEach(key => { + res.setHeader(key, proxyRes.headers[key]); + }); + + // Pipe response data + proxyRes.pipe(res); + }); + + // Handle proxy errors + proxyReq.on('error', (error) => { + console.error('Proxy error:', error); + res.statusCode = 500; + res.end('Proxy Error'); + }); + + // Pipe request data + if (['POST', 'PUT', 'PATCH'].includes(req.method)) { + req.pipe(proxyReq); + } else { + proxyReq.end(); + } + }); + + proxyServer = http.createServer(proxyApp); + await new Promise(resolve => proxyServer.listen(PROXY_PORT, resolve)); }); afterAll(async () => { - // Cleanup server + // Cleanup servers await new Promise(resolve => server.close(resolve)); + if (proxyServer) { + await new Promise(resolve => proxyServer.close(resolve)); + } + }); + + + describe('specific timeout behaviors', () => { + test('connectionAndInactivity triggers when server delays response headers', async () => { + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/slow-headers`, + { connectionAndInactivity: '1s' }, // connectionAndInactivity shorter than the server delay + 1024 * 1024, + null, + false, + null, + null + ); + throw new Error('Expected an error to be thrown'); + } catch (error) { + // Different implementations might throw different error messages/codes + expect(error.code).toBe('ESOCKETTIMEDOUT'); + } + }); + + + test('connectionAndInactivity does not trigger when longer than server delay', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/slow-headers`, + { connectionAndInactivity: '3s' }, // connectionAndInactivity longer than the server delay (2s) + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + }); + + + test('wholeCycle triggers even when server starts sending data but does not complete', async () => { + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/partial-response`, + { wholeCycle: '2s' }, // wholeCycle shorter than time needed for response + 1024 * 1024, + null, + false, + null, + null + ); + throw new Error('Expected an error to be thrown'); + } catch (error) { + expect(error.code).toBe('ETIMEDOUT'); + } + }); + + + test('connectionAndInactivity triggers when server stops sending data midway', async () => { + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/slow-body`, + { connectionAndInactivity: '1500ms' }, // connectionAndInactivity shorter than the second delay + 1024 * 1024, + null, + false, + null, + null + ); + throw new Error('Expected an error to be thrown'); + } catch (error) { + // This should catch the inactivity timeout during body transmission + expect(error.code).toBe('ESOCKETTIMEDOUT'); + } + }); + + test('connectionAndInactivity does not trigger when longer than inactivity periods', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/slow-body`, + { connectionAndInactivity: '2100ms' }, // connectionAndInactivity longer than the longest delay (2s) + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + const responseBody = JSON.parse(result.body.toString()); + expect(responseBody.part1).toBe('First part of the response'); + expect(responseBody.part2).toBe('Second part of the response'); + expect(responseBody.part3).toBe('third part'); + expect(responseBody.part4).toBe('Final part'); + }); + + test('wholeCycle does not trigger when longer than total response time', async () => { + const result = await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/slow-body`, + { wholeCycle: '7s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + const responseBody = JSON.parse(result.body.toString()); + expect(responseBody.part1).toBe('First part of the response'); + expect(responseBody.part2).toBe('Second part of the response'); + expect(responseBody.part3).toBe('third part'); + expect(responseBody.part4).toBe('Final part'); + }); }); describe('downloadUrlPromise', () => { @@ -229,10 +476,9 @@ describe('HTTP Request Integration Tests', () => { null, null ); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('canceled'); - expect(error.code).toBe('ETIMEDOUT'); + expect(error.code).toBe('ESOCKETTIMEDOUT'); } }); @@ -248,9 +494,8 @@ describe('HTTP Request Integration Tests', () => { null, null ); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('canceled'); expect(error.code).toBe('ETIMEDOUT'); } @@ -298,13 +543,9 @@ describe('HTTP Request Integration Tests', () => { null, null ); - - // Old implementation path - expect(result).toBeDefined(); - expect(getStatusCode(result.response)).toBe(302); } catch (error) { // New implementation path (Axios) - expect(error.message).toMatch(/(?:Request failed with status code 302|Error response: statusCode:302)/); + expect(error.statusCode).toBe(302) } }); @@ -335,11 +576,9 @@ describe('HTTP Request Integration Tests', () => { ); // Old implementation path - expect(result).toBeDefined(); - expect(getStatusCode(result.response)).toBe(302); } catch (error) { // New implementation path (Axios) - expect(error.message).toMatch(/(?:Request failed with status code 302|Error response: statusCode:302)/); + expect(error.statusCode).toBe(302); } }); @@ -353,7 +592,7 @@ describe('HTTP Request Integration Tests', () => { false, null, null - )).rejects.toThrow(/(?:Error response: statusCode:500|Request failed with status code 500)/); + )).rejects.toMatchObject({ code: 'ERR_BAD_RESPONSE' }); }); test('throws error when content-length exceeds limit', async () => { @@ -367,9 +606,8 @@ describe('HTTP Request Integration Tests', () => { false, null ); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('EMSGSIZE:'); expect(error.code).toBe('EMSGSIZE'); } @@ -383,9 +621,8 @@ describe('HTTP Request Integration Tests', () => { false, null ); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('EMSGSIZE:'); expect(error.code).toBe('EMSGSIZE'); } }); @@ -403,9 +640,8 @@ describe('HTTP Request Integration Tests', () => { true ); const receivedData = await buffer(stream); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('EMSGSIZE:'); expect(error.code).toBe('EMSGSIZE'); } try { @@ -420,9 +656,8 @@ describe('HTTP Request Integration Tests', () => { true ); const receivedData = await buffer(stream); - fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); } catch (error) { - expect(error.message).toContain('EMSGSIZE:'); expect(error.code).toBe('EMSGSIZE'); } }); @@ -608,6 +843,56 @@ describe('HTTP Request Integration Tests', () => { expect(body.headers).toMatchObject({...defaultHeaders, ...customHeaders}); expect(body.query).toMatchObject(customQueryParams); }); + + test('successfully routes GET request through a real proxy', async () => { + try { + // Create context with proxy configuration + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": true, + "blockPrivateIP": false, + "proxyUrl": PROXY_URL, + "proxyUser": { + "username": "proxyuser", + "password": "proxypass" + }, + "proxyHeaders": { + "X-Proxy-Custom": "custom-value" + } + } + }); + + // Make a GET request through the proxy + const result = await utils.downloadUrlPromise( + mockCtx, + `${BASE_URL}/api/data`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ); + + // Verify the request was successful + expect(result).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + expect(JSON.parse(result.body.toString())).toEqual({ success: true }); + + // Verify the request went through our proxy + expect(proxiedRequests.length).toBeGreaterThan(0); + const proxyRequest = proxiedRequests.find(r => + r.method === 'GET' && r.url.includes('/api/data') + ); + expect(proxyRequest).toBeDefined(); + expect(proxyRequest.url).toContain(`${BASE_URL}/api/data`); + // Check for Base64 encoded authorization header (starts with "Basic ") + expect(proxyRequest.headers['proxy-authorization']).toMatch(/^Basic /); + expect(proxyRequest.headers['x-proxy-custom']).toBe('custom-value'); + } finally { + // No need to clean up proxy server here anymore + } + }); }); test('handles binary data correctly', async () => { @@ -669,6 +954,7 @@ describe('HTTP Request Integration Tests', () => { } }); + // Use rejects.toThrow to test the error message await expect(utils.downloadUrlPromise( mockCtx, 'https://example.com/test', @@ -749,50 +1035,6 @@ describe('HTTP Request Integration Tests', () => { expect(JSON.parse(result.body.toString())).toEqual({ success: true }); }); - test('request with proxy configuration', async () => { - const mockCtx = createMockContext({ - 'externalRequest.action': { - "allow": true, - "blockPrivateIP": true, - "proxyUrl": "http://proxy.example.com:8080", - "proxyUser": { - "username": "testuser", - "password": "testpass" - }, - "proxyHeaders": { - "X-Custom-Header": "test-value" - } - } - }); - - try { - await utils.downloadUrlPromise( - mockCtx, - 'https://example.com/test', - { wholeCycle: '5s', connectionAndInactivity: '3s' }, - 1024 * 1024, - null, - false, - null, - null - ); - fail('Expected request to fail'); - } catch (error) { - // Different error structures between implementations - const headers = error.config?.headers || error.request?._headers || error._headers; - if (headers) { - expect(headers).toEqual( - expect.objectContaining({ - 'proxy-authorization': expect.stringContaining('testuser:testpass'), - 'X-Custom-Header': 'test-value' - }) - ); - } - // If headers aren't available, at least verify the error occurred - expect(error).toBeDefined(); - } - }); - describe('postRequestPromise', () => { test('successfully posts data', async () => { const postData = JSON.stringify({ test: 'data' }); @@ -827,7 +1069,7 @@ describe('HTTP Request Integration Tests', () => { null, false, { 'Content-Type': 'application/json' } - )).rejects.toThrow(/(?:ESOCKETTIMEDOUT|timeout of 500ms exceeded)/); + )).rejects.toMatchObject({ code: 'ESOCKETTIMEDOUT' }); }); test('handles post with Authorization header', async () => { @@ -914,7 +1156,7 @@ describe('HTTP Request Integration Tests', () => { null, false, { 'Content-Type': 'application/json' } - )).rejects.toThrow(/(?:ETIMEDOUT|ESOCKETTIMEDOUT|whole request cycle timeout: 1s|Whole request cycle timeout: 1s)/); + )).rejects.toMatchObject({ code: 'ETIMEDOUT' }); }); test('blocks external post requests when configured', async () => { @@ -983,54 +1225,6 @@ describe('HTTP Request Integration Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); }); - test('handles post with proxy configuration', async () => { - const mockCtx = createMockContext({ - 'externalRequest.action': { - "allow": true, - "blockPrivateIP": true, - "proxyUrl": "http://proxy.example.com:8080", - "proxyUser": { - "username": "testuser", - "password": "testpass" - }, - "proxyHeaders": { - "X-Custom-Proxy-Header": "test-value" - } - } - }); - - const postData = JSON.stringify({ test: 'data' }); - - try { - await utils.postRequestPromise( - mockCtx, - 'https://example.com/api/post', - postData, - null, - postData.length, - { wholeCycle: '5s', connectionAndInactivity: '3s' }, - null, - false, - { 'Content-Type': 'application/json' } - ); - fail('Expected request to fail'); - } catch (error) { - // Different error structures between implementations - const headers = error.config?.headers || error.request?._headers || error._headers; - if (headers) { - expect(headers).toEqual( - expect.objectContaining({ - 'proxy-authorization': expect.stringContaining('testuser:testpass'), - 'X-Custom-Proxy-Header': 'test-value', - 'Content-Type': 'application/json' - }) - ); - } - // If headers aren't available, at least verify the error occurred - expect(error).toBeDefined(); - } - }); - test('applies gzip setting to POST requests', async () => { // Setup a simple server that captures headers let capturedHeaders = {}; @@ -1119,5 +1313,65 @@ describe('HTTP Request Integration Tests', () => { await new Promise(resolve => testServer.close(resolve)); } }); + + test('successfully routes POST request through a real proxy', async () => { + try { + // Create context with proxy configuration + const mockCtx = createMockContext({ + 'externalRequest.action': { + "allow": true, + "blockPrivateIP": false, + "proxyUrl": PROXY_URL, + "proxyUser": { + "username": "proxyuser", + "password": "proxypass" + }, + "proxyHeaders": { + "X-Post-Proxy": "post-proxy-value" + } + } + }); + + // Test POST request + const postData = JSON.stringify({ nested: { test: 'complex-data' } }); + + const postResult = await utils.postRequestPromise( + mockCtx, + `${BASE_URL}/api/post`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 'auth-token', // With auth token + false, + { 'Content-Type': 'application/json', 'X-Custom': 'test-value' } + ); + + // Verify the post request + expect(postResult).toBeDefined(); + expect(postResult.response.statusCode).toBe(200); + expect(JSON.parse(postResult.body)).toEqual({ + received: { nested: { test: 'complex-data' } } + }); + + // Verify proxy headers and auth + const postProxyRequest = proxiedRequests.find(r => + r.method === 'POST' && r.url.includes('/api/post') + ); + + expect(postProxyRequest).toBeDefined(); + // Check for Base64 encoded authorization header (starts with "Basic ") + expect(postProxyRequest.headers['proxy-authorization']).toMatch(/^Basic /); + expect(postProxyRequest.headers['x-post-proxy']).toBe('post-proxy-value'); + expect(postProxyRequest.headers['content-type']).toBe('application/json'); + expect(postProxyRequest.headers['x-custom']).toBe('test-value'); + expect(postProxyRequest.headers['authorization']).toContain('Bearer auth-token'); + + // Verify post body was correctly sent + expect(JSON.parse(postProxyRequest.body)).toEqual({ nested: { test: 'complex-data' } }); + } finally { + // No need to clean up proxy server here anymore + } + }); }); -}); +}); \ No newline at end of file From 6fa190bc767529c72c9a3552ae85b5f93d74c7ac Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Fri, 18 Apr 2025 11:45:41 +0300 Subject: [PATCH 12/17] [feature] Refactor postRequestPromise --- Common/sources/utils.js | 2659 +++++++++++++++++++-------------------- 1 file changed, 1324 insertions(+), 1335 deletions(-) diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 942087c3..12e3d0d4 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -1,1335 +1,1324 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2024 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -'use strict'; - -//Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513) -require("tls").DEFAULT_ECDH_CURVE = "auto"; - -const { pipeline } = require('node:stream/promises'); -const { buffer } = require('node:stream/consumers'); -const { Transform } = require('stream'); -var config = require('config'); -var fs = require('fs'); -var path = require('path'); -const crypto = require('crypto'); -var url = require('url'); -var axios = require('axios'); -var co = require('co'); -var URI = require("uri-js"); -const escapeStringRegexp = require('escape-string-regexp'); -const ipaddr = require('ipaddr.js'); -const getDnsCache = require('dnscache'); -const jwt = require('jsonwebtoken'); -const NodeCache = require( "node-cache" ); -const ms = require('ms'); -const constants = require('./constants'); -const commonDefines = require('./commondefines'); -const forwarded = require('forwarded'); -const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent } = require("request-filtering-agent"); -const https = require('https'); -const http = require('http'); -const ca = require('win-ca/api'); -const util = require('util'); - -const contentDisposition = require('content-disposition'); -const operationContext = require("./operationContext"); - -//Clone sealed config objects before passing to external libraries using config.util.cloneDeep -const cfgDnsCache = config.util.cloneDeep(config.get('dnscache')); -const cfgIpFilterRules = config.get('services.CoAuthoring.ipfilter.rules'); -const cfgIpFilterErrorCode = config.get('services.CoAuthoring.ipfilter.errorcode'); -const cfgIpFilterUseForRequest = config.get('services.CoAuthoring.ipfilter.useforrequest'); -const cfgExpPemStdTtl = config.get('services.CoAuthoring.expire.pemStdTTL'); -const cfgExpPemCheckPeriod = config.get('services.CoAuthoring.expire.pemCheckPeriod'); -const cfgTokenOutboxHeader = config.get('services.CoAuthoring.token.outbox.header'); -const cfgTokenOutboxPrefix = config.get('services.CoAuthoring.token.outbox.prefix'); -const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm'); -const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires'); -const cfgVisibilityTimeout = config.get('queue.visibilityTimeout'); -const cfgQueueRetentionPeriod = config.get('queue.retentionPeriod'); -const cfgRequestDefaults = config.util.cloneDeep(config.get('services.CoAuthoring.requestDefaults')); -const cfgTokenEnableRequestOutbox = config.get('services.CoAuthoring.token.enable.request.outbox'); -const cfgTokenOutboxUrlExclusionRegex = config.get('services.CoAuthoring.token.outbox.urlExclusionRegex'); -const cfgSecret = config.get('aesEncrypt.secret'); -const cfgAESConfig = config.util.cloneDeep(config.get('aesEncrypt.config')); -const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent'); -const cfgStorageExternalHost = config.get('storage.externalHost'); -const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn'); -const cfgExternalRequestAction = config.get('externalRequest.action'); -const cfgWinCa = config.util.cloneDeep(config.get('win-ca')); - -ca(cfgWinCa); - -const minimumIterationsByteLength = 4; -const dnscache = getDnsCache(cfgDnsCache); - -var ANDROID_SAFE_FILENAME = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~\'=()[]{}0123456789'; - -//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json -BigInt.prototype.toJSON = function() { return this.toString() }; - -var g_oIpFilterRules = new Map(); -function getIpFilterRule(address) { - let exp = g_oIpFilterRules.get(address); - if (!exp) { - let regExpStr = address.split('*').map(escapeStringRegexp).join('.*'); - exp = new RegExp('^' + regExpStr + '$', 'i'); - g_oIpFilterRules.set(address, exp); - } - return exp; -} -const pemfileCache = new NodeCache({stdTTL: ms(cfgExpPemStdTtl) / 1000, checkperiod: ms(cfgExpPemCheckPeriod) / 1000, errorOnMissing: false, useClones: true}); - -exports.getConvertionTimeout = function(opt_ctx) { - if (opt_ctx) { - const tenVisibilityTimeout = opt_ctx.getCfg('queue.visibilityTimeout', cfgVisibilityTimeout); - const tenQueueRetentionPeriod = opt_ctx.getCfg('queue.retentionPeriod', cfgQueueRetentionPeriod); - return 1.5 * (tenVisibilityTimeout + tenQueueRetentionPeriod) * 1000; - } else { - return 1.5 * (cfgVisibilityTimeout + cfgQueueRetentionPeriod) * 1000; - } -} - -exports.addSeconds = function(date, sec) { - date.setSeconds(date.getSeconds() + sec); -}; -exports.getMillisecondsOfHour = function(date) { - return (date.getUTCMinutes() * 60 + date.getUTCSeconds()) * 1000 + date.getUTCMilliseconds(); -}; -exports.encodeXml = function(value) { - return value.replace(/[<>&'"\r\n\t\xA0]/g, function (c) { - switch (c) { - case '<': return '<'; - case '>': return '>'; - case '&': return '&'; - case '\'': return '''; - case '"': return '"'; - case '\r': return ' '; - case '\n': return ' '; - case '\t': return ' '; - case '\xA0': return ' '; - } - }); -}; -function fsStat(fsPath) { - return new Promise(function(resolve, reject) { - fs.stat(fsPath, function(err, stats) { - if (err) { - reject(err); - } else { - resolve(stats); - } - }); - }); -} -exports.fsStat = fsStat; -function fsReadDir(fsPath) { - return new Promise(function(resolve, reject) { - fs.readdir(fsPath, function(err, list) { - if (err) { - return reject(err); - } else { - resolve(list); - } - }); - }); -} -function* walkDir(fsPath, results, optNoSubDir, optOnlyFolders) { - const list = yield fsReadDir(fsPath); - for (let i = 0; i < list.length; ++i) { - const file = path.join(fsPath, list[i]); - let stats; - try { - stats = yield fsStat(file); - } catch (e) { - //exception if fsPath not exist - stats = null; - } - if (!stats) { - continue; - } - if (stats.isDirectory()) { - if (optNoSubDir) { - optOnlyFolders && results.push(file); - } else { - yield* walkDir(file, results, optNoSubDir, optOnlyFolders); - } - } else { - !optOnlyFolders && results.push(file); - } - } -} -exports.listFolders = function(fsPath, optNoSubDir) { - return co(function* () { - let stats, list = []; - try { - stats = yield fsStat(fsPath); - } catch (e) { - //exception if fsPath not exist - stats = null; - } - if (stats && stats.isDirectory()) { - yield* walkDir(fsPath, list, optNoSubDir, true); - } - return list; - }); -}; -exports.listObjects = function(fsPath, optNoSubDir) { - return co(function* () { - let stats, list = []; - try { - stats = yield fsStat(fsPath); - } catch (e) { - //exception if fsPath not exist - stats = null; - } - if (stats) { - if (stats.isDirectory()) { - yield* walkDir(fsPath, list, optNoSubDir, false); - } else { - list.push(fsPath); - } - } - return list; - }); -}; -exports.sleep = function(ms) { - return new Promise(function(resolve) { - setTimeout(resolve, ms); - }); -}; -exports.readFile = function(file) { - return new Promise(function(resolve, reject) { - fs.readFile(file, function(err, data) { - if (err) { - reject(err); - } else { - resolve(data); - } - }); - }); -}; -function makeAndroidSafeFileName(str) { - for (var i = 0; i < str.length; i++) { - if (-1 == ANDROID_SAFE_FILENAME.indexOf(str[i])) { - str[i] = '_'; - } - } - return str; -} -function encodeRFC5987ValueChars(str) { - return encodeURIComponent(str). - // Note that although RFC3986 reserves "!", RFC5987 does not, - // so we do not need to escape it - replace(/['()]/g, escape). // i.e., %27 %28 %29 - replace(/\*/g, '%2A'). - // The following are not required for percent-encoding per RFC5987, - // so we can allow for a little better readability over the wire: |`^ - replace(/%(?:7C|60|5E)/g, unescape); -} -function getContentDisposition (opt_filename, opt_useragent, opt_type) { - let type = opt_type || constants.CONTENT_DISPOSITION_ATTACHMENT; - return contentDisposition(opt_filename, {type: type}); -} -exports.getContentDisposition = getContentDisposition; -function raiseError(ro, code, msg) { - ro.abort(); - let error = new Error(msg); - error.code = code; - ro.emit('error', error); -} -function raiseErrorObj(ro, error) { - ro.abort(); - ro.emit('error', error); -} -function isRedirectResponse(response) { - //All header names are lower cased and can be accessed using the bracket notation. - return response && response.status >= 300 && response.status < 400 && !!response.headers['location']; -} - -function isAllowDirectRequest(ctx, uri, isInJwtToken) { - let res = false; - const tenExternalRequestDirectIfIn = ctx.getCfg('externalRequest.directIfIn', cfgExternalRequestDirectIfIn); - let allowList = tenExternalRequestDirectIfIn.allowList; - if (allowList.length > 0) { - let allowIndex = allowList.findIndex((allowPrefix) => { - return uri.startsWith(allowPrefix); - }, uri); - res = -1 !== allowIndex; - ctx.logger.debug("isAllowDirectRequest check allow list res=%s", res); - } else if (tenExternalRequestDirectIfIn.jwtToken) { - res = isInJwtToken; - ctx.logger.debug("isAllowDirectRequest url in jwt token res=%s", res); - } - return res; -} -function addExternalRequestOptions(ctx, uri, isInJwtToken, options, httpAgentOptions, httpsAgentOptions) { - let res = false; - const tenExternalRequestAction = ctx.getCfg('externalRequest.action', cfgExternalRequestAction); - const tenRequestFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); - if (isAllowDirectRequest(ctx, uri, isInJwtToken)) { - res = true; - } else if (tenExternalRequestAction.allow) { - res = true; - if (tenExternalRequestAction.blockPrivateIP) { - options.httpsAgent = new RequestFilteringHttpsAgent({ - ...httpsAgentOptions, - ...tenRequestFilteringAgent - }); - options.httpAgent = new RequestFilteringHttpAgent({ - ...httpAgentOptions, - ...tenRequestFilteringAgent - }); - } - if (tenExternalRequestAction.proxyUrl) { - const proxyUrl = tenExternalRequestAction.proxyUrl; - const parsedProxyUrl = url.parse(proxyUrl); - - options.proxy = { - host: parsedProxyUrl.hostname, - port: parsedProxyUrl.port, - protocol: parsedProxyUrl.protocol - }; - } - - if (tenExternalRequestAction.proxyUser?.username) { - //This will set an `Proxy-Authorization` header, overwriting any existing - //`Proxy-Authorization` custom headers you have set using `headers`. - options.proxy.auth = tenExternalRequestAction.proxyUser; - } - if (tenExternalRequestAction.proxyHeaders) { - options.headers = { - ...options.headers, - ...tenExternalRequestAction.proxyHeaders - }; - } - } - return res; -} -/* - * @param {object} options - The options object to modify. - */ -function changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions) { - if (false === options.followRedirect) { - options.maxRedirects = 0; - } - if (false === options.gzip) { - options.headers = { ...options.headers, 'Accept-Encoding': 'identity' }; - delete options.gzip; - } - if (options.forever !== undefined) { - httpAgentOptions.keepAlive = !!options.forever; - httpsAgentOptions.keepAlive = !!options.forever; - } -} -/* - * Download a URL and return the response. - * @param {operationContext.Context} ctx - The operation context. - * @param {string} uri - The URL to download. - * @param {object} optTimeout - Optional timeout configuration. - * @param {number} optLimit - Optional limit on the size of the response. - * @param {string} opt_Authorization - Optional authorization header. - * @param {boolean} opt_filterPrivate - Optional flag to filter private requests. - * @param {object} opt_headers - Optional headers to include in the request. - * @param {boolean} opt_returnStream - Optional flag to return stream. - * @returns {Promise<{response: axios.AxiosResponse, sha256: string|null, body: Buffer|null, stream: NodeJS.ReadableStream|null}>} - A promise that resolves to object containing response, sha256 hash, and body (null if opt_streamWriter is provided). - */ -async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_returnStream) { - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); - const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); - const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - let sizeLimit = optLimit || Number.MAX_VALUE; - uri = URI.serialize(URI.parse(uri)); - const options = config.util.cloneDeep(tenTenantRequestDefaults); - - //baseRequest creates new agent(win-ca injects in globalAgent) - const httpsAgentOptions = { ...https.globalAgent.options, ...options}; - const httpAgentOptions = { ...http.globalAgent.options, ...options}; - changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); - - // if (optTimeout.connectionAndInactivity) { - // httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - // httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - // } - - if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options, httpAgentOptions, httpsAgentOptions)) { - throw new Error('Block external request. See externalRequest config options'); - } - - if (!options.httpsAgent || !options.httpAgent) { - options.httpsAgent = new https.Agent(httpsAgentOptions); - options.httpAgent = new http.Agent(httpAgentOptions); - } - - const headers = { ...options.headers }; - if (opt_Authorization) { - headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; - } - if (opt_headers) { - Object.assign(headers, opt_headers); - } - - const axiosConfig = { - ...options, - url: uri, - method: 'GET', - responseType: 'stream', - headers, - validateStatus: (status) => status >= 200 && status < 300, - signal: optTimeout.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, - timeout: optTimeout.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, - // cancelToken: new axios.CancelToken(cancel => { - // if (optTimeout?.wholeCycle) { - // setTimeout(() => { - // cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); - // }, ms(optTimeout.wholeCycle)); - // } - // }), - }; - try { - const response = await axios(axiosConfig); - const { status, headers } = response; - if (![200, 206].includes(status)) { - const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)};`); - error.statusCode = status; - error.response = response; - throw error; - } - - const contentLength = headers['content-length']; - if (contentLength && parseInt(contentLength) > sizeLimit) { - // Close the stream to prevent downloading - const error = new Error('EMSGSIZE: Error response: content-length:' + contentLength); - error.code = 'EMSGSIZE'; - response.data.destroy(error); - throw error; - } - const limitedStream = new SizeLimitStream(optLimit); - if (opt_returnStream) { - // When returning a stream, we'll return the response for the caller to handle streaming - // The content-length check is already done above - return { response, sha256: null, body: null, stream: response.data.pipe(limitedStream) }; - } - - const body = await pipeline(response.data, limitedStream, buffer); - const sha256 = crypto.createHash('sha256').update(body).digest('hex'); - return { response, sha256, body, stream: null }; - } catch (err) { - if('ERR_CANCELED' === err.code) { - err.code = 'ETIMEDOUT'; - } else if(['ECONNABORTED', 'ECONNRESET'].includes(err.code)) { - err.code = 'ESOCKETTIMEDOUT'; - } - if (err.status){ - err.statusCode = err.status; - } - throw err; - } -} - -async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_isInJwtToken, opt_headers) { - const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); - const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); - const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); - let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity); - const wholeCycleTimeout = optTimeout?.wholeCycle ? ms(optTimeout.wholeCycle) : undefined; - uri = URI.serialize(URI.parse(uri)); - let options = { ...tenTenantRequestDefaults }; - Object.assign(options, { - method: 'post', - url: uri, - timeout: connectionAndInactivity, - validateStatus: (status) => status === 200 || status === 204 - }); - - if (options.gzip !== undefined && !options.gzip) { - options.headers = { ...options.headers, 'Accept-Encoding': 'identity' }; - delete options.gzip; - } - - if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options, http.globalAgent.options, https.globalAgent.options)) { - throw new Error('Block external request. See externalRequest config options'); - } - const protocol = new URL(uri).protocol; - if (!options.httpsAgent && !options.httpAgent) { - const agentOptions = { - ...https.globalAgent.options, - rejectUnauthorized: tenTenantRequestDefaults.rejectUnauthorized === false ? false : true - }; - - if (tenTenantRequestDefaults.forever !== undefined) { - agentOptions.keepAlive = !!tenTenantRequestDefaults.forever; - } - - if (protocol === 'https:') { - options.httpsAgent = new https.Agent(agentOptions); - } else if (protocol === 'http:') { - options.httpAgent = new http.Agent(agentOptions); - } - } - if (postData) { - options.data = postData; - } else if (postDataStream) { - options.data = postDataStream; - } - options.headers = options.headers || {}; - if (opt_Authorization) { - //todo ctx.getCfg - options.headers[tenTokenOutboxHeader] = `${tenTokenOutboxPrefix}${opt_Authorization}`; - } - if (opt_headers) { - Object.assign(options.headers, opt_headers); - } - if (undefined !== postDataSize) { - //If no Content-Length is set, data will automatically be encoded in HTTP Chunked transfer encoding, - //so that server knows when the data ends. The Transfer-Encoding: chunked header is added. - //https://nodejs.org/api/http.html#requestwritechunk-encoding-callback - //issue with Transfer-Encoding: chunked wopi and sharepoint 2019 - //https://community.alteryx.com/t5/Dev-Space/Download-Tool-amp-Microsoft-SharePoint-Chunked-Request-Error/td-p/735824 - options.headers['Content-Length'] = postDataSize; - } - const cancelTokenSource = axios.CancelToken.source(); - if (wholeCycleTimeout) { - setTimeout(() => { - cancelTokenSource.cancel(`Whole request cycle timeout: ${optTimeout.wholeCycle}`); - }, wholeCycleTimeout); - } - options.cancelToken = cancelTokenSource.token; - try { - const response = await axios(options); - return { - response: { - statusCode: response.status, - headers: response.headers, - body: response.data - }, - body: JSON.stringify(response.data) - } - } catch (error) { - if (axios.isCancel(error)) { - const err = new Error(error.message); - err.code = 'ETIMEDOUT'; - throw err; - } - if (error.response) { - const { status, headers, data } = error.response; - const err = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); - err.statusCode = status; - err.response = error.response; - throw err; - } - throw error; - } -} -exports.postRequestPromise = postRequestPromise; -exports.downloadUrlPromise = downloadUrlPromise; -exports.mapAscServerErrorToOldError = function(error) { - var res = -1; - switch (error) { - case constants.NO_ERROR : - case constants.CONVERT_CELLLIMITS : - res = 0; - break; - case constants.TASK_QUEUE : - case constants.TASK_RESULT : - res = -6; - break; - case constants.CONVERT_PASSWORD : - case constants.CONVERT_DRM : - case constants.CONVERT_DRM_UNSUPPORTED : - res = -5; - break; - case constants.CONVERT_DOWNLOAD : - res = -4; - break; - case constants.CONVERT_TIMEOUT : - case constants.CONVERT_DEAD_LETTER : - res = -2; - break; - case constants.CONVERT_PARAMS : - res = -7; - break; - case constants.CONVERT_LIMITS : - res = -10; - break; - case constants.CONVERT_NEED_PARAMS : - case constants.CONVERT_LIBREOFFICE : - case constants.CONVERT_CORRUPTED : - case constants.CONVERT_UNKNOWN_FORMAT : - case constants.CONVERT_READ_FILE : - case constants.CONVERT_TEMPORARY : - case constants.CONVERT : - res = -3; - break; - case constants.CONVERT_DETECT : - res = -9; - break; - case constants.VKEY : - case constants.VKEY_ENCRYPT : - case constants.VKEY_KEY_EXPIRE : - case constants.VKEY_USER_COUNT_EXCEED : - res = -8; - break; - case constants.STORAGE : - case constants.STORAGE_FILE_NO_FOUND : - case constants.STORAGE_READ : - case constants.STORAGE_WRITE : - case constants.STORAGE_REMOVE_DIR : - case constants.STORAGE_CREATE_DIR : - case constants.STORAGE_GET_INFO : - case constants.UPLOAD : - case constants.READ_REQUEST_STREAM : - case constants.UNKNOWN : - res = -1; - break; - } - return res; -}; -function fillXmlResponse(val) { - var xml = ''; - if (undefined != val.error) { - xml += '' + exports.encodeXml(val.error.toString()) + ''; - } else { - if (val.fileUrl) { - xml += '' + exports.encodeXml(val.fileUrl) + ''; - } else { - xml += ''; - } - if (val.fileType) { - xml += '' + exports.encodeXml(val.fileType) + ''; - } else { - xml += ''; - } - xml += '' + val.percent + ''; - xml += '' + (val.endConvert ? 'True' : 'False') + ''; - } - xml += ''; - return xml; -} - -function fillResponseSimple(res, str, contentType) { - let body = Buffer.from(str, 'utf-8'); - res.setHeader('Content-Type', contentType + '; charset=UTF-8'); - res.setHeader('Content-Length', body.length); - res.send(body); -} -function _fillResponse(res, output, isJSON) { - let data; - let contentType; - if (isJSON) { - data = JSON.stringify(output); - contentType = 'application/json'; - } else { - data = fillXmlResponse(output); - contentType = 'text/xml'; - } - fillResponseSimple(res, data, contentType); -} - -function fillResponse(req, res, convertStatus, isJSON) { - let output; - if (constants.NO_ERROR != convertStatus.err) { - output = {error: exports.mapAscServerErrorToOldError(convertStatus.err)}; - } else { - output = {fileUrl: convertStatus.url, fileType: convertStatus.filetype, percent: (convertStatus.end ? 100 : 0), endConvert: convertStatus.end}; - } - const accepts = isJSON ? ['json', 'xml'] : ['xml', 'json']; - switch (req.accepts(accepts)) { - case 'json': - isJSON = true; - break; - case 'xml': - isJSON = false; - break; - } - _fillResponse(res, output, isJSON); -} - -exports.fillResponseSimple = fillResponseSimple; -exports.fillResponse = fillResponse; - -function fillResponseBuilder(res, key, urls, end, error) { - let output; - if (constants.NO_ERROR != error) { - output = {error: exports.mapAscServerErrorToOldError(error)}; - } else { - output = {key: key, urls: urls, end: end}; - } - _fillResponse(res, output, true); -} - -exports.fillResponseBuilder = fillResponseBuilder; - -function promiseCreateWriteStream(strPath, optOptions) { - return new Promise(function(resolve, reject) { - var file = fs.createWriteStream(strPath, optOptions); - var errorCallback = function(e) { - reject(e); - }; - file.on('error', errorCallback); - file.on('open', function() { - file.removeListener('error', errorCallback); - resolve(file); - }); - }); -}; -exports.promiseCreateWriteStream = promiseCreateWriteStream; - -function promiseWaitDrain(stream) { - return new Promise(function(resolve, reject) { - stream.once('drain', resolve); - }); -} -exports.promiseWaitDrain = promiseWaitDrain; - -function promiseWaitClose(stream) { - return new Promise(function(resolve, reject) { - stream.once('close', resolve); - }); -} -exports.promiseWaitClose = promiseWaitClose; - -function promiseCreateReadStream(strPath) { - return new Promise(function(resolve, reject) { - var file = fs.createReadStream(strPath); - var errorCallback = function(e) { - reject(e); - }; - file.on('error', errorCallback); - file.on('open', function() { - file.removeListener('error', errorCallback); - resolve(file); - }); - }); -}; -exports.promiseCreateReadStream = promiseCreateReadStream; -exports.compareStringByLength = function(x, y) { - if (x && y) { - if (x.length == y.length) { - return x.localeCompare(y); - } else { - return x.length - y.length; - } - } else { - if (null != x) { - return 1; - } else if (null != y) { - return -1; - } - } - return 0; -}; -exports.promiseRedis = function(client, func) { - var newArguments = Array.prototype.slice.call(arguments, 2); - return new Promise(function(resolve, reject) { - newArguments.push(function(err, data) { - if (err) { - reject(err); - } else { - resolve(data); - } - }); - func.apply(client, newArguments); - }); -}; -exports.containsAllAscii = function(str) { - return /^[\000-\177]*$/.test(str); -}; -function containsAllAsciiNP(str) { - return /^[\040-\176]*$/.test(str);//non-printing characters -} -exports.containsAllAsciiNP = containsAllAsciiNP; -function getDomain(hostHeader, forwardedHostHeader) { - return forwardedHostHeader || hostHeader || 'localhost'; -}; -function getBaseUrl(protocol, hostHeader, forwardedProtoHeader, forwardedHostHeader, forwardedPrefixHeader) { - var url = ''; - if (forwardedProtoHeader && constants.ALLOWED_PROTO.test(forwardedProtoHeader)) { - url += forwardedProtoHeader; - } else if (protocol && constants.ALLOWED_PROTO.test(protocol)) { - url += protocol; - } else { - url += 'http'; - } - url += '://'; - url += getDomain(hostHeader, forwardedHostHeader); - if (forwardedPrefixHeader) { - url += forwardedPrefixHeader; - } - return url; -} -function getBaseUrlByConnection(ctx, conn) { - conn = conn.request; - //Header names are lower-cased. https://nodejs.org/api/http.html#messageheaders - let cloudfrontForwardedProto = conn.headers['cloudfront-forwarded-proto']; - let forwardedProto = conn.headers['x-forwarded-proto']; - let forwardedHost = conn.headers['x-forwarded-host']; - let forwardedPrefix = conn.headers['x-forwarded-prefix']; - let host = conn.headers['host']; - let proto = cloudfrontForwardedProto || forwardedProto; - ctx.logger.debug(`getBaseUrlByConnection host=%s x-forwarded-host=%s x-forwarded-proto=%s x-forwarded-prefix=%s cloudfront-forwarded-proto=%s `, - host, forwardedHost, forwardedProto, forwardedPrefix, cloudfrontForwardedProto); - return getBaseUrl('', host, proto, forwardedHost, forwardedPrefix); -} -function getBaseUrlByRequest(ctx, req) { - //case-insensitive match. https://expressjs.com/en/api.html#req.get - let cloudfrontForwardedProto = req.get('cloudfront-forwarded-proto'); - let forwardedProto = req.get('x-forwarded-proto'); - let forwardedHost = req.get('x-forwarded-host'); - let forwardedPrefix = req.get('x-forwarded-prefix'); - let host = req.get('host'); - let protocol = req.protocol; - let proto = cloudfrontForwardedProto || forwardedProto; - ctx.logger.debug(`getBaseUrlByRequest protocol=%s host=%s x-forwarded-host=%s x-forwarded-proto=%s x-forwarded-prefix=%s cloudfront-forwarded-proto=%s `, - protocol, host, forwardedHost, forwardedProto, forwardedPrefix, cloudfrontForwardedProto); - return getBaseUrl(protocol, host, proto, forwardedHost, forwardedPrefix); -} -exports.getBaseUrlByConnection = getBaseUrlByConnection; -exports.getBaseUrlByRequest = getBaseUrlByRequest; -function getDomainByConnection(ctx, conn) { - let incomingMessage = conn.request; - let host = incomingMessage.headers['host']; - let forwardedHost = incomingMessage.headers['x-forwarded-host']; - ctx.logger.debug("getDomainByConnection headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost); - return getDomain(host, forwardedHost); -} -function getDomainByRequest(ctx, req) { - let host = req.get('host'); - let forwardedHost = req.get('x-forwarded-host'); - ctx.logger.debug("getDomainByRequest headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost); - return getDomain(req.get('host'), req.get('x-forwarded-host')); -} -exports.getDomainByConnection = getDomainByConnection; -exports.getDomainByRequest = getDomainByRequest; -function getShardKeyByConnection(ctx, conn) { - return conn?.handshake?.query?.[constants.SHARD_KEY_API_NAME]; -} -function getWopiSrcByConnection(ctx, conn) { - return conn?.handshake?.query?.[constants.SHARD_KEY_WOPI_NAME]; -} -function getShardKeyByRequest(ctx, req) { - return req.query?.[constants.SHARD_KEY_API_NAME]; -} -function getWopiSrcByRequest(ctx, req) { - return req.query?.[constants.SHARD_KEY_WOPI_NAME]; -} -exports.getShardKeyByConnection = getShardKeyByConnection; -exports.getWopiSrcByConnection = getWopiSrcByConnection; -exports.getShardKeyByRequest = getShardKeyByRequest; -exports.getWopiSrcByRequest = getWopiSrcByRequest; -function stream2Buffer(stream) { - return new Promise(function(resolve, reject) { - if (!stream.readable) { - resolve(Buffer.alloc(0)); - } - var bufs = []; - stream.on('data', function(data) { - bufs.push(data); - }); - function onEnd(err) { - if (err) { - reject(err); - } else { - resolve(Buffer.concat(bufs)); - } - } - stream.on('end', onEnd); - stream.on('error', onEnd); - }); -} -exports.stream2Buffer = stream2Buffer; -function changeOnlyOfficeUrl(inputUrl, strPath, optFilename) { - //onlyoffice file server expects url end with file extension - if (-1 == inputUrl.indexOf('?')) { - inputUrl += '?'; - } else { - inputUrl += '&'; - } - return inputUrl + constants.ONLY_OFFICE_URL_PARAM + '=' + constants.OUTPUT_NAME + path.extname(optFilename || strPath); -} -exports.changeOnlyOfficeUrl = changeOnlyOfficeUrl; -function pipeStreams(from, to, isEnd) { - return new Promise(function(resolve, reject) { - from.pipe(to, {end: isEnd}); - from.on('end', function() { - resolve(); - }); - from.on('error', function(e) { - reject(e); - }); - }); -} -exports.pipeStreams = pipeStreams; -function* pipeFiles(from, to) { - var fromStream = yield promiseCreateReadStream(from); - var toStream = yield promiseCreateWriteStream(to); - yield pipeStreams(fromStream, toStream, true); -} -exports.pipeFiles = co.wrap(pipeFiles); -function checkIpFilter(ctx, ipString, opt_hostname) { - const tenIpFilterRules = ctx.getCfg('services.CoAuthoring.ipfilter.rules', cfgIpFilterRules); - - var status = 0; - var ip4; - var ip6; - if (ipaddr.isValid(ipString)) { - var ip = ipaddr.parse(ipString); - if ('ipv6' === ip.kind()) { - if (ip.isIPv4MappedAddress()) { - ip4 = ip.toIPv4Address().toString(); - } - ip6 = ip.toNormalizedString(); - } else { - ip4 = ip.toString(); - ip6 = ip.toIPv4MappedAddress().toNormalizedString(); - } - } - - for (let i = 0; i < tenIpFilterRules.length; ++i) { - let rule = tenIpFilterRules[i]; - let exp = getIpFilterRule(rule.address); - if ((opt_hostname && exp.test(opt_hostname)) || (ip4 && exp.test(ip4)) || (ip6 && exp.test(ip6))) { - if (!rule.allowed) { - const tenIpFilterErrorCode = ctx.getCfg('services.CoAuthoring.ipfilter.errorcode', cfgIpFilterErrorCode); - status = tenIpFilterErrorCode; - } - break; - } - } - return status; -} -exports.checkIpFilter = checkIpFilter; -function* checkHostFilter(ctx, hostname) { - let status = 0; - let hostIp; - try { - hostIp = yield dnsLookup(hostname); - } catch (e) { - const tenIpFilterErrorCode = ctx.getCfg('services.CoAuthoring.ipfilter.errorcode', cfgIpFilterErrorCode); - status = tenIpFilterErrorCode; - ctx.logger.error('dnsLookup error: hostname = %s %s', hostname, e.stack); - } - if (0 === status) { - status = checkIpFilter(ctx, hostIp, hostname); - } - return status; -} -exports.checkHostFilter = checkHostFilter; -function checkClientIp(req, res, next) { - let ctx = new operationContext.Context(); - ctx.initFromRequest(req); - const tenIpFilterUseForRequest = ctx.getCfg('services.CoAuthoring.ipfilter.useforrequest', cfgIpFilterUseForRequest); - let status = 0; - if (tenIpFilterUseForRequest) { - const addresses = forwarded(req); - const ipString = addresses[addresses.length - 1]; - status = checkIpFilter(ctx, ipString); - } - if (status > 0) { - res.sendStatus(status); - } else { - next(); - } -} -exports.checkClientIp = checkClientIp; -function lowercaseQueryString(req, res, next) { - for (var key in req.query) { - if (req.query.hasOwnProperty(key) && key.toLowerCase() !== key) { - req.query[key.toLowerCase()] = req.query[key]; - delete req.query[key]; - } - } - next(); -} -exports.lowercaseQueryString = lowercaseQueryString; -function dnsLookup(hostname, options) { - return new Promise(function(resolve, reject) { - dnscache.lookup(hostname, options, function(err, addresses){ - if (err) { - reject(err); - } else { - resolve(addresses); - } - }); - }); -} -exports.dnsLookup = dnsLookup; -function isEmptyObject(val) { - return !(val && Object.keys(val).length); -} -exports.isEmptyObject = isEmptyObject; -function getSecretByElem(secretElem) { - let secret; - if (secretElem) { - if (secretElem.string) { - secret = secretElem.string; - } else if (secretElem.file) { - secret = pemfileCache.get(secretElem.file); - if (!secret) { - secret = fs.readFileSync(secretElem.file); - pemfileCache.set(secretElem.file, secret); - } - } - } - return secret; -} -exports.getSecretByElem = getSecretByElem; -function fillJwtForRequest(ctx, payload, secret, opt_inBody) { - const tenTokenOutboxAlgorithm = ctx.getCfg('services.CoAuthoring.token.outbox.algorithm', cfgTokenOutboxAlgorithm); - const tenTokenOutboxExpires = ctx.getCfg('services.CoAuthoring.token.outbox.expires', cfgTokenOutboxExpires); - //todo refuse prototypes in payload(they are simple getter/setter). - //JSON.parse/stringify is more universal but Object.assign is enough for our inputs - payload = Object.assign(Object.create(null), payload); - let data; - if (opt_inBody) { - data = payload; - } else { - data = {payload: payload}; - } - - let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires}; - return jwt.sign(data, secret, options); -} -exports.fillJwtForRequest = fillJwtForRequest; -exports.forwarded = forwarded; -exports.getIndexFromUserId = function(userId, userIdOriginal){ - return parseInt(userId.substring(userIdOriginal.length)); -}; -exports.checkPathTraversal = function(ctx, docId, rootDirectory, filename) { - if (filename.indexOf('\0') !== -1) { - ctx.logger.warn('checkPathTraversal Poison Null Bytes filename=%s', filename); - return false; - } - if (!filename.startsWith(rootDirectory)) { - ctx.logger.warn('checkPathTraversal Path Traversal filename=%s', filename); - return false; - } - return true; -}; -exports.getConnectionInfo = function(conn){ - var user = conn.user; - var data = { - id: user.id, - idOriginal: user.idOriginal, - username: user.username, - indexUser: user.indexUser, - view: user.view, - connectionId: conn.id, - isCloseCoAuthoring: conn.isCloseCoAuthoring, - isLiveViewer: exports.isLiveViewer(conn), - encrypted: conn.encrypted - }; - return data; -}; -exports.getConnectionInfoStr = function(conn){ - return JSON.stringify(exports.getConnectionInfo(conn)); -}; -exports.isLiveViewer = function(conn){ - return conn.user?.view && "fast" === conn.coEditingMode; -}; -exports.isLiveViewerSupport = function(licenseInfo){ - return licenseInfo.connectionsView > 0 || licenseInfo.usersViewCount > 0; -}; -exports.canIncludeOutboxAuthorization = function (ctx, url) { - const tenTokenEnableRequestOutbox = ctx.getCfg('services.CoAuthoring.token.enable.request.outbox', cfgTokenEnableRequestOutbox); - const tenTokenOutboxUrlExclusionRegex = ctx.getCfg('services.CoAuthoring.token.outbox.urlExclusionRegex', cfgTokenOutboxUrlExclusionRegex); - if (tenTokenEnableRequestOutbox) { - if (!tenTokenOutboxUrlExclusionRegex) { - return true; - } else if (!new RegExp(escapeStringRegexp(tenTokenOutboxUrlExclusionRegex)).test(url)) { - return true; - } else { - ctx.logger.debug('canIncludeOutboxAuthorization excluded by token.outbox.urlExclusionRegex url=%s', url); - } - } - return false; -}; -/* - Code samples taken from here: https://gist.github.com/btxtiger/e8eaee70d6e46729d127f1e384e755d6 - */ -exports.encryptPassword = async function (ctx, password) { - const pbkdf2Promise = util.promisify(crypto.pbkdf2); - const tenSecret = ctx.getCfg('aesEncrypt.secret', cfgSecret); - const tenAESConfig = ctx.getCfg('aesEncrypt.config', cfgAESConfig) ?? {}; - const { - keyByteLength = 32, - saltByteLength = 64, - initializationVectorByteLength = 16, - iterationsByteLength = 5 - } = tenAESConfig; - - const salt = crypto.randomBytes(saltByteLength); - const initializationVector = crypto.randomBytes(initializationVectorByteLength); - - const iterationsLength = iterationsByteLength < minimumIterationsByteLength ? minimumIterationsByteLength : iterationsByteLength; - // Generate random count of iterations; 10.000 - 99.999 -> 5 bytes - const lowerNumber = Math.pow(10, iterationsLength - 1); - const greaterNumber = Math.pow(10, iterationsLength) - 1; - const iterations = Math.floor(Math.random() * (greaterNumber - lowerNumber)) + lowerNumber; - - const encryptionKey = await pbkdf2Promise(tenSecret, salt, iterations, keyByteLength, 'sha512'); - //todo chacha20-poly1305 (clean db) - const cipher = crypto.createCipheriv('aes-256-gcm', encryptionKey, initializationVector, {authTagLength:16}); - const encryptedData = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]); - const authTag = cipher.getAuthTag(); - const predicate = iterations.toString(16); - const data = Buffer.concat([salt, initializationVector, authTag, encryptedData]).toString('hex'); - - return `${predicate}:${data}`; -}; -exports.decryptPassword = async function (ctx, password) { - const pbkdf2Promise = util.promisify(crypto.pbkdf2); - const tenSecret = ctx.getCfg('aesEncrypt.secret', cfgSecret); - const tenAESConfig = ctx.getCfg('aesEncrypt.config', cfgAESConfig) ?? {}; - const { - keyByteLength = 32, - saltByteLength = 64, - initializationVectorByteLength = 16, - } = tenAESConfig; - - const [iterations, dataHex] = password.split(':'); - const data = Buffer.from(dataHex, 'hex'); - // authTag in node.js equals 16 bytes(128 bits), see https://stackoverflow.com/questions/33976117/does-node-js-crypto-use-fixed-tag-size-with-gcm-mode - const delta = [saltByteLength, initializationVectorByteLength, 16]; - const pointerArray = []; - - for (let byte = 0, i = 0; i < delta.length; i++) { - const deltaValue = delta[i]; - pointerArray.push(data.subarray(byte, byte + deltaValue)); - byte += deltaValue; - - if (i === delta.length - 1) { - pointerArray.push(data.subarray(byte)); - } - } - - const [ - salt, - initializationVector, - authTag, - encryptedData - ] = pointerArray; - - const decryptionKey = await pbkdf2Promise(tenSecret, salt, parseInt(iterations, 16), keyByteLength, 'sha512'); - const decipher = crypto.createDecipheriv('aes-256-gcm', decryptionKey, initializationVector, {authTagLength:16}); - decipher.setAuthTag(authTag); - - return Buffer.concat([decipher.update(encryptedData, 'binary'), decipher.final()]).toString(); -}; -exports.getDateTimeTicks = function(date) { - return BigInt(date.getTime() * 10000) + 621355968000000000n; -}; -exports.convertLicenseInfoToFileParams = function(licenseInfo) { - // todo - // { - // user_quota = 0; - // portal_count = 0; - // process = 2; - // ssbranding = false; - // whiteLabel = false; - // } - let license = {}; - license.start_date = licenseInfo.startDate && licenseInfo.startDate.toJSON(); - license.end_date = licenseInfo.endDate && licenseInfo.endDate.toJSON(); - license.timelimited = 0 !== (constants.LICENSE_MODE.Limited & licenseInfo.mode); - license.trial = 0 !== (constants.LICENSE_MODE.Trial & licenseInfo.mode); - license.developer = 0 !== (constants.LICENSE_MODE.Developer & licenseInfo.mode); - license.branding = licenseInfo.branding; - license.customization = licenseInfo.customization; - license.advanced_api = licenseInfo.advancedApi; - license.connections = licenseInfo.connections; - license.connections_view = licenseInfo.connectionsView; - license.users_count = licenseInfo.usersCount; - license.users_view_count = licenseInfo.usersViewCount; - license.users_expire = licenseInfo.usersExpire / constants.LICENSE_EXPIRE_USERS_ONE_DAY; - license.customer_id = licenseInfo.customerId; - license.alias = licenseInfo.alias; - license.multitenancy = licenseInfo.multitenancy; - return license; -}; -exports.convertLicenseInfoToServerParams = function(licenseInfo) { - let license = {}; - license.workersCount = licenseInfo.count; - license.resultType = licenseInfo.type; - license.packageType = licenseInfo.packageType; - license.buildDate = licenseInfo.buildDate && licenseInfo.buildDate.toJSON(); - license.buildVersion = commonDefines.buildVersion; - license.buildNumber = commonDefines.buildNumber; - return license; -}; -exports.checkBaseUrl = function(ctx, baseUrl, opt_storageCfg) { - let storageExternalHost = opt_storageCfg ? opt_storageCfg.externalHost : cfgStorageExternalHost - const tenStorageExternalHost = ctx.getCfg('storage.externalHost', storageExternalHost); - return tenStorageExternalHost ? tenStorageExternalHost : baseUrl; -}; -exports.resolvePath = function(object, path, defaultValue) { - return path.split('.').reduce((o, p) => o ? o[p] : defaultValue, object); -}; -Date.isLeapYear = function (year) { - return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); -}; - -Date.getDaysInMonth = function (year, month) { - return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; -}; - -Date.prototype.isLeapYear = function () { - return Date.isLeapYear(this.getUTCFullYear()); -}; - -Date.prototype.getDaysInMonth = function () { - return Date.getDaysInMonth(this.getUTCFullYear(), this.getUTCMonth()); -}; - -Date.prototype.addMonths = function (value) { - var n = this.getUTCDate(); - this.setUTCDate(1); - this.setUTCMonth(this.getUTCMonth() + value); - this.setUTCDate(Math.min(n, this.getDaysInMonth())); - return this; -}; -function getMonthDiff(d1, d2) { - var months; - months = (d2.getUTCFullYear() - d1.getUTCFullYear()) * 12; - months -= d1.getUTCMonth(); - months += d2.getUTCMonth(); - return months; -} -exports.getMonthDiff = getMonthDiff; - -/** - * A Transform stream that limits the size of data passing through it. - * It will throw an EMSGSIZE error if the size exceeds the limit. - * - * @class SizeLimitStream - * @extends {Transform} - */ -class SizeLimitStream extends Transform { - /** - * Creates an instance of SizeLimitStream. - * @param {number} sizeLimit - Maximum size in bytes that can pass through the stream - * @memberof SizeLimitStream - */ - constructor(sizeLimit) { - super(); - this.sizeLimit = sizeLimit; - this.bytesReceived = 0; - } - - /** - * Transform implementation that tracks the bytes received and enforces the size limit - * - * @param {Buffer|string} chunk - The chunk of data to process - * @param {string} encoding - The encoding of the chunk if it's a string - * @param {Function} callback - Called when processing is complete - * @memberof SizeLimitStream - */ - _transform(chunk, encoding, callback) { - this.bytesReceived += chunk.length; - - if (this.sizeLimit && this.bytesReceived > this.sizeLimit) { - const error = new Error(`EMSGSIZE: Response too large: ${this.bytesReceived} bytes (limit: ${this.sizeLimit} bytes)`); - error.code = 'EMSGSIZE'; - callback(error); - return; - } - - callback(null, chunk); - } -} -exports.getLicensePeriod = function(startDate, now) { - startDate = new Date(startDate.getTime());//clone - startDate.addMonths(getMonthDiff(startDate, now)); - if (startDate > now) { - startDate.addMonths(-1); - } - startDate.setUTCHours(0,0,0,0); - return startDate.getTime(); -}; - -exports.removeIllegalCharacters = function(filename) { - return filename?.replace(/[/\\?%*:|"<>]/g, '-') || filename; -} -exports.getFunctionArguments = function(func) { - return func.toString(). - replace(/[\r\n\s]+/g, ' '). - match(/(?:function\s*\w*)?\s*(?:\((.*?)\)|([^\s]+))/). - slice(1, 3). - join(''). - split(/\s*,\s*/); -}; -exports.isUselesSfc = function(row, cmd) { - return !(row && commonDefines.FileStatus.SaveVersion === row.status && cmd.getStatusInfoIn() === row.status_info); -}; -exports.getChangesFileHeader = function() { - return `CHANGES\t${commonDefines.buildVersion}\n`; -}; -exports.checksumFile = function(hashName, path) { - //https://stackoverflow.com/a/44643479 - return new Promise((resolve, reject) => { - const hash = crypto.createHash(hashName); - const stream = fs.createReadStream(path); - stream.on('error', err => reject(err)); - stream.on('data', chunk => hash.update(chunk)); - stream.on('end', () => resolve(hash.digest('hex'))); - }); -}; - -function isObject(item) { - return (item && typeof item === 'object' && !Array.isArray(item)); -} - -function deepMergeObjects(target, ...sources) { - if (!sources.length) { - return target; - } - - const source = sources.shift(); - if (isObject(target) && isObject(source)) { - for (const key in source) { - if (isObject(source[key])) { - if (!target[key]) { - Object.assign(target, { [key]: {} }); - } - - deepMergeObjects(target[key], source[key]); - } else { - Object.assign(target, { [key]: source[key] }); - } - } - } - - return deepMergeObjects(target, ...sources); -} -exports.isObject = isObject; -exports.deepMergeObjects = deepMergeObjects; +/* + * (c) Copyright Ascensio System SIA 2010-2024 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +'use strict'; + +//Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513) +require("tls").DEFAULT_ECDH_CURVE = "auto"; + +const { pipeline } = require('node:stream/promises'); +const { buffer } = require('node:stream/consumers'); +const { Transform } = require('stream'); +var config = require('config'); +var fs = require('fs'); +var path = require('path'); +const crypto = require('crypto'); +var url = require('url'); +var axios = require('axios'); +var co = require('co'); +var URI = require("uri-js"); +const escapeStringRegexp = require('escape-string-regexp'); +const ipaddr = require('ipaddr.js'); +const getDnsCache = require('dnscache'); +const jwt = require('jsonwebtoken'); +const NodeCache = require( "node-cache" ); +const ms = require('ms'); +const constants = require('./constants'); +const commonDefines = require('./commondefines'); +const forwarded = require('forwarded'); +const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent } = require("request-filtering-agent"); +const https = require('https'); +const http = require('http'); +const ca = require('win-ca/api'); +const util = require('util'); + +const contentDisposition = require('content-disposition'); +const operationContext = require("./operationContext"); + +//Clone sealed config objects before passing to external libraries using config.util.cloneDeep +const cfgDnsCache = config.util.cloneDeep(config.get('dnscache')); +const cfgIpFilterRules = config.get('services.CoAuthoring.ipfilter.rules'); +const cfgIpFilterErrorCode = config.get('services.CoAuthoring.ipfilter.errorcode'); +const cfgIpFilterUseForRequest = config.get('services.CoAuthoring.ipfilter.useforrequest'); +const cfgExpPemStdTtl = config.get('services.CoAuthoring.expire.pemStdTTL'); +const cfgExpPemCheckPeriod = config.get('services.CoAuthoring.expire.pemCheckPeriod'); +const cfgTokenOutboxHeader = config.get('services.CoAuthoring.token.outbox.header'); +const cfgTokenOutboxPrefix = config.get('services.CoAuthoring.token.outbox.prefix'); +const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm'); +const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires'); +const cfgVisibilityTimeout = config.get('queue.visibilityTimeout'); +const cfgQueueRetentionPeriod = config.get('queue.retentionPeriod'); +const cfgRequestDefaults = config.util.cloneDeep(config.get('services.CoAuthoring.requestDefaults')); +const cfgTokenEnableRequestOutbox = config.get('services.CoAuthoring.token.enable.request.outbox'); +const cfgTokenOutboxUrlExclusionRegex = config.get('services.CoAuthoring.token.outbox.urlExclusionRegex'); +const cfgSecret = config.get('aesEncrypt.secret'); +const cfgAESConfig = config.util.cloneDeep(config.get('aesEncrypt.config')); +const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent'); +const cfgStorageExternalHost = config.get('storage.externalHost'); +const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn'); +const cfgExternalRequestAction = config.get('externalRequest.action'); +const cfgWinCa = config.util.cloneDeep(config.get('win-ca')); + +ca(cfgWinCa); + +const minimumIterationsByteLength = 4; +const dnscache = getDnsCache(cfgDnsCache); + +var ANDROID_SAFE_FILENAME = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~\'=()[]{}0123456789'; + +//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json +BigInt.prototype.toJSON = function() { return this.toString() }; + +var g_oIpFilterRules = new Map(); +function getIpFilterRule(address) { + let exp = g_oIpFilterRules.get(address); + if (!exp) { + let regExpStr = address.split('*').map(escapeStringRegexp).join('.*'); + exp = new RegExp('^' + regExpStr + '$', 'i'); + g_oIpFilterRules.set(address, exp); + } + return exp; +} +const pemfileCache = new NodeCache({stdTTL: ms(cfgExpPemStdTtl) / 1000, checkperiod: ms(cfgExpPemCheckPeriod) / 1000, errorOnMissing: false, useClones: true}); + +exports.getConvertionTimeout = function(opt_ctx) { + if (opt_ctx) { + const tenVisibilityTimeout = opt_ctx.getCfg('queue.visibilityTimeout', cfgVisibilityTimeout); + const tenQueueRetentionPeriod = opt_ctx.getCfg('queue.retentionPeriod', cfgQueueRetentionPeriod); + return 1.5 * (tenVisibilityTimeout + tenQueueRetentionPeriod) * 1000; + } else { + return 1.5 * (cfgVisibilityTimeout + cfgQueueRetentionPeriod) * 1000; + } +} + +exports.addSeconds = function(date, sec) { + date.setSeconds(date.getSeconds() + sec); +}; +exports.getMillisecondsOfHour = function(date) { + return (date.getUTCMinutes() * 60 + date.getUTCSeconds()) * 1000 + date.getUTCMilliseconds(); +}; +exports.encodeXml = function(value) { + return value.replace(/[<>&'"\r\n\t\xA0]/g, function (c) { + switch (c) { + case '<': return '<'; + case '>': return '>'; + case '&': return '&'; + case '\'': return '''; + case '"': return '"'; + case '\r': return ' '; + case '\n': return ' '; + case '\t': return ' '; + case '\xA0': return ' '; + } + }); +}; +function fsStat(fsPath) { + return new Promise(function(resolve, reject) { + fs.stat(fsPath, function(err, stats) { + if (err) { + reject(err); + } else { + resolve(stats); + } + }); + }); +} +exports.fsStat = fsStat; +function fsReadDir(fsPath) { + return new Promise(function(resolve, reject) { + fs.readdir(fsPath, function(err, list) { + if (err) { + return reject(err); + } else { + resolve(list); + } + }); + }); +} +function* walkDir(fsPath, results, optNoSubDir, optOnlyFolders) { + const list = yield fsReadDir(fsPath); + for (let i = 0; i < list.length; ++i) { + const file = path.join(fsPath, list[i]); + let stats; + try { + stats = yield fsStat(file); + } catch (e) { + //exception if fsPath not exist + stats = null; + } + if (!stats) { + continue; + } + if (stats.isDirectory()) { + if (optNoSubDir) { + optOnlyFolders && results.push(file); + } else { + yield* walkDir(file, results, optNoSubDir, optOnlyFolders); + } + } else { + !optOnlyFolders && results.push(file); + } + } +} +exports.listFolders = function(fsPath, optNoSubDir) { + return co(function* () { + let stats, list = []; + try { + stats = yield fsStat(fsPath); + } catch (e) { + //exception if fsPath not exist + stats = null; + } + if (stats && stats.isDirectory()) { + yield* walkDir(fsPath, list, optNoSubDir, true); + } + return list; + }); +}; +exports.listObjects = function(fsPath, optNoSubDir) { + return co(function* () { + let stats, list = []; + try { + stats = yield fsStat(fsPath); + } catch (e) { + //exception if fsPath not exist + stats = null; + } + if (stats) { + if (stats.isDirectory()) { + yield* walkDir(fsPath, list, optNoSubDir, false); + } else { + list.push(fsPath); + } + } + return list; + }); +}; +exports.sleep = function(ms) { + return new Promise(function(resolve) { + setTimeout(resolve, ms); + }); +}; +exports.readFile = function(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, function(err, data) { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + }); +}; +function makeAndroidSafeFileName(str) { + for (var i = 0; i < str.length; i++) { + if (-1 == ANDROID_SAFE_FILENAME.indexOf(str[i])) { + str[i] = '_'; + } + } + return str; +} +function encodeRFC5987ValueChars(str) { + return encodeURIComponent(str). + // Note that although RFC3986 reserves "!", RFC5987 does not, + // so we do not need to escape it + replace(/['()]/g, escape). // i.e., %27 %28 %29 + replace(/\*/g, '%2A'). + // The following are not required for percent-encoding per RFC5987, + // so we can allow for a little better readability over the wire: |`^ + replace(/%(?:7C|60|5E)/g, unescape); +} +function getContentDisposition (opt_filename, opt_useragent, opt_type) { + let type = opt_type || constants.CONTENT_DISPOSITION_ATTACHMENT; + return contentDisposition(opt_filename, {type: type}); +} +exports.getContentDisposition = getContentDisposition; +function raiseError(ro, code, msg) { + ro.abort(); + let error = new Error(msg); + error.code = code; + ro.emit('error', error); +} +function raiseErrorObj(ro, error) { + ro.abort(); + ro.emit('error', error); +} +function isRedirectResponse(response) { + //All header names are lower cased and can be accessed using the bracket notation. + return response && response.status >= 300 && response.status < 400 && !!response.headers['location']; +} + +function isAllowDirectRequest(ctx, uri, isInJwtToken) { + let res = false; + const tenExternalRequestDirectIfIn = ctx.getCfg('externalRequest.directIfIn', cfgExternalRequestDirectIfIn); + let allowList = tenExternalRequestDirectIfIn.allowList; + if (allowList.length > 0) { + let allowIndex = allowList.findIndex((allowPrefix) => { + return uri.startsWith(allowPrefix); + }, uri); + res = -1 !== allowIndex; + ctx.logger.debug("isAllowDirectRequest check allow list res=%s", res); + } else if (tenExternalRequestDirectIfIn.jwtToken) { + res = isInJwtToken; + ctx.logger.debug("isAllowDirectRequest url in jwt token res=%s", res); + } + return res; +} +function addExternalRequestOptions(ctx, uri, isInJwtToken, options, httpAgentOptions, httpsAgentOptions) { + let res = false; + const tenExternalRequestAction = ctx.getCfg('externalRequest.action', cfgExternalRequestAction); + const tenRequestFilteringAgent = ctx.getCfg('services.CoAuthoring.request-filtering-agent', cfgRequesFilteringAgent); + if (isAllowDirectRequest(ctx, uri, isInJwtToken)) { + res = true; + } else if (tenExternalRequestAction.allow) { + res = true; + if (tenExternalRequestAction.blockPrivateIP) { + options.httpsAgent = new RequestFilteringHttpsAgent({ + ...httpsAgentOptions, + ...tenRequestFilteringAgent + }); + options.httpAgent = new RequestFilteringHttpAgent({ + ...httpAgentOptions, + ...tenRequestFilteringAgent + }); + } + if (tenExternalRequestAction.proxyUrl) { + const proxyUrl = tenExternalRequestAction.proxyUrl; + const parsedProxyUrl = url.parse(proxyUrl); + + options.proxy = { + host: parsedProxyUrl.hostname, + port: parsedProxyUrl.port, + protocol: parsedProxyUrl.protocol + }; + } + + if (tenExternalRequestAction.proxyUser?.username) { + //This will set an `Proxy-Authorization` header, overwriting any existing + //`Proxy-Authorization` custom headers you have set using `headers`. + options.proxy.auth = tenExternalRequestAction.proxyUser; + } + if (tenExternalRequestAction.proxyHeaders) { + options.headers = { + ...options.headers, + ...tenExternalRequestAction.proxyHeaders + }; + } + } + return res; +} +/* + * @param {object} options - The options object to modify. + */ +function changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions) { + if (false === options.followRedirect) { + options.maxRedirects = 0; + } + if (false === options.gzip) { + options.headers = { ...options.headers, 'Accept-Encoding': 'identity' }; + delete options.gzip; + } + if (options.forever !== undefined) { + httpAgentOptions.keepAlive = !!options.forever; + httpsAgentOptions.keepAlive = !!options.forever; + } +} +/* + * Download a URL and return the response. + * @param {operationContext.Context} ctx - The operation context. + * @param {string} uri - The URL to download. + * @param {object} optTimeout - Optional timeout configuration. + * @param {number} optLimit - Optional limit on the size of the response. + * @param {string} opt_Authorization - Optional authorization header. + * @param {boolean} opt_filterPrivate - Optional flag to filter private requests. + * @param {object} opt_headers - Optional headers to include in the request. + * @param {boolean} opt_returnStream - Optional flag to return stream. + * @returns {Promise<{response: axios.AxiosResponse, sha256: string|null, body: Buffer|null, stream: NodeJS.ReadableStream|null}>} - A promise that resolves to object containing response, sha256 hash, and body (null if opt_streamWriter is provided). + */ +async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_returnStream) { + const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); + const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); + const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); + let sizeLimit = optLimit || Number.MAX_VALUE; + uri = URI.serialize(URI.parse(uri)); + const options = config.util.cloneDeep(tenTenantRequestDefaults); + + //baseRequest creates new agent(win-ca injects in globalAgent) + const httpsAgentOptions = { ...https.globalAgent.options, ...options}; + const httpAgentOptions = { ...http.globalAgent.options, ...options}; + changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); + + // if (optTimeout.connectionAndInactivity) { + // httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); + // httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); + // } + + if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options, httpAgentOptions, httpsAgentOptions)) { + throw new Error('Block external request. See externalRequest config options'); + } + + if (!options.httpsAgent || !options.httpAgent) { + options.httpsAgent = new https.Agent(httpsAgentOptions); + options.httpAgent = new http.Agent(httpAgentOptions); + } + + const headers = { ...options.headers }; + if (opt_Authorization) { + headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; + } + if (opt_headers) { + Object.assign(headers, opt_headers); + } + + const axiosConfig = { + ...options, + url: uri, + method: 'GET', + responseType: 'stream', + headers, + validateStatus: (status) => status >= 200 && status < 300, + signal: optTimeout.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, + timeout: optTimeout.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, + // cancelToken: new axios.CancelToken(cancel => { + // if (optTimeout?.wholeCycle) { + // setTimeout(() => { + // cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); + // }, ms(optTimeout.wholeCycle)); + // } + // }), + }; + try { + const response = await axios(axiosConfig); + const { status, headers } = response; + if (![200, 206].includes(status)) { + const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)};`); + error.statusCode = status; + error.response = response; + throw error; + } + + const contentLength = headers['content-length']; + if (contentLength && parseInt(contentLength) > sizeLimit) { + // Close the stream to prevent downloading + const error = new Error('EMSGSIZE: Error response: content-length:' + contentLength); + error.code = 'EMSGSIZE'; + response.data.destroy(error); + throw error; + } + const limitedStream = new SizeLimitStream(optLimit); + if (opt_returnStream) { + // When returning a stream, we'll return the response for the caller to handle streaming + // The content-length check is already done above + return { response, sha256: null, body: null, stream: response.data.pipe(limitedStream) }; + } + + const body = await pipeline(response.data, limitedStream, buffer); + const sha256 = crypto.createHash('sha256').update(body).digest('hex'); + return { response, sha256, body, stream: null }; + } catch (err) { + if('ERR_CANCELED' === err.code) { + err.code = 'ETIMEDOUT'; + } else if(['ECONNABORTED', 'ECONNRESET'].includes(err.code)) { + err.code = 'ESOCKETTIMEDOUT'; + } + if (err.status){ + err.statusCode = err.status; + } + throw err; + } +} + +async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_isInJwtToken, opt_headers) { + const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults); + const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader); + const tenTokenOutboxPrefix = ctx.getCfg('services.CoAuthoring.token.outbox.prefix', cfgTokenOutboxPrefix); + uri = URI.serialize(URI.parse(uri)); + const options = config.util.cloneDeep(tenTenantRequestDefaults); + + const httpsAgentOptions = { ...https.globalAgent.options, ...options}; + const httpAgentOptions = { ...http.globalAgent.options, ...options}; + changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); + + if (!addExternalRequestOptions(ctx, uri, opt_isInJwtToken, options, httpAgentOptions, httpsAgentOptions)) { + throw new Error('Block external request. See externalRequest config options'); + } + + if (!options.httpsAgent || !options.httpAgent) { + options.httpsAgent = new https.Agent(httpsAgentOptions); + options.httpAgent = new http.Agent(httpAgentOptions); + } + + const headers = { ...options.headers }; + if (opt_Authorization) { + headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization; + } + if (opt_headers) { + Object.assign(headers, opt_headers); + } + if (undefined !== postDataSize) { + //If no Content-Length is set, data will automatically be encoded in HTTP Chunked transfer encoding, + //so that server knows when the data ends. The Transfer-Encoding: chunked header is added. + //https://nodejs.org/api/http.html#requestwritechunk-encoding-callback + //issue with Transfer-Encoding: chunked wopi and sharepoint 2019 + //https://community.alteryx.com/t5/Dev-Space/Download-Tool-amp-Microsoft-SharePoint-Chunked-Request-Error/td-p/735824 + headers['Content-Length'] = postDataSize; + } + + const axiosConfig = { + ...options, + url: uri, + method: 'POST', + headers, + validateStatus: (status) => status === 200 || status === 204, + signal: optTimeout?.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, + timeout: optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, + }; + + if (postData) { + axiosConfig.data = postData; + } else if (postDataStream) { + axiosConfig.data = postDataStream; + } + + try { + const response = await axios(axiosConfig); + const { status, headers, data } = response; + + return { + response: { + statusCode: status, + headers: headers, + body: data + }, + body: JSON.stringify(data) + }; + } catch (err) { + if ('ERR_CANCELED' === err.code) { + err.code = 'ETIMEDOUT'; + } else if (['ECONNABORTED', 'ECONNRESET'].includes(err.code)) { + err.code = 'ESOCKETTIMEDOUT'; + } + if (err.status) { + err.statusCode = err.status; + } + if (err.response) { + const { status, headers, data } = err.response; + const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); + error.statusCode = status; + error.response = err.response; + throw error; + } + throw err; + } +} +exports.postRequestPromise = postRequestPromise; +exports.downloadUrlPromise = downloadUrlPromise; +exports.mapAscServerErrorToOldError = function(error) { + var res = -1; + switch (error) { + case constants.NO_ERROR : + case constants.CONVERT_CELLLIMITS : + res = 0; + break; + case constants.TASK_QUEUE : + case constants.TASK_RESULT : + res = -6; + break; + case constants.CONVERT_PASSWORD : + case constants.CONVERT_DRM : + case constants.CONVERT_DRM_UNSUPPORTED : + res = -5; + break; + case constants.CONVERT_DOWNLOAD : + res = -4; + break; + case constants.CONVERT_TIMEOUT : + case constants.CONVERT_DEAD_LETTER : + res = -2; + break; + case constants.CONVERT_PARAMS : + res = -7; + break; + case constants.CONVERT_LIMITS : + res = -10; + break; + case constants.CONVERT_NEED_PARAMS : + case constants.CONVERT_LIBREOFFICE : + case constants.CONVERT_CORRUPTED : + case constants.CONVERT_UNKNOWN_FORMAT : + case constants.CONVERT_READ_FILE : + case constants.CONVERT_TEMPORARY : + case constants.CONVERT : + res = -3; + break; + case constants.CONVERT_DETECT : + res = -9; + break; + case constants.VKEY : + case constants.VKEY_ENCRYPT : + case constants.VKEY_KEY_EXPIRE : + case constants.VKEY_USER_COUNT_EXCEED : + res = -8; + break; + case constants.STORAGE : + case constants.STORAGE_FILE_NO_FOUND : + case constants.STORAGE_READ : + case constants.STORAGE_WRITE : + case constants.STORAGE_REMOVE_DIR : + case constants.STORAGE_CREATE_DIR : + case constants.STORAGE_GET_INFO : + case constants.UPLOAD : + case constants.READ_REQUEST_STREAM : + case constants.UNKNOWN : + res = -1; + break; + } + return res; +}; +function fillXmlResponse(val) { + var xml = ''; + if (undefined != val.error) { + xml += '' + exports.encodeXml(val.error.toString()) + ''; + } else { + if (val.fileUrl) { + xml += '' + exports.encodeXml(val.fileUrl) + ''; + } else { + xml += ''; + } + if (val.fileType) { + xml += '' + exports.encodeXml(val.fileType) + ''; + } else { + xml += ''; + } + xml += '' + val.percent + ''; + xml += '' + (val.endConvert ? 'True' : 'False') + ''; + } + xml += ''; + return xml; +} + +function fillResponseSimple(res, str, contentType) { + let body = Buffer.from(str, 'utf-8'); + res.setHeader('Content-Type', contentType + '; charset=UTF-8'); + res.setHeader('Content-Length', body.length); + res.send(body); +} +function _fillResponse(res, output, isJSON) { + let data; + let contentType; + if (isJSON) { + data = JSON.stringify(output); + contentType = 'application/json'; + } else { + data = fillXmlResponse(output); + contentType = 'text/xml'; + } + fillResponseSimple(res, data, contentType); +} + +function fillResponse(req, res, convertStatus, isJSON) { + let output; + if (constants.NO_ERROR != convertStatus.err) { + output = {error: exports.mapAscServerErrorToOldError(convertStatus.err)}; + } else { + output = {fileUrl: convertStatus.url, fileType: convertStatus.filetype, percent: (convertStatus.end ? 100 : 0), endConvert: convertStatus.end}; + } + const accepts = isJSON ? ['json', 'xml'] : ['xml', 'json']; + switch (req.accepts(accepts)) { + case 'json': + isJSON = true; + break; + case 'xml': + isJSON = false; + break; + } + _fillResponse(res, output, isJSON); +} + +exports.fillResponseSimple = fillResponseSimple; +exports.fillResponse = fillResponse; + +function fillResponseBuilder(res, key, urls, end, error) { + let output; + if (constants.NO_ERROR != error) { + output = {error: exports.mapAscServerErrorToOldError(error)}; + } else { + output = {key: key, urls: urls, end: end}; + } + _fillResponse(res, output, true); +} + +exports.fillResponseBuilder = fillResponseBuilder; + +function promiseCreateWriteStream(strPath, optOptions) { + return new Promise(function(resolve, reject) { + var file = fs.createWriteStream(strPath, optOptions); + var errorCallback = function(e) { + reject(e); + }; + file.on('error', errorCallback); + file.on('open', function() { + file.removeListener('error', errorCallback); + resolve(file); + }); + }); +}; +exports.promiseCreateWriteStream = promiseCreateWriteStream; + +function promiseWaitDrain(stream) { + return new Promise(function(resolve, reject) { + stream.once('drain', resolve); + }); +} +exports.promiseWaitDrain = promiseWaitDrain; + +function promiseWaitClose(stream) { + return new Promise(function(resolve, reject) { + stream.once('close', resolve); + }); +} +exports.promiseWaitClose = promiseWaitClose; + +function promiseCreateReadStream(strPath) { + return new Promise(function(resolve, reject) { + var file = fs.createReadStream(strPath); + var errorCallback = function(e) { + reject(e); + }; + file.on('error', errorCallback); + file.on('open', function() { + file.removeListener('error', errorCallback); + resolve(file); + }); + }); +}; +exports.promiseCreateReadStream = promiseCreateReadStream; +exports.compareStringByLength = function(x, y) { + if (x && y) { + if (x.length == y.length) { + return x.localeCompare(y); + } else { + return x.length - y.length; + } + } else { + if (null != x) { + return 1; + } else if (null != y) { + return -1; + } + } + return 0; +}; +exports.promiseRedis = function(client, func) { + var newArguments = Array.prototype.slice.call(arguments, 2); + return new Promise(function(resolve, reject) { + newArguments.push(function(err, data) { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + func.apply(client, newArguments); + }); +}; +exports.containsAllAscii = function(str) { + return /^[\000-\177]*$/.test(str); +}; +function containsAllAsciiNP(str) { + return /^[\040-\176]*$/.test(str);//non-printing characters +} +exports.containsAllAsciiNP = containsAllAsciiNP; +function getDomain(hostHeader, forwardedHostHeader) { + return forwardedHostHeader || hostHeader || 'localhost'; +}; +function getBaseUrl(protocol, hostHeader, forwardedProtoHeader, forwardedHostHeader, forwardedPrefixHeader) { + var url = ''; + if (forwardedProtoHeader && constants.ALLOWED_PROTO.test(forwardedProtoHeader)) { + url += forwardedProtoHeader; + } else if (protocol && constants.ALLOWED_PROTO.test(protocol)) { + url += protocol; + } else { + url += 'http'; + } + url += '://'; + url += getDomain(hostHeader, forwardedHostHeader); + if (forwardedPrefixHeader) { + url += forwardedPrefixHeader; + } + return url; +} +function getBaseUrlByConnection(ctx, conn) { + conn = conn.request; + //Header names are lower-cased. https://nodejs.org/api/http.html#messageheaders + let cloudfrontForwardedProto = conn.headers['cloudfront-forwarded-proto']; + let forwardedProto = conn.headers['x-forwarded-proto']; + let forwardedHost = conn.headers['x-forwarded-host']; + let forwardedPrefix = conn.headers['x-forwarded-prefix']; + let host = conn.headers['host']; + let proto = cloudfrontForwardedProto || forwardedProto; + ctx.logger.debug(`getBaseUrlByConnection host=%s x-forwarded-host=%s x-forwarded-proto=%s x-forwarded-prefix=%s cloudfront-forwarded-proto=%s `, + host, forwardedHost, forwardedProto, forwardedPrefix, cloudfrontForwardedProto); + return getBaseUrl('', host, proto, forwardedHost, forwardedPrefix); +} +function getBaseUrlByRequest(ctx, req) { + //case-insensitive match. https://expressjs.com/en/api.html#req.get + let cloudfrontForwardedProto = req.get('cloudfront-forwarded-proto'); + let forwardedProto = req.get('x-forwarded-proto'); + let forwardedHost = req.get('x-forwarded-host'); + let forwardedPrefix = req.get('x-forwarded-prefix'); + let host = req.get('host'); + let protocol = req.protocol; + let proto = cloudfrontForwardedProto || forwardedProto; + ctx.logger.debug(`getBaseUrlByRequest protocol=%s host=%s x-forwarded-host=%s x-forwarded-proto=%s x-forwarded-prefix=%s cloudfront-forwarded-proto=%s `, + protocol, host, forwardedHost, forwardedProto, forwardedPrefix, cloudfrontForwardedProto); + return getBaseUrl(protocol, host, proto, forwardedHost, forwardedPrefix); +} +exports.getBaseUrlByConnection = getBaseUrlByConnection; +exports.getBaseUrlByRequest = getBaseUrlByRequest; +function getDomainByConnection(ctx, conn) { + let incomingMessage = conn.request; + let host = incomingMessage.headers['host']; + let forwardedHost = incomingMessage.headers['x-forwarded-host']; + ctx.logger.debug("getDomainByConnection headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost); + return getDomain(host, forwardedHost); +} +function getDomainByRequest(ctx, req) { + let host = req.get('host'); + let forwardedHost = req.get('x-forwarded-host'); + ctx.logger.debug("getDomainByRequest headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost); + return getDomain(req.get('host'), req.get('x-forwarded-host')); +} +exports.getDomainByConnection = getDomainByConnection; +exports.getDomainByRequest = getDomainByRequest; +function getShardKeyByConnection(ctx, conn) { + return conn?.handshake?.query?.[constants.SHARD_KEY_API_NAME]; +} +function getWopiSrcByConnection(ctx, conn) { + return conn?.handshake?.query?.[constants.SHARD_KEY_WOPI_NAME]; +} +function getShardKeyByRequest(ctx, req) { + return req.query?.[constants.SHARD_KEY_API_NAME]; +} +function getWopiSrcByRequest(ctx, req) { + return req.query?.[constants.SHARD_KEY_WOPI_NAME]; +} +exports.getShardKeyByConnection = getShardKeyByConnection; +exports.getWopiSrcByConnection = getWopiSrcByConnection; +exports.getShardKeyByRequest = getShardKeyByRequest; +exports.getWopiSrcByRequest = getWopiSrcByRequest; +function stream2Buffer(stream) { + return new Promise(function(resolve, reject) { + if (!stream.readable) { + resolve(Buffer.alloc(0)); + } + var bufs = []; + stream.on('data', function(data) { + bufs.push(data); + }); + function onEnd(err) { + if (err) { + reject(err); + } else { + resolve(Buffer.concat(bufs)); + } + } + stream.on('end', onEnd); + stream.on('error', onEnd); + }); +} +exports.stream2Buffer = stream2Buffer; +function changeOnlyOfficeUrl(inputUrl, strPath, optFilename) { + //onlyoffice file server expects url end with file extension + if (-1 == inputUrl.indexOf('?')) { + inputUrl += '?'; + } else { + inputUrl += '&'; + } + return inputUrl + constants.ONLY_OFFICE_URL_PARAM + '=' + constants.OUTPUT_NAME + path.extname(optFilename || strPath); +} +exports.changeOnlyOfficeUrl = changeOnlyOfficeUrl; +function pipeStreams(from, to, isEnd) { + return new Promise(function(resolve, reject) { + from.pipe(to, {end: isEnd}); + from.on('end', function() { + resolve(); + }); + from.on('error', function(e) { + reject(e); + }); + }); +} +exports.pipeStreams = pipeStreams; +function* pipeFiles(from, to) { + var fromStream = yield promiseCreateReadStream(from); + var toStream = yield promiseCreateWriteStream(to); + yield pipeStreams(fromStream, toStream, true); +} +exports.pipeFiles = co.wrap(pipeFiles); +function checkIpFilter(ctx, ipString, opt_hostname) { + const tenIpFilterRules = ctx.getCfg('services.CoAuthoring.ipfilter.rules', cfgIpFilterRules); + + var status = 0; + var ip4; + var ip6; + if (ipaddr.isValid(ipString)) { + var ip = ipaddr.parse(ipString); + if ('ipv6' === ip.kind()) { + if (ip.isIPv4MappedAddress()) { + ip4 = ip.toIPv4Address().toString(); + } + ip6 = ip.toNormalizedString(); + } else { + ip4 = ip.toString(); + ip6 = ip.toIPv4MappedAddress().toNormalizedString(); + } + } + + for (let i = 0; i < tenIpFilterRules.length; ++i) { + let rule = tenIpFilterRules[i]; + let exp = getIpFilterRule(rule.address); + if ((opt_hostname && exp.test(opt_hostname)) || (ip4 && exp.test(ip4)) || (ip6 && exp.test(ip6))) { + if (!rule.allowed) { + const tenIpFilterErrorCode = ctx.getCfg('services.CoAuthoring.ipfilter.errorcode', cfgIpFilterErrorCode); + status = tenIpFilterErrorCode; + } + break; + } + } + return status; +} +exports.checkIpFilter = checkIpFilter; +function* checkHostFilter(ctx, hostname) { + let status = 0; + let hostIp; + try { + hostIp = yield dnsLookup(hostname); + } catch (e) { + const tenIpFilterErrorCode = ctx.getCfg('services.CoAuthoring.ipfilter.errorcode', cfgIpFilterErrorCode); + status = tenIpFilterErrorCode; + ctx.logger.error('dnsLookup error: hostname = %s %s', hostname, e.stack); + } + if (0 === status) { + status = checkIpFilter(ctx, hostIp, hostname); + } + return status; +} +exports.checkHostFilter = checkHostFilter; +function checkClientIp(req, res, next) { + let ctx = new operationContext.Context(); + ctx.initFromRequest(req); + const tenIpFilterUseForRequest = ctx.getCfg('services.CoAuthoring.ipfilter.useforrequest', cfgIpFilterUseForRequest); + let status = 0; + if (tenIpFilterUseForRequest) { + const addresses = forwarded(req); + const ipString = addresses[addresses.length - 1]; + status = checkIpFilter(ctx, ipString); + } + if (status > 0) { + res.sendStatus(status); + } else { + next(); + } +} +exports.checkClientIp = checkClientIp; +function lowercaseQueryString(req, res, next) { + for (var key in req.query) { + if (req.query.hasOwnProperty(key) && key.toLowerCase() !== key) { + req.query[key.toLowerCase()] = req.query[key]; + delete req.query[key]; + } + } + next(); +} +exports.lowercaseQueryString = lowercaseQueryString; +function dnsLookup(hostname, options) { + return new Promise(function(resolve, reject) { + dnscache.lookup(hostname, options, function(err, addresses){ + if (err) { + reject(err); + } else { + resolve(addresses); + } + }); + }); +} +exports.dnsLookup = dnsLookup; +function isEmptyObject(val) { + return !(val && Object.keys(val).length); +} +exports.isEmptyObject = isEmptyObject; +function getSecretByElem(secretElem) { + let secret; + if (secretElem) { + if (secretElem.string) { + secret = secretElem.string; + } else if (secretElem.file) { + secret = pemfileCache.get(secretElem.file); + if (!secret) { + secret = fs.readFileSync(secretElem.file); + pemfileCache.set(secretElem.file, secret); + } + } + } + return secret; +} +exports.getSecretByElem = getSecretByElem; +function fillJwtForRequest(ctx, payload, secret, opt_inBody) { + const tenTokenOutboxAlgorithm = ctx.getCfg('services.CoAuthoring.token.outbox.algorithm', cfgTokenOutboxAlgorithm); + const tenTokenOutboxExpires = ctx.getCfg('services.CoAuthoring.token.outbox.expires', cfgTokenOutboxExpires); + //todo refuse prototypes in payload(they are simple getter/setter). + //JSON.parse/stringify is more universal but Object.assign is enough for our inputs + payload = Object.assign(Object.create(null), payload); + let data; + if (opt_inBody) { + data = payload; + } else { + data = {payload: payload}; + } + + let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires}; + return jwt.sign(data, secret, options); +} +exports.fillJwtForRequest = fillJwtForRequest; +exports.forwarded = forwarded; +exports.getIndexFromUserId = function(userId, userIdOriginal){ + return parseInt(userId.substring(userIdOriginal.length)); +}; +exports.checkPathTraversal = function(ctx, docId, rootDirectory, filename) { + if (filename.indexOf('\0') !== -1) { + ctx.logger.warn('checkPathTraversal Poison Null Bytes filename=%s', filename); + return false; + } + if (!filename.startsWith(rootDirectory)) { + ctx.logger.warn('checkPathTraversal Path Traversal filename=%s', filename); + return false; + } + return true; +}; +exports.getConnectionInfo = function(conn){ + var user = conn.user; + var data = { + id: user.id, + idOriginal: user.idOriginal, + username: user.username, + indexUser: user.indexUser, + view: user.view, + connectionId: conn.id, + isCloseCoAuthoring: conn.isCloseCoAuthoring, + isLiveViewer: exports.isLiveViewer(conn), + encrypted: conn.encrypted + }; + return data; +}; +exports.getConnectionInfoStr = function(conn){ + return JSON.stringify(exports.getConnectionInfo(conn)); +}; +exports.isLiveViewer = function(conn){ + return conn.user?.view && "fast" === conn.coEditingMode; +}; +exports.isLiveViewerSupport = function(licenseInfo){ + return licenseInfo.connectionsView > 0 || licenseInfo.usersViewCount > 0; +}; +exports.canIncludeOutboxAuthorization = function (ctx, url) { + const tenTokenEnableRequestOutbox = ctx.getCfg('services.CoAuthoring.token.enable.request.outbox', cfgTokenEnableRequestOutbox); + const tenTokenOutboxUrlExclusionRegex = ctx.getCfg('services.CoAuthoring.token.outbox.urlExclusionRegex', cfgTokenOutboxUrlExclusionRegex); + if (tenTokenEnableRequestOutbox) { + if (!tenTokenOutboxUrlExclusionRegex) { + return true; + } else if (!new RegExp(escapeStringRegexp(tenTokenOutboxUrlExclusionRegex)).test(url)) { + return true; + } else { + ctx.logger.debug('canIncludeOutboxAuthorization excluded by token.outbox.urlExclusionRegex url=%s', url); + } + } + return false; +}; +/* + Code samples taken from here: https://gist.github.com/btxtiger/e8eaee70d6e46729d127f1e384e755d6 + */ +exports.encryptPassword = async function (ctx, password) { + const pbkdf2Promise = util.promisify(crypto.pbkdf2); + const tenSecret = ctx.getCfg('aesEncrypt.secret', cfgSecret); + const tenAESConfig = ctx.getCfg('aesEncrypt.config', cfgAESConfig) ?? {}; + const { + keyByteLength = 32, + saltByteLength = 64, + initializationVectorByteLength = 16, + iterationsByteLength = 5 + } = tenAESConfig; + + const salt = crypto.randomBytes(saltByteLength); + const initializationVector = crypto.randomBytes(initializationVectorByteLength); + + const iterationsLength = iterationsByteLength < minimumIterationsByteLength ? minimumIterationsByteLength : iterationsByteLength; + // Generate random count of iterations; 10.000 - 99.999 -> 5 bytes + const lowerNumber = Math.pow(10, iterationsLength - 1); + const greaterNumber = Math.pow(10, iterationsLength) - 1; + const iterations = Math.floor(Math.random() * (greaterNumber - lowerNumber)) + lowerNumber; + + const encryptionKey = await pbkdf2Promise(tenSecret, salt, iterations, keyByteLength, 'sha512'); + //todo chacha20-poly1305 (clean db) + const cipher = crypto.createCipheriv('aes-256-gcm', encryptionKey, initializationVector, {authTagLength:16}); + const encryptedData = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]); + const authTag = cipher.getAuthTag(); + const predicate = iterations.toString(16); + const data = Buffer.concat([salt, initializationVector, authTag, encryptedData]).toString('hex'); + + return `${predicate}:${data}`; +}; +exports.decryptPassword = async function (ctx, password) { + const pbkdf2Promise = util.promisify(crypto.pbkdf2); + const tenSecret = ctx.getCfg('aesEncrypt.secret', cfgSecret); + const tenAESConfig = ctx.getCfg('aesEncrypt.config', cfgAESConfig) ?? {}; + const { + keyByteLength = 32, + saltByteLength = 64, + initializationVectorByteLength = 16, + } = tenAESConfig; + + const [iterations, dataHex] = password.split(':'); + const data = Buffer.from(dataHex, 'hex'); + // authTag in node.js equals 16 bytes(128 bits), see https://stackoverflow.com/questions/33976117/does-node-js-crypto-use-fixed-tag-size-with-gcm-mode + const delta = [saltByteLength, initializationVectorByteLength, 16]; + const pointerArray = []; + + for (let byte = 0, i = 0; i < delta.length; i++) { + const deltaValue = delta[i]; + pointerArray.push(data.subarray(byte, byte + deltaValue)); + byte += deltaValue; + + if (i === delta.length - 1) { + pointerArray.push(data.subarray(byte)); + } + } + + const [ + salt, + initializationVector, + authTag, + encryptedData + ] = pointerArray; + + const decryptionKey = await pbkdf2Promise(tenSecret, salt, parseInt(iterations, 16), keyByteLength, 'sha512'); + const decipher = crypto.createDecipheriv('aes-256-gcm', decryptionKey, initializationVector, {authTagLength:16}); + decipher.setAuthTag(authTag); + + return Buffer.concat([decipher.update(encryptedData, 'binary'), decipher.final()]).toString(); +}; +exports.getDateTimeTicks = function(date) { + return BigInt(date.getTime() * 10000) + 621355968000000000n; +}; +exports.convertLicenseInfoToFileParams = function(licenseInfo) { + // todo + // { + // user_quota = 0; + // portal_count = 0; + // process = 2; + // ssbranding = false; + // whiteLabel = false; + // } + let license = {}; + license.start_date = licenseInfo.startDate && licenseInfo.startDate.toJSON(); + license.end_date = licenseInfo.endDate && licenseInfo.endDate.toJSON(); + license.timelimited = 0 !== (constants.LICENSE_MODE.Limited & licenseInfo.mode); + license.trial = 0 !== (constants.LICENSE_MODE.Trial & licenseInfo.mode); + license.developer = 0 !== (constants.LICENSE_MODE.Developer & licenseInfo.mode); + license.branding = licenseInfo.branding; + license.customization = licenseInfo.customization; + license.advanced_api = licenseInfo.advancedApi; + license.connections = licenseInfo.connections; + license.connections_view = licenseInfo.connectionsView; + license.users_count = licenseInfo.usersCount; + license.users_view_count = licenseInfo.usersViewCount; + license.users_expire = licenseInfo.usersExpire / constants.LICENSE_EXPIRE_USERS_ONE_DAY; + license.customer_id = licenseInfo.customerId; + license.alias = licenseInfo.alias; + license.multitenancy = licenseInfo.multitenancy; + return license; +}; +exports.convertLicenseInfoToServerParams = function(licenseInfo) { + let license = {}; + license.workersCount = licenseInfo.count; + license.resultType = licenseInfo.type; + license.packageType = licenseInfo.packageType; + license.buildDate = licenseInfo.buildDate && licenseInfo.buildDate.toJSON(); + license.buildVersion = commonDefines.buildVersion; + license.buildNumber = commonDefines.buildNumber; + return license; +}; +exports.checkBaseUrl = function(ctx, baseUrl, opt_storageCfg) { + let storageExternalHost = opt_storageCfg ? opt_storageCfg.externalHost : cfgStorageExternalHost + const tenStorageExternalHost = ctx.getCfg('storage.externalHost', storageExternalHost); + return tenStorageExternalHost ? tenStorageExternalHost : baseUrl; +}; +exports.resolvePath = function(object, path, defaultValue) { + return path.split('.').reduce((o, p) => o ? o[p] : defaultValue, object); +}; +Date.isLeapYear = function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); +}; + +Date.getDaysInMonth = function (year, month) { + return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; +}; + +Date.prototype.isLeapYear = function () { + return Date.isLeapYear(this.getUTCFullYear()); +}; + +Date.prototype.getDaysInMonth = function () { + return Date.getDaysInMonth(this.getUTCFullYear(), this.getUTCMonth()); +}; + +Date.prototype.addMonths = function (value) { + var n = this.getUTCDate(); + this.setUTCDate(1); + this.setUTCMonth(this.getUTCMonth() + value); + this.setUTCDate(Math.min(n, this.getDaysInMonth())); + return this; +}; +function getMonthDiff(d1, d2) { + var months; + months = (d2.getUTCFullYear() - d1.getUTCFullYear()) * 12; + months -= d1.getUTCMonth(); + months += d2.getUTCMonth(); + return months; +} +exports.getMonthDiff = getMonthDiff; + +/** + * A Transform stream that limits the size of data passing through it. + * It will throw an EMSGSIZE error if the size exceeds the limit. + * + * @class SizeLimitStream + * @extends {Transform} + */ +class SizeLimitStream extends Transform { + /** + * Creates an instance of SizeLimitStream. + * @param {number} sizeLimit - Maximum size in bytes that can pass through the stream + * @memberof SizeLimitStream + */ + constructor(sizeLimit) { + super(); + this.sizeLimit = sizeLimit; + this.bytesReceived = 0; + } + + /** + * Transform implementation that tracks the bytes received and enforces the size limit + * + * @param {Buffer|string} chunk - The chunk of data to process + * @param {string} encoding - The encoding of the chunk if it's a string + * @param {Function} callback - Called when processing is complete + * @memberof SizeLimitStream + */ + _transform(chunk, encoding, callback) { + this.bytesReceived += chunk.length; + + if (this.sizeLimit && this.bytesReceived > this.sizeLimit) { + const error = new Error(`EMSGSIZE: Response too large: ${this.bytesReceived} bytes (limit: ${this.sizeLimit} bytes)`); + error.code = 'EMSGSIZE'; + callback(error); + return; + } + + callback(null, chunk); + } +} +exports.getLicensePeriod = function(startDate, now) { + startDate = new Date(startDate.getTime());//clone + startDate.addMonths(getMonthDiff(startDate, now)); + if (startDate > now) { + startDate.addMonths(-1); + } + startDate.setUTCHours(0,0,0,0); + return startDate.getTime(); +}; + +exports.removeIllegalCharacters = function(filename) { + return filename?.replace(/[/\\?%*:|"<>]/g, '-') || filename; +} +exports.getFunctionArguments = function(func) { + return func.toString(). + replace(/[\r\n\s]+/g, ' '). + match(/(?:function\s*\w*)?\s*(?:\((.*?)\)|([^\s]+))/). + slice(1, 3). + join(''). + split(/\s*,\s*/); +}; +exports.isUselesSfc = function(row, cmd) { + return !(row && commonDefines.FileStatus.SaveVersion === row.status && cmd.getStatusInfoIn() === row.status_info); +}; +exports.getChangesFileHeader = function() { + return `CHANGES\t${commonDefines.buildVersion}\n`; +}; +exports.checksumFile = function(hashName, path) { + //https://stackoverflow.com/a/44643479 + return new Promise((resolve, reject) => { + const hash = crypto.createHash(hashName); + const stream = fs.createReadStream(path); + stream.on('error', err => reject(err)); + stream.on('data', chunk => hash.update(chunk)); + stream.on('end', () => resolve(hash.digest('hex'))); + }); +}; + +function isObject(item) { + return (item && typeof item === 'object' && !Array.isArray(item)); +} + +function deepMergeObjects(target, ...sources) { + if (!sources.length) { + return target; + } + + const source = sources.shift(); + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (isObject(source[key])) { + if (!target[key]) { + Object.assign(target, { [key]: {} }); + } + + deepMergeObjects(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); + } + } + } + + return deepMergeObjects(target, ...sources); +} +exports.isObject = isObject; +exports.deepMergeObjects = deepMergeObjects; From 8e59949de801d3a34b61cc9874aba12ca2ec9e77 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Mon, 21 Apr 2025 14:38:19 +0300 Subject: [PATCH 13/17] [feature] Upgrade express from v4.17.1 to v4.21.2 --- npm-shrinkwrap.json | 543 ++++++++++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 425 insertions(+), 120 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 54189366..896d4f29 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1292,21 +1292,23 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", + "bytes": "3.1.2", + "content-type": "~1.0.5", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" } }, "brace-expansion": { @@ -1346,9 +1348,9 @@ "dev": true }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true }, "cacheable-lookup": { @@ -1387,6 +1389,81 @@ } } }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + } + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + } + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1484,12 +1561,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { @@ -1505,9 +1582,9 @@ "dev": true }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true }, "cookie-signature": { @@ -1659,15 +1736,15 @@ } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true }, "detect-newline": { @@ -1682,6 +1759,25 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "dependencies": { + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1707,9 +1803,9 @@ "dev": true }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true }, "eol": { @@ -1771,6 +1867,27 @@ "which-typed-array": "^1.1.13" } }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, "es-set-tostringtag": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", @@ -1857,38 +1974,39 @@ } }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", + "depd": "2.0.0", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.3.1", "fresh": "0.5.2", - "merge-descriptors": "1.0.1", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -1910,17 +2028,17 @@ } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" } }, @@ -2029,6 +2147,16 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, "get-stdin": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", @@ -2184,24 +2312,16 @@ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - } + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "http2-wrapper": { @@ -3735,6 +3855,12 @@ "tmpl": "1.0.5" } }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -3747,9 +3873,9 @@ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==" }, "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true }, "merge-stream": { @@ -3998,9 +4124,9 @@ } }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "requires": { "ee-first": "1.1.1" @@ -4106,9 +4232,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true }, "path-type": { @@ -4202,10 +4328,34 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + }, + "dependencies": { + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true + }, + "side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + } + } }, "quick-lru": { "version": "5.1.1", @@ -4219,13 +4369,13 @@ "dev": true }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -4343,9 +4493,9 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "safe-regex-test": { @@ -4370,30 +4520,36 @@ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true + }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -4409,15 +4565,15 @@ } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "requires": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.19.0" } }, "set-function-length": { @@ -4442,9 +4598,9 @@ } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, "shebang-command": { @@ -4477,6 +4633,155 @@ "object-inspect": "^1.9.0" } }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "dependencies": { + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true + } + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true + } + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true + } + } + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4568,9 +4873,9 @@ } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true }, "string-length": { @@ -4723,9 +5028,9 @@ "dev": true }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, "tslib": { diff --git a/package.json b/package.json index 10b2d7cd..32618fff 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@jest/globals": "29.7.0", "cross-env": "7.0.3", "jest": "29.7.0", - "express": "4.17.1" + "express": "4.21.2" }, "scripts": { "perf-expired": "cd ./DocService&& cross-env NODE_ENV=development-windows NODE_CONFIG_DIR=../Common/config node ../tests/perf/checkFileExpire.js", From 6b9e7e007e2be29c22487dd1db6d8d76f125a612 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Mon, 21 Apr 2025 17:49:25 +0300 Subject: [PATCH 14/17] [bug] Fix tests timeout --- tests/unit/request.tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index bb776ce3..28dd3c62 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -786,7 +786,7 @@ describe('HTTP Request Unit Tests', () => { } finally { await new Promise(resolve => testServer.close(resolve)); } - }); + }, 30000); test('disables keep-alive when forever is false', async () => { const mockCtx = createMockContext({ @@ -1312,7 +1312,7 @@ describe('HTTP Request Unit Tests', () => { } finally { await new Promise(resolve => testServer.close(resolve)); } - }); + }, 30000); test('successfully routes POST request through a real proxy', async () => { try { From 093800fbc36905b6fccc1b23dc4b04f692da5bf8 Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Mon, 21 Apr 2025 17:56:40 +0300 Subject: [PATCH 15/17] [refactoring] Refactor tests; Decrease some test timeouts --- Common/sources/utils.js | 48 +-------- tests/unit/request.tests.js | 193 +++++++++--------------------------- 2 files changed, 51 insertions(+), 190 deletions(-) diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 12e3d0d4..f66af4c0 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -239,43 +239,11 @@ exports.readFile = function(file) { }); }); }; -function makeAndroidSafeFileName(str) { - for (var i = 0; i < str.length; i++) { - if (-1 == ANDROID_SAFE_FILENAME.indexOf(str[i])) { - str[i] = '_'; - } - } - return str; -} -function encodeRFC5987ValueChars(str) { - return encodeURIComponent(str). - // Note that although RFC3986 reserves "!", RFC5987 does not, - // so we do not need to escape it - replace(/['()]/g, escape). // i.e., %27 %28 %29 - replace(/\*/g, '%2A'). - // The following are not required for percent-encoding per RFC5987, - // so we can allow for a little better readability over the wire: |`^ - replace(/%(?:7C|60|5E)/g, unescape); -} function getContentDisposition (opt_filename, opt_useragent, opt_type) { let type = opt_type || constants.CONTENT_DISPOSITION_ATTACHMENT; return contentDisposition(opt_filename, {type: type}); } exports.getContentDisposition = getContentDisposition; -function raiseError(ro, code, msg) { - ro.abort(); - let error = new Error(msg); - error.code = code; - ro.emit('error', error); -} -function raiseErrorObj(ro, error) { - ro.abort(); - ro.emit('error', error); -} -function isRedirectResponse(response) { - //All header names are lower cased and can be accessed using the bracket notation. - return response && response.status >= 300 && response.status < 400 && !!response.headers['location']; -} function isAllowDirectRequest(ctx, uri, isInJwtToken) { let res = false; @@ -377,11 +345,6 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat const httpAgentOptions = { ...http.globalAgent.options, ...options}; changeOptionsForCompatibilityWithRequest(options, httpAgentOptions, httpsAgentOptions); - // if (optTimeout.connectionAndInactivity) { - // httpAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - // httpsAgentOptions.timeout = ms(optTimeout.connectionAndInactivity); - // } - if (!addExternalRequestOptions(ctx, uri, opt_filterPrivate, options, httpAgentOptions, httpsAgentOptions)) { throw new Error('Block external request. See externalRequest config options'); } @@ -406,15 +369,8 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat responseType: 'stream', headers, validateStatus: (status) => status >= 200 && status < 300, - signal: optTimeout.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, - timeout: optTimeout.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, - // cancelToken: new axios.CancelToken(cancel => { - // if (optTimeout?.wholeCycle) { - // setTimeout(() => { - // cancel(`ETIMEDOUT: ${optTimeout.wholeCycle}`); - // }, ms(optTimeout.wholeCycle)); - // } - // }), + signal: optTimeout?.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, + timeout: optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, }; try { const response = await axios(axiosConfig); diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index 28dd3c62..fb1da623 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -117,7 +117,7 @@ describe('HTTP Request Unit Tests', () => { // Delay sending headers setTimeout(() => { res.json({ success: true }); - }, 2000); // 2 seconds delay before sending any response + }, 200); // 200 ms delay before sending any response }); @@ -148,9 +148,9 @@ describe('HTTP Request Unit Tests', () => { setTimeout(() => { res.write('"part4": "Final part"}'); res.end(); - }, 2000); - }, 1000); - }, 1000); + }, 200); + }, 100); + }, 100); }); // POST endpoint @@ -186,30 +186,6 @@ describe('HTTP Request Unit Tests', () => { res.end(); }); - // Endpoint that returns connection header info - app.get('/api/connection', (req, res) => { - res.json({ - connection: req.headers.connection, - keepAlive: req.headers.connection?.toLowerCase() === 'keep-alive' - }); - }); - - // Endpoint that returns only the accept-encoding header - app.get('/api/accept-encoding', (req, res) => { - res.json({ - acceptEncoding: req.headers['accept-encoding'] || null - }); - }); - - // Endpoint that returns only the connection header - app.get('/api/connection-header', (req, res) => { - const connectionHeader = req.headers['connection'] || ''; - res.json({ - connection: connectionHeader, - keepAlive: connectionHeader.toLowerCase() === 'keep-alive' - }); - }); - // Endpoint that mirrors whole request - handles any HTTP method app.use('/api/mirror', express.json(), express.urlencoded({ extended: true }), (req, res) => { // Create a mirror response object with all request details @@ -332,7 +308,7 @@ describe('HTTP Request Unit Tests', () => { await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-headers`, - { connectionAndInactivity: '1s' }, // connectionAndInactivity shorter than the server delay + { connectionAndInactivity: '100ms' }, // connectionAndInactivity shorter than the server delay 1024 * 1024, null, false, @@ -351,7 +327,7 @@ describe('HTTP Request Unit Tests', () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-headers`, - { connectionAndInactivity: '3s' }, // connectionAndInactivity longer than the server delay (2s) + { connectionAndInactivity: '300ms' }, // connectionAndInactivity longer than the server delay (200ms) 1024 * 1024, null, false, @@ -370,7 +346,7 @@ describe('HTTP Request Unit Tests', () => { await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/partial-response`, - { wholeCycle: '2s' }, // wholeCycle shorter than time needed for response + { wholeCycle: '1s' }, // wholeCycle shorter than time needed for response 1024 * 1024, null, false, @@ -389,7 +365,7 @@ describe('HTTP Request Unit Tests', () => { await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-body`, - { connectionAndInactivity: '1500ms' }, // connectionAndInactivity shorter than the second delay + { connectionAndInactivity: '150ms' }, // connectionAndInactivity shorter than the second delay 1024 * 1024, null, false, @@ -407,7 +383,7 @@ describe('HTTP Request Unit Tests', () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-body`, - { connectionAndInactivity: '2100ms' }, // connectionAndInactivity longer than the longest delay (2s) + { connectionAndInactivity: '250ms' }, // connectionAndInactivity longer than the longest delay (2s) 1024 * 1024, null, false, @@ -428,7 +404,7 @@ describe('HTTP Request Unit Tests', () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-body`, - { wholeCycle: '7s' }, + { wholeCycle: '1s' }, 1024 * 1024, null, false, @@ -604,6 +580,7 @@ describe('HTTP Request Unit Tests', () => { 1024 * 1024, null, false, + null, null ); throw new Error('Expected an error to be thrown'); @@ -619,6 +596,7 @@ describe('HTTP Request Unit Tests', () => { 1024 * 1024, null, false, + null, null ); throw new Error('Expected an error to be thrown'); @@ -663,21 +641,6 @@ describe('HTTP Request Unit Tests', () => { }); test('enables compression when gzip is true', async () => { - // Setup a simple server that captures headers - let capturedHeaders = {}; - const app = express(); - app.get('/test', (req, res) => { - capturedHeaders = { - acceptEncoding: req.headers['accept-encoding'] - }; - res.json({ success: true }); - }); - - const testServer = http.createServer(app); - const testPort = PORT + 1000; - await new Promise(resolve => testServer.listen(testPort, resolve)); - - try { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -686,9 +649,9 @@ describe('HTTP Request Unit Tests', () => { } }); - await utils.downloadUrlPromise( + const response = await utils.downloadUrlPromise( mockCtx, - `http://localhost:${testPort}/test`, + `${BASE_URL}/api/mirror`, { wholeCycle: '2s' }, 1024 * 1024, null, @@ -697,30 +660,15 @@ describe('HTTP Request Unit Tests', () => { null ); + // Parse the response body assuming it's JSON + const responseBody = JSON.parse(response.body); + // When gzip is true, 'accept-encoding' should include 'gzip' - expect(capturedHeaders.acceptEncoding).toBeDefined(); - expect(capturedHeaders.acceptEncoding).toMatch(/gzip/i); - } finally { - await new Promise(resolve => testServer.close(resolve)); - } + expect(responseBody.headers?.['accept-encoding']).toBeDefined(); + expect(responseBody.headers?.['accept-encoding']).toMatch(/gzip/i); }); test('disables compression when gzip is false', async () => { - // Setup a simple server that captures headers - let capturedHeaders = {}; - const app = express(); - app.get('/test', (req, res) => { - capturedHeaders = { - acceptEncoding: req.headers['accept-encoding'] - }; - res.json({ success: true }); - }); - - const testServer = http.createServer(app); - const testPort = PORT + 1001; - await new Promise(resolve => testServer.listen(testPort, resolve)); - - try { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -729,9 +677,9 @@ describe('HTTP Request Unit Tests', () => { } }); - await utils.downloadUrlPromise( + const response = await utils.downloadUrlPromise( mockCtx, - `http://localhost:${testPort}/test`, + `${BASE_URL}/api/mirror`, { wholeCycle: '2s' }, 1024 * 1024, null, @@ -740,28 +688,13 @@ describe('HTTP Request Unit Tests', () => { null ); - expect(capturedHeaders.acceptEncoding === 'identity' || capturedHeaders.acceptEncoding === undefined).toBe(true); - } finally { - await new Promise(resolve => testServer.close(resolve)); - } + // Parse the response body assuming it's JSON + const responseBody = JSON.parse(response.body); + + expect(responseBody.headers?.['accept-encoding'] === 'identity' || responseBody.headers?.['accept-encoding'] === undefined).toBe(true); }); test('enables keep-alive when forever is true', async () => { - // Setup a simple server that captures headers - let capturedHeaders = {}; - const app = express(); - app.get('/test', (req, res) => { - capturedHeaders = { - connection: req.headers['connection'] - }; - res.json({ success: true }); - }); - - const testServer = http.createServer(app); - const testPort = PORT + 1002; - await new Promise(resolve => testServer.listen(testPort, resolve)); - - try { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -770,9 +703,9 @@ describe('HTTP Request Unit Tests', () => { } }); - await utils.downloadUrlPromise( + const response = await utils.downloadUrlPromise( mockCtx, - `http://localhost:${testPort}/test`, + `${BASE_URL}/api/mirror`, { wholeCycle: '2s' }, 1024 * 1024, null, @@ -781,11 +714,11 @@ describe('HTTP Request Unit Tests', () => { null ); + // Parse the response body assuming it's JSON + const responseBody = JSON.parse(response.body); + // When forever is true, connection should be 'keep-alive' - expect(capturedHeaders.connection?.toLowerCase()).toMatch(/keep-alive/i); - } finally { - await new Promise(resolve => testServer.close(resolve)); - } + expect(responseBody.headers?.connection?.toLowerCase()).toMatch(/keep-alive/i); }, 30000); test('disables keep-alive when forever is false', async () => { @@ -801,7 +734,7 @@ describe('HTTP Request Unit Tests', () => { const result = await utils.downloadUrlPromise( mockCtx, - `${BASE_URL}/api/connection-header`, + `${BASE_URL}/api/mirror`, { wholeCycle: '5s', connectionAndInactivity: '3s' }, 1024 * 1024, null, @@ -811,12 +744,14 @@ describe('HTTP Request Unit Tests', () => { ); expect(result).toBeDefined(); - const responseData = JSON.parse(result.body.toString()); + expect(result.response).toBeDefined(); + expect(getStatusCode(result.response)).toBe(200); + const responseBody = JSON.parse(result.body.toString()); // When forever is false, connection should NOT be 'keep-alive' // Note: Different HTTP clients might handle this differently, // so we're checking that keepAlive is false - expect(responseData.keepAlive).toBe(false); + expect(responseBody.headers?.connection?.toLowerCase()).not.toMatch(/keep-alive/i); }); test('test requestDefaults', async () => { @@ -838,7 +773,7 @@ describe('HTTP Request Unit Tests', () => { customHeaders ); expect(result).toBeDefined(); - expect(result.response.status).toBe(200); + expect(getStatusCode(result.response)).toBe(200); const body = JSON.parse(result.body); expect(body.headers).toMatchObject({...defaultHeaders, ...customHeaders}); expect(body.query).toMatchObject(customQueryParams); @@ -1226,21 +1161,6 @@ describe('HTTP Request Unit Tests', () => { }); test('applies gzip setting to POST requests', async () => { - // Setup a simple server that captures headers - let capturedHeaders = {}; - const app = express(); - app.post('/test', express.json(), (req, res) => { - capturedHeaders = { - acceptEncoding: req.headers['accept-encoding'] - }; - res.json({ success: true }); - }); - - const testServer = http.createServer(app); - const testPort = PORT + 1003; - await new Promise(resolve => testServer.listen(testPort, resolve)); - - try { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -1251,9 +1171,9 @@ describe('HTTP Request Unit Tests', () => { const postData = JSON.stringify({ test: 'data' }); - await utils.postRequestPromise( + const response = await utils.postRequestPromise( mockCtx, - `http://localhost:${testPort}/test`, + `${BASE_URL}/api/mirror`, postData, null, postData.length, @@ -1263,28 +1183,13 @@ describe('HTTP Request Unit Tests', () => { { 'Content-Type': 'application/json' } ); - expect(capturedHeaders.acceptEncoding === 'identity' || capturedHeaders.acceptEncoding === undefined).toBe(true); - } finally { - await new Promise(resolve => testServer.close(resolve)); - } + // Parse the response body assuming it's JSON + const responseBody = JSON.parse(response.body); + + expect(responseBody.headers?.['accept-encoding'] === 'identity' || responseBody.headers?.['accept-encoding'] === undefined).toBe(true); }); test('applies forever setting to POST requests', async () => { - // Setup a simple server that captures headers - let capturedHeaders = {}; - const app = express(); - app.post('/test', express.json(), (req, res) => { - capturedHeaders = { - connection: req.headers['connection'] - }; - res.json({ success: true }); - }); - - const testServer = http.createServer(app); - const testPort = PORT + 1004; - await new Promise(resolve => testServer.listen(testPort, resolve)); - - try { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -1295,9 +1200,9 @@ describe('HTTP Request Unit Tests', () => { const postData = JSON.stringify({ test: 'data' }); - await utils.postRequestPromise( + const response = await utils.postRequestPromise( mockCtx, - `http://localhost:${testPort}/test`, + `${BASE_URL}/api/mirror`, postData, null, postData.length, @@ -1307,11 +1212,11 @@ describe('HTTP Request Unit Tests', () => { { 'Content-Type': 'application/json' } ); + // Parse the response body assuming it's JSON + const responseBody = JSON.parse(response.body); + // When forever is true, connection should be 'keep-alive' - expect(capturedHeaders.connection?.toLowerCase()).toMatch(/keep-alive/i); - } finally { - await new Promise(resolve => testServer.close(resolve)); - } + expect(responseBody.headers?.connection?.toLowerCase()).toMatch(/keep-alive/i); }, 30000); test('successfully routes POST request through a real proxy', async () => { From 8baae4b0ddf3d3effc3283022d533e264f75aba0 Mon Sep 17 00:00:00 2001 From: Pavel Ostrovskij Date: Mon, 21 Apr 2025 21:07:54 +0300 Subject: [PATCH 16/17] [refactor] Improved tests and error handling --- Common/sources/utils.js | 32 +++++++-------- tests/unit/request.tests.js | 78 ++++++++++++++++++------------------- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/Common/sources/utils.js b/Common/sources/utils.js index f66af4c0..a318a5cf 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -368,7 +368,6 @@ async function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorizat method: 'GET', responseType: 'stream', headers, - validateStatus: (status) => status >= 200 && status < 300, signal: optTimeout?.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, timeout: optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, }; @@ -454,7 +453,6 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi url: uri, method: 'POST', headers, - validateStatus: (status) => status === 200 || status === 204, signal: optTimeout?.wholeCycle && AbortSignal.timeout ? AbortSignal.timeout(ms(optTimeout.wholeCycle)) : undefined, timeout: optTimeout?.connectionAndInactivity ? ms(optTimeout.connectionAndInactivity) : undefined, }; @@ -469,14 +467,21 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi const response = await axios(axiosConfig); const { status, headers, data } = response; - return { - response: { - statusCode: status, - headers: headers, - body: data - }, - body: JSON.stringify(data) - }; + if (status === 200 || status === 204) { + return { + response: { + statusCode: status, + headers: headers, + body: data + }, + body: JSON.stringify(data) + }; + } else { + const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); + error.status = status; + error.response = response; + throw error; + } } catch (err) { if ('ERR_CANCELED' === err.code) { err.code = 'ETIMEDOUT'; @@ -486,13 +491,6 @@ async function postRequestPromise(ctx, uri, postData, postDataStream, postDataSi if (err.status) { err.statusCode = err.status; } - if (err.response) { - const { status, headers, data } = err.response; - const error = new Error(`Error response: statusCode:${status}; headers:${JSON.stringify(headers)}; body:\r\n${data}`); - error.statusCode = status; - error.response = err.response; - throw error; - } throw err; } } diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index fb1da623..355c728b 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -303,7 +303,7 @@ describe('HTTP Request Unit Tests', () => { describe('specific timeout behaviors', () => { - test('connectionAndInactivity triggers when server delays response headers', async () => { + test.concurrent('connectionAndInactivity triggers when server delays response headers', async () => { try { await utils.downloadUrlPromise( ctx, @@ -323,7 +323,7 @@ describe('HTTP Request Unit Tests', () => { }); - test('connectionAndInactivity does not trigger when longer than server delay', async () => { + test.concurrent('connectionAndInactivity does not trigger when longer than server delay', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-headers`, @@ -341,7 +341,7 @@ describe('HTTP Request Unit Tests', () => { }); - test('wholeCycle triggers even when server starts sending data but does not complete', async () => { + test.concurrent('wholeCycle triggers even when server starts sending data but does not complete', async () => { try { await utils.downloadUrlPromise( ctx, @@ -360,7 +360,7 @@ describe('HTTP Request Unit Tests', () => { }); - test('connectionAndInactivity triggers when server stops sending data midway', async () => { + test.concurrent('connectionAndInactivity triggers when server stops sending data midway', async () => { try { await utils.downloadUrlPromise( ctx, @@ -379,7 +379,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test('connectionAndInactivity does not trigger when longer than inactivity periods', async () => { + test.concurrent('connectionAndInactivity does not trigger when longer than inactivity periods', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-body`, @@ -400,7 +400,7 @@ describe('HTTP Request Unit Tests', () => { expect(responseBody.part4).toBe('Final part'); }); - test('wholeCycle does not trigger when longer than total response time', async () => { + test.concurrent('wholeCycle does not trigger when longer than total response time', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/slow-body`, @@ -423,7 +423,7 @@ describe('HTTP Request Unit Tests', () => { }); describe('downloadUrlPromise', () => { - test('successfully downloads JSON data', async () => { + test.concurrent('successfully downloads JSON data', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/data`, @@ -440,7 +440,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body.toString())).toEqual({ success: true }); }); - test('throws error on timeout', async () => { + test.concurrent('throws error on timeout', async () => { try { await utils.downloadUrlPromise( ctx, @@ -458,7 +458,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test('throws error on wholeCycle timeout', async () => { + test.concurrent('throws error on wholeCycle timeout', async () => { try { await utils.downloadUrlPromise( ctx, @@ -477,7 +477,7 @@ describe('HTTP Request Unit Tests', () => { }); - test('follows redirects correctly', async () => { + test.concurrent('follows redirects correctly', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/redirect`, @@ -494,7 +494,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body.toString())).toEqual({ success: true }); }); - test(`doesn't follow redirects(maxRedirects=0)`, async () => { + test.concurrent(`doesn't follow redirects(maxRedirects=0)`, async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { "headers": { @@ -525,7 +525,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test(`doesn't follow redirects(followRedirect=false)`, async () => { + test.concurrent(`doesn't follow redirects(followRedirect=false)`, async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { "headers": { @@ -558,7 +558,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test('throws error on server error', async () => { + test.concurrent('throws error on server error', async () => { await expect(utils.downloadUrlPromise( ctx, `${BASE_URL}/api/error`, @@ -571,7 +571,7 @@ describe('HTTP Request Unit Tests', () => { )).rejects.toMatchObject({ code: 'ERR_BAD_RESPONSE' }); }); - test('throws error when content-length exceeds limit', async () => { + test.concurrent('throws error when content-length exceeds limit', async () => { try { await utils.downloadUrlPromise( ctx, @@ -605,7 +605,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test('throws error when content-length exceeds limit with stream', async () => { + test.concurrent('throws error when content-length exceeds limit with stream', async () => { try { const {stream} = await utils.downloadUrlPromise( ctx, @@ -640,7 +640,7 @@ describe('HTTP Request Unit Tests', () => { } }); - test('enables compression when gzip is true', async () => { + test.concurrent('enables compression when gzip is true', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -668,7 +668,7 @@ describe('HTTP Request Unit Tests', () => { expect(responseBody.headers?.['accept-encoding']).toMatch(/gzip/i); }); - test('disables compression when gzip is false', async () => { + test.concurrent('disables compression when gzip is false', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -694,7 +694,7 @@ describe('HTTP Request Unit Tests', () => { expect(responseBody.headers?.['accept-encoding'] === 'identity' || responseBody.headers?.['accept-encoding'] === undefined).toBe(true); }); - test('enables keep-alive when forever is true', async () => { + test.concurrent('enables keep-alive when forever is true', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -719,9 +719,9 @@ describe('HTTP Request Unit Tests', () => { // When forever is true, connection should be 'keep-alive' expect(responseBody.headers?.connection?.toLowerCase()).toMatch(/keep-alive/i); - }, 30000); + }); - test('disables keep-alive when forever is false', async () => { + test.concurrent('disables keep-alive when forever is false', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { @@ -754,7 +754,7 @@ describe('HTTP Request Unit Tests', () => { expect(responseBody.headers?.connection?.toLowerCase()).not.toMatch(/keep-alive/i); }); - test('test requestDefaults', async () => { + test.concurrent('test requestDefaults', async () => { const defaultHeaders = {"user-agent": "Node.js/6.13"}; const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { @@ -779,7 +779,7 @@ describe('HTTP Request Unit Tests', () => { expect(body.query).toMatchObject(customQueryParams); }); - test('successfully routes GET request through a real proxy', async () => { + test.concurrent('successfully routes GET request through a real proxy', async () => { try { // Create context with proxy configuration const mockCtx = createMockContext({ @@ -830,7 +830,7 @@ describe('HTTP Request Unit Tests', () => { }); }); - test('handles binary data correctly', async () => { + test.concurrent('handles binary data correctly', async () => { const result = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/binary`, @@ -856,7 +856,7 @@ describe('HTTP Request Unit Tests', () => { expect(Buffer.compare(result.body, expectedData)).toBe(0); }); - test('handles binary data with stream writer', async () => { + test.concurrent('handles binary data with stream writer', async () => { const { stream } = await utils.downloadUrlPromise( ctx, `${BASE_URL}/api/binary`, @@ -875,7 +875,7 @@ describe('HTTP Request Unit Tests', () => { expect(Buffer.compare(receivedData, expectedData)).toBe(0); }); - test('block external requests', async () => { + test.concurrent('block external requests', async () => { const mockCtx = createMockContext({ 'externalRequest.action': { "allow": false, // Block all external requests @@ -902,7 +902,7 @@ describe('HTTP Request Unit Tests', () => { )).rejects.toThrow('Block external request. See externalRequest config options'); }); - test('allows request to external url in allowlist', async () => { + test.concurrent('allows request to external url in allowlist', async () => { const mockCtx = createMockContext({ 'externalRequest.action': { "allow": false, // Block external requests by default @@ -936,7 +936,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body.toString())).toEqual({ success: true }); }); - test('allows request when URL is in JWT token', async () => { + test.concurrent('allows request when URL is in JWT token', async () => { const mockCtx = createMockContext({ 'externalRequest.action': { "allow": false, // Block external requests by default @@ -971,7 +971,7 @@ describe('HTTP Request Unit Tests', () => { }); describe('postRequestPromise', () => { - test('successfully posts data', async () => { + test.concurrent('successfully posts data', async () => { const postData = JSON.stringify({ test: 'data' }); const result = await utils.postRequestPromise( @@ -991,7 +991,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); }); - test('handles timeout during post', async () => { + test.concurrent('handles timeout during post', async () => { const postData = JSON.stringify({ test: 'data' }); await expect(utils.postRequestPromise( @@ -1007,7 +1007,7 @@ describe('HTTP Request Unit Tests', () => { )).rejects.toMatchObject({ code: 'ESOCKETTIMEDOUT' }); }); - test('handles post with Authorization header', async () => { + test.concurrent('handles post with Authorization header', async () => { const postData = JSON.stringify({ test: 'data' }); const authToken = 'test-auth-token'; @@ -1028,7 +1028,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); }); - test('handles post with custom headers', async () => { + test.concurrent('handles post with custom headers', async () => { const postData = JSON.stringify({ test: 'data' }); const customHeaders = { 'X-Custom-Header': 'test-value', @@ -1052,7 +1052,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); }); - test('handles post with stream data', async () => { + test.concurrent('handles post with stream data', async () => { const postData = JSON.stringify({ test: 'stream-data' }); const postStream = new Readable({ read() { @@ -1078,7 +1078,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'stream-data' } }); }); - test('throws error on wholeCycle timeout during post', async () => { + test.concurrent('throws error on wholeCycle timeout during post', async () => { const postData = JSON.stringify({ test: 'data' }); await expect(utils.postRequestPromise( @@ -1094,7 +1094,7 @@ describe('HTTP Request Unit Tests', () => { )).rejects.toMatchObject({ code: 'ETIMEDOUT' }); }); - test('blocks external post requests when configured', async () => { + test.concurrent('blocks external post requests when configured', async () => { const mockCtx = createMockContext({ 'externalRequest.action': { "allow": false, @@ -1123,7 +1123,7 @@ describe('HTTP Request Unit Tests', () => { )).rejects.toThrow('Block external request. See externalRequest config options'); }); - test('allows post request when URL is in JWT token', async () => { + test.concurrent('allows post request when URL is in JWT token', async () => { const mockCtx = createMockContext({ 'externalRequest.action': { "allow": false, @@ -1160,7 +1160,7 @@ describe('HTTP Request Unit Tests', () => { expect(JSON.parse(result.body)).toEqual({ received: { test: 'data' } }); }); - test('applies gzip setting to POST requests', async () => { + test.concurrent('applies gzip setting to POST requests', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -1189,7 +1189,7 @@ describe('HTTP Request Unit Tests', () => { expect(responseBody.headers?.['accept-encoding'] === 'identity' || responseBody.headers?.['accept-encoding'] === undefined).toBe(true); }); - test('applies forever setting to POST requests', async () => { + test.concurrent('applies forever setting to POST requests', async () => { const mockCtx = createMockContext({ 'services.CoAuthoring.requestDefaults': { headers: { "User-Agent": "Node.js/6.13" }, @@ -1217,9 +1217,9 @@ describe('HTTP Request Unit Tests', () => { // When forever is true, connection should be 'keep-alive' expect(responseBody.headers?.connection?.toLowerCase()).toMatch(/keep-alive/i); - }, 30000); + }); - test('successfully routes POST request through a real proxy', async () => { + test.concurrent('successfully routes POST request through a real proxy', async () => { try { // Create context with proxy configuration const mockCtx = createMockContext({ From 115bb31da7e7f5cacdf0b9178ce4d9a9f80950db Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Tue, 22 Apr 2025 10:37:57 +0300 Subject: [PATCH 17/17] [tests] Add test for status!=200 --- tests/unit/request.tests.js | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/unit/request.tests.js b/tests/unit/request.tests.js index 355c728b..414c256a 100644 --- a/tests/unit/request.tests.js +++ b/tests/unit/request.tests.js @@ -103,6 +103,10 @@ describe('HTTP Request Unit Tests', () => { return; }); + app.use('/api/status/:code', (req, res) => { + res.status(Number(req.params.code)).send(); + }); + // Endpoint that redirects app.get('/api/redirect', (req, res) => { res.redirect('/api/data'); @@ -828,6 +832,25 @@ describe('HTTP Request Unit Tests', () => { // No need to clean up proxy server here anymore } }); + + test.concurrent('should return 205 status code for /status/205', async () => { + try { + await utils.downloadUrlPromise( + ctx, + `${BASE_URL}/api/status/205`, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + 1024 * 1024, + null, + false, + null, + null + ) + throw new Error('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('Error response:') + expect(error.statusCode).toBe(205); + } + }); }); test.concurrent('handles binary data correctly', async () => { @@ -1278,5 +1301,27 @@ describe('HTTP Request Unit Tests', () => { // No need to clean up proxy server here anymore } }); + + test.concurrent('should return 205 status code for /status/205', async () => { + try { + const postData = JSON.stringify({ test: 'data' }); + + const result = await utils.postRequestPromise( + ctx, + `${BASE_URL}/api/status/205`, + postData, + null, + postData.length, + { wholeCycle: '5s', connectionAndInactivity: '3s' }, + null, + false, + { 'Content-Type': 'application/json' } + ); + throw new Error('Expected an error to be thrown'); + } catch (error) { + expect(error.message).toContain('Error response:') + expect(error.statusCode).toBe(205); + } + }); }); }); \ No newline at end of file