From 03d4c829511181056c70057a5686255be86697b9 Mon Sep 17 00:00:00 2001 From: AntonSeleznev Date: Sun, 5 Jun 2022 20:52:12 +0300 Subject: [PATCH 01/28] apn use rawPayload --- src/sendAPN.js | 4 +++ test/send/sendAPN.js | 59 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/sendAPN.js b/src/sendAPN.js index 55b5cc6..3d5eb16 100644 --- a/src/sendAPN.js +++ b/src/sendAPN.js @@ -97,6 +97,10 @@ class APN { pushType: data.pushType, }); + if (data.rawPayload) { + message.rawPayload = data.rawPayload; + } + if (!this.connection) { return Promise.reject( this.connectionError || diff --git a/test/send/sendAPN.js b/test/send/sendAPN.js index c152f94..83dba73 100644 --- a/test/send/sendAPN.js +++ b/test/send/sendAPN.js @@ -34,6 +34,8 @@ const data = { sender: 'appfeel-test', }, }; +const experienceId = '43e798c-4dff073-2b58a85a-27c5d9fdf59-b69'; + const apnOptions = { cert: path.resolve('./test/send/cert.pem'), key: path.resolve('./test/send/key.pem'), @@ -261,6 +263,63 @@ describe('push-notifications-apn', () => { }); }); + describe('send notifications with rawPayload', () => { + before(() => { + sendMethod = sinon.stub( + apn.Provider.prototype, + 'send', + (message, _regIds) => { + expect(_regIds).to.be.instanceOf(Array); + _regIds.forEach((regId) => expect(regIds).to.include(regId)); + + const rawPayloadEq = { + ...data.custom, + experienceId, + apn: { + 'mutable-content': 1, + sound: data.sound, + alert: { + title: data.title, + body: data.body, + }, + }, + }; + expect(message).to.be.instanceOf(apn.Notification); + expect(message.rawPayload).to.deep.equal(rawPayloadEq); + return Promise.resolve({ + sent: _regIds, + }); + } + ); + }); + + after(() => { + sendMethod.restore(); + }); + + it('all responses should be successful', (done) => { + const rawPayloadPushData = { + topic: 'testTopic', + mutableContent: false, + rawPayload: { + experienceId, + ...data.custom, + apn: { + 'mutable-content': 1, + sound: data.sound, + alert: { + title: data.title, + body: data.body, + }, + }, + }, + }; + pn.send(regIds, rawPayloadPushData, (err, results) => + testSuccess(err, results, done) + ); + }); + }); + describe('send notifications with pushType property', () => { before(() => { sendMethod = sinon.stub( From 1c70880e345fee72e8ac38a004a879fc803dde1b Mon Sep 17 00:00:00 2001 From: AntonSeleznev Date: Mon, 11 Jul 2022 13:47:26 +0300 Subject: [PATCH 02/28] add fcm_notification field to sendGCM --- src/sendGCM.js | 2 +- test/send/sendGCM.js | 66 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/sendGCM.js b/src/sendGCM.js index aa28a0d..07d9bd7 100644 --- a/src/sendGCM.js +++ b/src/sendGCM.js @@ -89,7 +89,7 @@ const sendGCM = (regIds, data, settings) => { delete opts.id; const GCMSender = new gcm.Sender(id, opts); const promises = []; - const notification = { + const notification = data.fcm_notification || { title: data.title, // Android, iOS (Watch) body: data.body, // Android, iOS icon: data.icon, // Android diff --git a/test/send/sendGCM.js b/test/send/sendGCM.js index 1c6e3aa..c306e59 100644 --- a/test/send/sendGCM.js +++ b/test/send/sendGCM.js @@ -37,6 +37,12 @@ const gcmOpts = { id: 'your id', }, }; +const notificationOptions = { + title: 'Notification Title', + body: 'Notification Body', + image: 'https://s3.image.com', + color: '#000', +}; const pn = new PN(gcmOpts); const fErr = new Error('Forced error'); @@ -801,6 +807,66 @@ describe('push-notifications-gcm', () => { }); }); + describe('include fcm_notification option', () => { + before(() => { + sendMethod = sinon.stub( + gcm.Sender.prototype, + 'send', + (message, recipients, retries, cb) => { + expect(recipients).to.be.instanceOf(Object); + expect(recipients).to.have.property('registrationTokens'); + const { registrationTokens } = recipients; + expect(registrationTokens).to.be.instanceOf(Array); + registrationTokens.forEach((regId) => + expect(regIds).to.include(regId) + ); + expect(retries).to.be.a('number'); + expect(message).to.be.instanceOf(gcm.Message); + expect(message.params.notification.title).to.equal( + notificationOptions.title + ); + expect(message.params.notification.body).to.equal( + notificationOptions.body + ); + expect(message.params.notification.color).to.equal( + notificationOptions.color + ); + expect(message.params.notification.image).to.equal( + notificationOptions.image + ); + + expect(message.params.data.user_id).to.equal(538); + + cb(null, { + multicast_id: 'abc', + success: registrationTokens.length, + failure: 0, + results: registrationTokens.map((token) => ({ + message_id: '', + registration_id: token, + error: null, + })), + }); + } + ); + }); + + after(() => { + sendMethod.restore(); + }); + + it('all responses should be successful (callback, fcm_notification)', (done) => { + const androidData = { + ...data, + fcm_notification: notificationOptions, + custom: { user_id: 538 }, + }; + pn.send(regIds, androidData, (err, results) => + testSuccess(err, results, done) + ); + }); + }); + describe('send push notifications in phonegap-push compatibility mode', () => { const pushPhoneGap = new PN({ gcm: { From 7c09a102bba53f6f2fe9659e88a149600847937f Mon Sep 17 00:00:00 2001 From: AntonSeleznev Date: Mon, 11 Jul 2022 13:49:50 +0300 Subject: [PATCH 03/28] 2.0.3-banshiAnton.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e61b912..429115f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-pushnotifications", - "version": "2.0.3", + "version": "2.0.3-banshiAnton.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-pushnotifications", - "version": "2.0.3", + "version": "2.0.3-banshiAnton.1", "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", diff --git a/package.json b/package.json index 24ffb93..524916d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-pushnotifications", "description": "A cross-platform push service for node.js", - "version": "2.0.3", + "version": "2.0.3-banshiAnton.1", "author": { "name": "AppFeel", "email": "info@appfeel.com" From a3d8005be037c6ad34471ab5d016e6e010843e1c Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Thu, 13 Oct 2022 11:20:12 +0300 Subject: [PATCH 04/28] senderGCM: timeToLive calculated from expiry must not be negative --- src/sendGCM.js | 1 + test/send/sendGCM.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/sendGCM.js b/src/sendGCM.js index 07d9bd7..f5a96ba 100644 --- a/src/sendGCM.js +++ b/src/sendGCM.js @@ -4,6 +4,7 @@ const { DEFAULT_TTL, GCM_METHOD, GCM_MAX_TTL } = require('./constants'); const ttlFromExpiry = R.compose( R.min(GCM_MAX_TTL), + R.max(0), (expiry) => expiry - Math.floor(Date.now() / 1000) ); diff --git a/test/send/sendGCM.js b/test/send/sendGCM.js index c306e59..106302f 100644 --- a/test/send/sendGCM.js +++ b/test/send/sendGCM.js @@ -658,6 +658,48 @@ describe('push-notifications-gcm', () => { }); }); + describe('send push notifications with timeToLive calculated from expiry must not be negative', () => { + const expiredTimestampDate = Math.floor(Date.now() / 1000) - 1; + + before(() => { + sendMethod = sinon.stub( + gcm.Sender.prototype, + 'send', + (message, recipients, retries, cb) => { + expect(recipients).to.be.instanceOf(Object); + expect(recipients).to.have.property('registrationTokens'); + const { registrationTokens } = recipients; + expect(registrationTokens).to.be.instanceOf(Array); + registrationTokens.forEach((regId) => + expect(regIds).to.include(regId) + ); + expect(message.params.timeToLive).to.equal(0); + cb(null, { + multicast_id: 'abc', + success: registrationTokens.length, + failure: 0, + results: registrationTokens.map((token) => ({ + message_id: '', + registration_id: token, + error: null, + })), + }); + } + ); + }); + + after(() => { + sendMethod.restore(); + }); + + it('timeToLive from expiry must not exceed max TTL', (done) => { + const expiryData = { ...data, expiry: expiredTimestampDate }; + pn.send(regIds, expiryData, (err, results) => + testSuccess(err, results, done) + ); + }); + }); + describe('send push notifications with neither expiry nor timeToLive given', () => { before(() => { sendMethod = sinon.stub( From 70c86d48c40c97eecd2ddd9dd378d9df0e9a3d3e Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Thu, 13 Oct 2022 11:21:02 +0300 Subject: [PATCH 05/28] 2.0.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e61b912..8b670ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-pushnotifications", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-pushnotifications", - "version": "2.0.3", + "version": "2.0.4", "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", diff --git a/package.json b/package.json index 24ffb93..4695cc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-pushnotifications", "description": "A cross-platform push service for node.js", - "version": "2.0.3", + "version": "2.0.4", "author": { "name": "AppFeel", "email": "info@appfeel.com" From 3316ef2f6841bdf594a4ea6429bcd26f0bdf0707 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Thu, 13 Oct 2022 11:26:04 +0300 Subject: [PATCH 06/28] 2.0.4-banshiAnton --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8b670ed..3b66796 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-pushnotifications", - "version": "2.0.4", + "version": "2.0.4-banshiAnton", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-pushnotifications", - "version": "2.0.4", + "version": "2.0.4-banshiAnton", "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", diff --git a/package.json b/package.json index 4695cc3..5ac5155 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-pushnotifications", "description": "A cross-platform push service for node.js", - "version": "2.0.4", + "version": "2.0.4-banshiAnton", "author": { "name": "AppFeel", "email": "info@appfeel.com" From 07db58c85f0038c1149723aacdc1b65e679cf680 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 13 Sep 2023 17:09:26 +0300 Subject: [PATCH 07/28] add fcm method --- .eslintrc | 3 + .gitignore | 1 + package-lock.json | 3084 +++++++++++++++++++++++++++++++++++-- package.json | 1 + src/constants.js | 6 + src/push-notifications.js | 22 +- src/sendAPN.js | 57 +- src/sendFCM.js | 122 ++ src/sendGCM.js | 31 +- src/utils/fcmMessage.js | 107 ++ src/utils/tools.js | 80 + 11 files changed, 3276 insertions(+), 238 deletions(-) create mode 100644 src/sendFCM.js create mode 100644 src/utils/fcmMessage.js create mode 100644 src/utils/tools.js diff --git a/.eslintrc b/.eslintrc index 3f03e1f..29413ac 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,5 +2,8 @@ "extends": ["airbnb-base", "plugin:prettier/recommended"], "env": { "node": true + }, + "rules": { + "no-param-reassign": "off" } } diff --git a/.gitignore b/.gitignore index 2079a8f..8950ce6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ coverage lib release.sh .nyc_output +test.js \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3b66796..ec343b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", + "firebase-admin": "11.10.1", "node-adm": "0.9.1", "node-gcm": "1.0.5", "ramda": "0.28.0", @@ -530,10 +531,10 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", - "dev": true, + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "devOptional": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -1761,6 +1762,267 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@fastify/busboy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "node_modules/@firebase/component": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", + "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", + "dependencies": { + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", + "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==", + "dependencies": { + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz", + "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/database": "0.14.4", + "@firebase/database-types": "0.10.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", + "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==", + "dependencies": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.3" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.7.0.tgz", + "integrity": "sha512-bkH2jb5KkQSUa+NAvpip9HQ+rpYhi77IaqHovWuN07adVmvNXX08gPpvPWEzoXYa/wDjEVI7LiAtCWkJJEYTNg==", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^3.5.7", + "protobufjs": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", + "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz", + "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "fast-xml-parser": "^4.2.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "optional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@google-cloud/storage/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz", + "integrity": "sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.9.tgz", + "integrity": "sha512-YJsOehVXzgurc+lLAxYnlSMc1p/Gu6VAvnfx0ATi2nzvr0YZcjhmZDeY8SeAKv1M7zE3aEJH0Xo9mK1iZ8GYoQ==", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", @@ -1892,6 +2154,18 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "optional": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", @@ -2093,6 +2367,70 @@ "node": ">=0.6.0" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true + }, "node_modules/@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -2117,6 +2455,24 @@ "node": ">=10" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, "node_modules/@types/cacheable-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", @@ -2133,7 +2489,53 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "devOptional": true + }, + "node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.36", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", + "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "optional": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, + "node_modules/@types/glob/node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "optional": true }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", @@ -2141,12 +2543,25 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "dev": true }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/keyv": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", @@ -2156,6 +2571,39 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==", + "optional": true + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "optional": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "optional": true + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, "node_modules/@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -2165,8 +2613,7 @@ "node_modules/@types/node": { "version": "16.11.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.9.tgz", - "integrity": "sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==", - "dev": true + "integrity": "sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2174,6 +2621,16 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/qs": { + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, "node_modules/@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -2183,17 +2640,58 @@ "@types/node": "*" } }, + "node_modules/@types/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "optional": true, + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/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==", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -2205,7 +2703,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, + "devOptional": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -2312,7 +2810,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -2321,7 +2819,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" @@ -2334,7 +2832,7 @@ "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, + "devOptional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2346,7 +2844,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "devOptional": true }, "node_modules/anymatch": { "version": "3.1.2", @@ -2455,7 +2953,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -2497,7 +2995,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, + "devOptional": true, "dependencies": { "retry": "0.13.1" } @@ -2581,13 +3079,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "devOptional": true }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -2618,8 +3116,17 @@ "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", "dev": true }, - "node_modules/bl": { - "version": "4.1.0", + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/bl": { + "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, @@ -2629,6 +3136,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "optional": true + }, "node_modules/bn.js": { "version": "4.11.9", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", @@ -2700,7 +3213,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2947,6 +3460,18 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "optional": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", @@ -3231,11 +3756,23 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "devOptional": true }, "node_modules/configstore": { "version": "5.0.1", @@ -3528,7 +4065,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "devOptional": true }, "node_modules/default-require-extensions": { "version": "3.0.0", @@ -3661,6 +4198,18 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -3688,17 +4237,32 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "devOptional": true }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.4.0" } }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "optional": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -3769,7 +4333,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -3792,6 +4356,97 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "optional": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "optional": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "optional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/eslint": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", @@ -4044,7 +4699,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, + "devOptional": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -4135,7 +4790,7 @@ "version": "9.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, + "devOptional": true, "dependencies": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", @@ -4149,7 +4804,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, + "devOptional": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4186,7 +4841,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -4195,11 +4850,20 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/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==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", @@ -4283,7 +4947,35 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "devOptional": true + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "optional": true + }, + "node_modules/fast-xml-parser": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz", + "integrity": "sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } }, "node_modules/fastq": { "version": "1.13.0", @@ -4294,6 +4986,17 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -4423,6 +5126,79 @@ "node": ">=4" } }, + "node_modules/firebase-admin": { + "version": "11.10.1", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz", + "integrity": "sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ==", + "dependencies": { + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^0.3.4", + "@firebase/database-types": "^0.10.4", + "@types/node": ">=12.12.47", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^6.6.0", + "@google-cloud/storage": "^6.9.5" + } + }, + "node_modules/firebase-admin/node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "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.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/firebase-admin/node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/firebase-admin/node_modules/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==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-admin/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -4510,7 +5286,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "devOptional": true }, "node_modules/fsevents": { "version": "2.3.2", @@ -4536,7 +5312,35 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "devOptional": true + }, + "node_modules/gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -4551,7 +5355,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, + "devOptional": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4647,7 +5451,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4728,6 +5532,125 @@ "node": ">=8" } }, + "node_modules/google-auth-library": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz", + "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.3.0", + "gtoken": "^6.1.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/google-auth-library/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-auth-library/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-gax": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz", + "integrity": "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.8.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "@types/rimraf": "^3.0.2", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^8.0.2", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^1.0.0", + "protobufjs": "7.2.4", + "protobufjs-cli": "1.1.1", + "retry-request": "^5.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js", + "minifyProtoJson": "build/tools/minify.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/google-gax/node_modules/protobufjs": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/google-p12-pem": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", + "optional": true, + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/google-p12-pem/node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "optional": true, + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/got": { "version": "11.8.3", "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", @@ -4757,7 +5680,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -4771,6 +5694,41 @@ "node": ">=4.x" } }, + "node_modules/gtoken": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", + "optional": true, + "dependencies": { + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/gtoken/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/gtoken/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -4908,6 +5866,25 @@ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", "dev": true }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -5101,7 +6078,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5316,7 +6293,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -5480,11 +6457,17 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -5752,6 +6735,14 @@ "node": ">=8" } }, + "node_modules/jose": { + "version": "4.14.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.6.tgz", + "integrity": "sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5771,12 +6762,59 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "optional": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "optional": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5789,6 +6827,15 @@ "node": ">=4" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -5891,6 +6938,38 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jwks-rsa": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.0.1.tgz", + "integrity": "sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw==", + "dependencies": { + "@types/express": "^4.17.14", + "@types/jsonwebtoken": "^9.0.0", + "debug": "^4.3.4", + "jose": "^4.10.4", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jwks-rsa/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -5909,6 +6988,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -5934,12 +7022,26 @@ "node": ">= 0.8.0" } }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, "node_modules/lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "optional": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -5995,6 +7097,17 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -6095,6 +7208,12 @@ "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true + }, "node_modules/loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -6130,7 +7249,6 @@ "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, "dependencies": { "yallist": "^4.0.0" }, @@ -6138,6 +7256,29 @@ "node": ">=10" } }, + "node_modules/lru-memoizer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", + "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, "node_modules/macos-release": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", @@ -6172,6 +7313,56 @@ "node": ">=4" } }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "optional": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "optional": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "optional": true + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "optional": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "optional": true + }, "node_modules/meow": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", @@ -6238,6 +7429,18 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -6284,7 +7487,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, + "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6319,6 +7522,18 @@ "node": ">=0.10.0" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", @@ -6573,10 +7788,10 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "devOptional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -6892,6 +8107,15 @@ "node": "*" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", @@ -6963,7 +8187,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -7436,7 +8660,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -7690,12 +8914,164 @@ "node": ">=8" } }, + "node_modules/proto3-json-serializer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz", + "integrity": "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw==", + "optional": true, + "dependencies": { + "protobufjs": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs-cli": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", + "optional": true, + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "optional": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/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==", + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "optional": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, "node_modules/protocols": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", "dev": true }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "node_modules/psl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", @@ -7865,7 +9241,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, + "devOptional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8250,7 +9626,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -8261,7 +9637,16 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "node_modules/resolve": { + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "optional": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", @@ -8315,11 +9700,24 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 4" } }, + "node_modules/retry-request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -8334,7 +9732,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "devOptional": true, "dependencies": { "glob": "^7.1.3" }, @@ -8683,6 +10081,21 @@ "tweetnacl": "~0.14.0" } }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -8696,7 +10109,7 @@ "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==", - "dev": true, + "devOptional": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -8705,7 +10118,7 @@ "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, + "devOptional": true, "funding": [ { "type": "github", @@ -8722,14 +10135,14 @@ ] }, "node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" @@ -8765,7 +10178,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8804,16 +10217,28 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true + }, "node_modules/supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, + "devOptional": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -8825,11 +10250,36 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } }, + "node_modules/teeny-request": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/temp-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", @@ -8896,6 +10346,11 @@ "node": ">=8" } }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -8966,7 +10421,7 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true + "devOptional": true }, "node_modules/trim-newlines": { "version": "2.0.0", @@ -9004,8 +10459,7 @@ "node_modules/tslib": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -9063,6 +10517,24 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "optional": true + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -9078,6 +10550,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "optional": true + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -9251,7 +10729,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "devOptional": true }, "node_modules/util/node_modules/inherits": { "version": "2.0.1", @@ -9347,13 +10825,34 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true + "devOptional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, + "devOptional": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -9441,7 +10940,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -9456,7 +10955,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "devOptional": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9473,7 +10972,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "devOptional": true }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -9496,6 +10995,12 @@ "node": ">=8" } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "optional": true + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -9505,8 +11010,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -9594,6 +11098,18 @@ "engines": { "node": ">=10" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -9963,10 +11479,10 @@ } }, "@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", - "dev": true + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "devOptional": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", @@ -10799,6 +12315,223 @@ } } }, + "@fastify/busboy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "requires": { + "text-decoding": "^1.0.0" + } + }, + "@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "@firebase/component": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", + "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", + "requires": { + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "@firebase/database": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", + "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==", + "requires": { + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "@firebase/database-compat": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz", + "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==", + "requires": { + "@firebase/component": "0.6.4", + "@firebase/database": "0.14.4", + "@firebase/database-types": "0.10.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "@firebase/database-types": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", + "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==", + "requires": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.3" + } + }, + "@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@google-cloud/firestore": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.7.0.tgz", + "integrity": "sha512-bkH2jb5KkQSUa+NAvpip9HQ+rpYhi77IaqHovWuN07adVmvNXX08gPpvPWEzoXYa/wDjEVI7LiAtCWkJJEYTNg==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^3.5.7", + "protobufjs": "^7.0.0" + } + }, + "@google-cloud/paginator": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", + "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + } + }, + "@google-cloud/projectify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", + "optional": true + }, + "@google-cloud/promisify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", + "optional": true + }, + "@google-cloud/storage": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz", + "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==", + "optional": true, + "requires": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "fast-xml-parser": "^4.2.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.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==", + "optional": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true + } + } + }, + "@grpc/grpc-js": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz", + "integrity": "sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg==", + "optional": true, + "requires": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.9.tgz", + "integrity": "sha512-YJsOehVXzgurc+lLAxYnlSMc1p/Gu6VAvnfx0ATi2nzvr0YZcjhmZDeY8SeAKv1M7zE3aEJH0Xo9mK1iZ8GYoQ==", + "optional": true, + "requires": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true + } + } + }, "@humanwhocodes/config-array": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", @@ -10905,6 +12638,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "optional": true, + "requires": { + "lodash": "^4.17.21" + } + }, "@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", @@ -11085,6 +12827,70 @@ } } }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true + }, "@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -11100,6 +12906,21 @@ "defer-to-connect": "^2.0.0" } }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, "@types/cacheable-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", @@ -11116,7 +12937,55 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "devOptional": true + }, + "@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.36", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", + "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "optional": true, + "requires": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + }, + "dependencies": { + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "optional": true + } + } }, "@types/http-cache-semantics": { "version": "4.0.1", @@ -11124,12 +12993,25 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "dev": true }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "requires": { + "@types/node": "*" + } + }, "@types/keyv": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", @@ -11139,6 +13021,39 @@ "@types/node": "*" } }, + "@types/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==", + "optional": true + }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, + "@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "optional": true, + "requires": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "optional": true + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -11148,8 +13063,7 @@ "@types/node": { "version": "16.11.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.9.tgz", - "integrity": "sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==", - "dev": true + "integrity": "sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==" }, "@types/parse-json": { "version": "4.0.0", @@ -11157,6 +13071,16 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/qs": { + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -11166,23 +13090,61 @@ "@types/node": "*" } }, + "@types/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "optional": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "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==", + "optional": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true + "devOptional": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, + "devOptional": true, "requires": {} }, "agent-base": { @@ -11265,13 +13227,13 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "devOptional": true }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, + "devOptional": true, "requires": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" @@ -11281,7 +13243,7 @@ "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, + "devOptional": true, "requires": { "color-name": "~1.1.4" } @@ -11290,7 +13252,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "devOptional": true } } }, @@ -11374,7 +13336,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true + "devOptional": true }, "asn1": { "version": "0.2.3", @@ -11407,7 +13369,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, + "devOptional": true, "requires": { "retry": "0.13.1" } @@ -11478,13 +13440,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "devOptional": true }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "devOptional": true }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -11501,6 +13463,12 @@ "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", "dev": true }, + "bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "optional": true + }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -11512,6 +13480,12 @@ "readable-stream": "^3.4.0" } }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "optional": true + }, "bn.js": { "version": "4.11.9", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", @@ -11561,7 +13535,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11732,6 +13706,15 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "optional": true, + "requires": { + "lodash": "^4.17.15" + } + }, "chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", @@ -11951,11 +13934,20 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "devOptional": true }, "configstore": { "version": "5.0.1", @@ -12176,7 +14168,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "devOptional": true }, "default-require-extensions": { "version": "3.0.0", @@ -12283,6 +14275,18 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -12310,17 +14314,29 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "devOptional": true }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, + "devOptional": true, "requires": { "once": "^1.4.0" } }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "optional": true + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -12379,7 +14395,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "devOptional": true }, "escape-goat": { "version": "2.1.1", @@ -12393,6 +14409,72 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "optional": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "optional": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, "eslint": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", @@ -12649,13 +14731,13 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true + "devOptional": true }, "espree": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, + "devOptional": true, "requires": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", @@ -12666,7 +14748,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "devOptional": true }, "esquery": { "version": "1.4.0", @@ -12690,13 +14772,19 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true + "devOptional": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "devOptional": true + }, + "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==", + "optional": true }, "execa": { "version": "4.1.0", @@ -12769,7 +14857,22 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "devOptional": true + }, + "fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "optional": true + }, + "fast-xml-parser": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz", + "integrity": "sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==", + "optional": true, + "requires": { + "strnum": "^1.0.5" + } }, "fastq": { "version": "1.13.0", @@ -12780,6 +14883,14 @@ "reusify": "^1.0.4" } }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -12875,6 +14986,60 @@ } } }, + "firebase-admin": { + "version": "11.10.1", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz", + "integrity": "sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ==", + "requires": { + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^0.3.4", + "@firebase/database-types": "^0.10.4", + "@google-cloud/firestore": "^6.6.0", + "@google-cloud/storage": "^6.9.5", + "@types/node": ">=12.12.47", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "dependencies": { + "jsonwebtoken": { + "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.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.5.4" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "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" + } + }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + } + } + }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -12947,7 +15112,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "devOptional": true }, "fsevents": { "version": "2.3.2", @@ -12966,7 +15131,29 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "devOptional": true + }, + "gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "requires": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + } + }, + "gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "requires": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + } }, "gensync": { "version": "1.0.0-beta.2", @@ -12978,7 +15165,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "devOptional": true }, "get-func-name": { "version": "2.0.0", @@ -13053,7 +15240,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "devOptional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -13109,6 +15296,108 @@ } } }, + "google-auth-library": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz", + "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.3.0", + "gtoken": "^6.1.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "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", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + } + } + }, + "google-gax": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz", + "integrity": "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w==", + "optional": true, + "requires": { + "@grpc/grpc-js": "~1.8.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "@types/rimraf": "^3.0.2", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^8.0.2", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^1.0.0", + "protobufjs": "7.2.4", + "protobufjs-cli": "1.1.1", + "retry-request": "^5.0.0" + }, + "dependencies": { + "protobufjs": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + } + } + }, + "google-p12-pem": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", + "optional": true, + "requires": { + "node-forge": "^1.3.1" + }, + "dependencies": { + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "optional": true + } + } + }, "got": { "version": "11.8.3", "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", @@ -13128,18 +15417,52 @@ "responselike": "^2.0.0" } }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "devOptional": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "gtoken": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", + "optional": true, + "requires": { + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", + "jws": "^4.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "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", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -13238,6 +15561,22 @@ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", "dev": true }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -13366,7 +15705,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, + "devOptional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -13525,7 +15864,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "devOptional": true }, "is-glob": { "version": "4.0.3", @@ -13632,7 +15971,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true + "devOptional": true + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true }, "is-string": { "version": "1.0.7", @@ -13837,6 +16182,11 @@ "istanbul-lib-report": "^3.0.0" } }, + "jose": { + "version": "4.14.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.6.tgz", + "integrity": "sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13853,18 +16203,67 @@ "esprima": "^4.0.0" } }, + "js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "optional": true, + "requires": { + "xmlcreate": "^2.0.4" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "optional": true, + "requires": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "optional": true + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -13953,6 +16352,29 @@ "safe-buffer": "^5.0.1" } }, + "jwks-rsa": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.0.1.tgz", + "integrity": "sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw==", + "requires": { + "@types/express": "^4.17.14", + "@types/jsonwebtoken": "^9.0.0", + "debug": "^4.3.4", + "jose": "^4.10.4", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -13971,6 +16393,15 @@ "json-buffer": "3.0.1" } }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -13990,12 +16421,26 @@ "type-check": "~0.4.0" } }, + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "optional": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -14041,6 +16486,17 @@ "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": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -14128,6 +16584,12 @@ "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -14157,11 +16619,35 @@ "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" } }, + "lru-memoizer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", + "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", + "requires": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "requires": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + } + } + }, "macos-release": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", @@ -14184,6 +16670,46 @@ "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", "dev": true }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "optional": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "optional": true + } + } + }, + "markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "optional": true, + "requires": {} + }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "optional": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "optional": true + }, "meow": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", @@ -14240,6 +16766,12 @@ "picomatch": "^2.2.3" } }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true + }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -14274,7 +16806,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, + "devOptional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -14302,6 +16834,12 @@ } } }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + }, "mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", @@ -14495,10 +17033,10 @@ "integrity": "sha1-+ManL/rbGn39ZjcQLJUKmpSW6EI=" }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "devOptional": true, "requires": { "whatwg-url": "^5.0.0" } @@ -14744,6 +17282,12 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true + }, "object-inspect": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", @@ -14794,7 +17338,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, + "devOptional": true, "requires": { "wrappy": "1" } @@ -15169,7 +17713,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "devOptional": true }, "path-key": { "version": "3.1.1", @@ -15351,12 +17895,125 @@ "fromentries": "^1.2.0" } }, + "proto3-json-serializer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz", + "integrity": "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw==", + "optional": true, + "requires": { + "protobufjs": "^7.0.0" + } + }, + "protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, + "protobufjs-cli": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", + "optional": true, + "requires": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "optional": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "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==", + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "optional": true, + "requires": { + "rimraf": "^3.0.0" + } + } + } + }, "protocols": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", "dev": true }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "psl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", @@ -15480,7 +18137,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, + "devOptional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -15775,7 +18432,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "devOptional": true }, "require-main-filename": { "version": "2.0.0", @@ -15783,6 +18440,15 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "optional": true, + "requires": { + "lodash": "^4.17.21" + } + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -15828,7 +18494,17 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true + "devOptional": true + }, + "retry-request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", + "optional": true, + "requires": { + "debug": "^4.1.1", + "extend": "^3.0.2" + } }, "reusify": { "version": "1.0.4", @@ -15840,7 +18516,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "devOptional": true, "requires": { "glob": "^7.1.3" } @@ -16110,6 +18786,21 @@ "tweetnacl": "~0.14.0" } }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, "strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -16120,7 +18811,7 @@ "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==", - "dev": true, + "devOptional": true, "requires": { "safe-buffer": "~5.2.0" }, @@ -16129,19 +18820,19 @@ "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 + "devOptional": true } } }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "string.prototype.trimend": { @@ -16168,7 +18859,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "devOptional": true, "requires": { "ansi-regex": "^5.0.1" } @@ -16195,13 +18886,25 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "devOptional": true + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, + "devOptional": true, "requires": { "has-flag": "^4.0.0" }, @@ -16210,7 +18913,28 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "devOptional": true + } + } + }, + "teeny-request": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", + "optional": true, + "requires": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "optional": true } } }, @@ -16267,6 +18991,11 @@ "minimatch": "^3.0.4" } }, + "text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -16322,7 +19051,7 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true + "devOptional": true }, "trim-newlines": { "version": "2.0.0", @@ -16356,8 +19085,7 @@ "tslib": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, "tunnel-agent": { "version": "0.6.0", @@ -16403,6 +19131,18 @@ "is-typedarray": "^1.0.0" } }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "optional": true + }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -16415,6 +19155,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "optional": true + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -16559,7 +19305,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "devOptional": true }, "uuid": { "version": "3.3.2", @@ -16639,13 +19385,28 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true + "devOptional": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, + "devOptional": true, "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -16712,7 +19473,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "devOptional": true }, "workerpool": { "version": "6.2.0", @@ -16724,7 +19485,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "devOptional": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16735,7 +19496,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "devOptional": true }, "write-file-atomic": { "version": "3.0.3", @@ -16755,6 +19516,12 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "optional": true + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -16764,8 +19531,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.2", @@ -16833,6 +19599,12 @@ "dev": true } } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "optional": true } } } diff --git a/package.json b/package.json index 5ac5155..eaa5253 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ }, "dependencies": { "@parse/node-apn": "5.1.3", + "firebase-admin": "11.10.1", "node-adm": "0.9.1", "node-gcm": "1.0.5", "ramda": "0.28.0", diff --git a/src/constants.js b/src/constants.js index a5998b1..a220e49 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,6 +3,7 @@ module.exports = { GCM_MAX_TTL: 2419200, // 4 weeks in seconds (https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json) APN_METHOD: 'apn', GCM_METHOD: 'gcm', + FCM_METHOD: 'fcm', ADM_METHOD: 'adm', WNS_METHOD: 'wns', WEB_METHOD: 'webPush', @@ -11,6 +12,10 @@ module.exports = { gcm: { id: null, // PUT YOUR GCM SERVER API KEY, }, + fcm: { + appName: null, + serviceAccountKey: null, + }, apn: { // See options at https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown token: null, @@ -65,5 +70,6 @@ module.exports = { // contentEncoding: '< Encoding type, e.g.: aesgcm or aes128gcm >' }, isAlwaysUseFCM: false, + useFCMMethodInsteadOfGCM: false, }, }; diff --git a/src/push-notifications.js b/src/push-notifications.js index 95fbe1b..dd62ee5 100644 --- a/src/push-notifications.js +++ b/src/push-notifications.js @@ -2,9 +2,11 @@ import sendGCM from './sendGCM'; import APN from './sendAPN'; +import sendFCM from './sendFCM'; import sendADM from './sendADM'; import sendWNS from './sendWNS'; import sendWebPush from './sendWeb'; + import { DEFAULT_SETTINGS, UNKNOWN_METHOD, @@ -13,6 +15,7 @@ import { ADM_METHOD, GCM_METHOD, APN_METHOD, + FCM_METHOD, } from './constants'; class PN { @@ -45,7 +48,7 @@ class PN { return WEB_METHOD; } if (this.settings.isAlwaysUseFCM) { - return GCM_METHOD; + return this.settings.useFCMMethodInsteadOfGCM ? FCM_METHOD : GCM_METHOD; } if (regId.substring(0, 4) === 'http') { return WNS_METHOD; @@ -54,7 +57,7 @@ class PN { return ADM_METHOD; } if (regId.length > 64) { - return GCM_METHOD; + return this.settings.useFCMMethodInsteadOfGCM ? FCM_METHOD : GCM_METHOD; } if (regId.length === 64) { return APN_METHOD; @@ -64,7 +67,7 @@ class PN { send(_regIds, data, callback) { const promises = []; - const regIdsGCM = []; + const regIdsFCM = []; const regIdsAPN = []; const regIdsWNS = []; const regIdsADM = []; @@ -78,8 +81,8 @@ class PN { if (pushMethod === WEB_METHOD) { regIdsWebPush.push(regId); - } else if (pushMethod === GCM_METHOD) { - regIdsGCM.push(regId); + } else if (pushMethod === GCM_METHOD || pushMethod === FCM_METHOD) { + regIdsFCM.push(regId); } else if (pushMethod === WNS_METHOD) { regIdsWNS.push(regId); } else if (pushMethod === ADM_METHOD) { @@ -92,9 +95,12 @@ class PN { }); try { - // Android GCM - if (regIdsGCM.length > 0) { - promises.push(this.sendWith(sendGCM, regIdsGCM, data)); + // Android GCM / FCM (Android/iOS) + if (regIdsFCM.length > 0) { + const method = this.settings.useFCMMethodInsteadOfGCM + ? sendFCM + : sendGCM; + promises.push(this.sendWith(method, regIdsFCM, data)); } // iOS APN diff --git a/src/sendAPN.js b/src/sendAPN.js index 3d5eb16..5ffa473 100644 --- a/src/sendAPN.js +++ b/src/sendAPN.js @@ -1,54 +1,11 @@ const apn = require('@parse/node-apn'); const R = require('ramda'); -const { DEFAULT_TTL, APN_METHOD } = require('./constants'); - -const expiryFromTtl = (ttl) => ttl + Math.floor(Date.now() / 1000); - -const extractExpiry = R.cond([ - [R.propIs(Number, 'expiry'), R.prop('expiry')], - [ - R.propIs(Number, 'timeToLive'), - ({ timeToLive }) => expiryFromTtl(timeToLive), - ], - [R.T, () => expiryFromTtl(DEFAULT_TTL)], -]); - -const getPropValueOrUndefinedIfIsSilent = (propName, data) => - R.ifElse( - R.propEq('silent', true), - R.always(undefined), - R.prop(propName) - )(data); - -const toJSONorUndefined = R.tryCatch(JSON.parse, R.always(undefined)); - -const alertLocArgsToJSON = R.evolve({ - alert: { - 'title-loc-args': toJSONorUndefined, - 'loc-args': toJSONorUndefined, - }, -}); - -const getDefaultAlert = (data) => ({ - title: data.title, - body: data.body, - 'title-loc-key': data.titleLocKey, - 'title-loc-args': data.titleLocArgs, - 'loc-key': data.locKey, - // bodyLocArgs is kept for backward compatibility - 'loc-args': data.locArgs || data.bodyLocArgs, - 'launch-image': data.launchImage, - action: data.action, -}); - -const alertOrDefault = (data) => - R.when( - R.propSatisfies(R.isNil, 'alert'), - R.assoc('alert', getDefaultAlert(data)) - ); - -const getParsedAlertOrDefault = (data) => - R.pipe(alertOrDefault(data), alertLocArgsToJSON)(data); +const { APN_METHOD } = require('./constants'); +const { + expiryApns, + getPropValueOrUndefinedIfIsSilent, + getParsedAlertOrDefault, +} = require('./utils/tools'); const getDeviceTokenOrSelf = R.ifElse( R.has('device'), @@ -75,7 +32,7 @@ class APN { sendAPN(regIds, data) { const message = new apn.Notification({ retryLimit: data.retries || -1, - expiry: extractExpiry(data), + expiry: expiryApns(data), priority: data.priority === 'normal' || data.silent === true ? 5 : 10, encoding: data.encoding, payload: data.custom || {}, diff --git a/src/sendFCM.js b/src/sendFCM.js new file mode 100644 index 0000000..5a55de9 --- /dev/null +++ b/src/sendFCM.js @@ -0,0 +1,122 @@ +const R = require('ramda'); +const firebaseAdmin = require('firebase-admin'); + +const { FCM_METHOD } = require('./constants'); +const FcmMessage = require('./utils/fcmMessage'); +const { + propValueToSingletonArray, + containsValidRecipients, +} = require('./utils/tools'); + +const getRecipientList = R.cond([ + [R.has('tokens'), R.prop('tokens')], + [R.has('token'), propValueToSingletonArray('token')], + [R.has('condition'), propValueToSingletonArray('condition')], + [R.has('topic'), propValueToSingletonArray('topic')], +]); + +const sendChunk = (firebaseApp, recipients, message) => { + const firebaseMessage = message.build(recipients); + + console.log('[firebaseMessage]', JSON.stringify(firebaseMessage, null, 5)); + + return firebaseAdmin + .messaging(firebaseApp) + .sendEachForMulticast(firebaseMessage, message.dryRun) + .then((response, err) => { + const recipientList = getRecipientList(recipients); + if (err) { + return { + method: FCM_METHOD, + success: 0, + failure: recipientList.length, + message: recipientList.map((value) => ({ + originalRegId: value, + regId: value, + error: err, + errorMsg: err instanceof Error ? err.message : err, + })), + }; + } + if (response && response.responses !== undefined) { + let regIndex = 0; + return { + method: FCM_METHOD, + success: response.successCount, + failure: response.failureCount, + message: response.responses.map((value) => { + const regToken = recipientList[regIndex]; + regIndex += 1; + return { + messageId: value.message_id, + originalRegId: regToken, + regId: value.registration_id || regToken, + error: value.error ? new Error(value.error) : null, + errorMsg: value.error ? value.error.message || value.error : null, + }; + }), + }; + } + return { + method: FCM_METHOD, + success: response.successCount, + failure: response.failureCount, + message: recipientList.map((value) => ({ + originalRegId: value, + regId: value, + error: new Error('unknown'), + errorMsg: 'unknown', + })), + }; + }); +}; + +const sendFCM = (regIds, data, settings) => { + const appName = `${settings.fcm.appName}`; + const opts = { + credential: firebaseAdmin.credential.cert(settings.fcm.serviceAccountKey), + }; + const firebaseApp = firebaseAdmin.initializeApp(opts, appName); + firebaseAdmin.INTERNAL.appStore.removeApp(appName); + + const promises = []; + + const fcmMessage = FcmMessage.build(data, regIds); + + let chunk = 0; + + if (containsValidRecipients(data)) { + if (data.recipients.to) { + data.recipients.topic = data.recipients.to; + delete data.recipients.to; + } + promises.push(sendChunk(firebaseApp, data.recipients, fcmMessage)); + } else { + do { + const registrationTokens = regIds.slice(chunk * 1000, (chunk + 1) * 1000); + promises.push( + sendChunk(firebaseApp, { tokens: registrationTokens }, fcmMessage) + ); + chunk += 1; + } while (1000 * chunk < regIds.length); + } + + return Promise.all(promises).then((results) => { + const resumed = { + method: FCM_METHOD, + success: 0, + failure: 0, + message: [], + }; + + results.forEach((result) => { + resumed.success += result.success; + resumed.failure += result.failure; + resumed.message.push(...result.message); + }); + + return resumed; + }); +}; + +module.exports = sendFCM; diff --git a/src/sendGCM.js b/src/sendGCM.js index f5a96ba..495a4b9 100644 --- a/src/sendGCM.js +++ b/src/sendGCM.js @@ -1,28 +1,11 @@ const gcm = require('node-gcm'); const R = require('ramda'); -const { DEFAULT_TTL, GCM_METHOD, GCM_MAX_TTL } = require('./constants'); - -const ttlFromExpiry = R.compose( - R.min(GCM_MAX_TTL), - R.max(0), - (expiry) => expiry - Math.floor(Date.now() / 1000) -); - -const extractTimeToLive = R.cond([ - [R.propIs(Number, 'expiry'), ({ expiry }) => ttlFromExpiry(expiry)], - [R.propIs(Number, 'timeToLive'), R.prop('timeToLive')], - [R.T, R.always(DEFAULT_TTL)], -]); - -const pathIsString = R.pathSatisfies(R.is(String)); - -const containsValidRecipients = R.either( - pathIsString(['recipients', 'to']), - pathIsString(['recipients', 'condition']) -); - -const propValueToSingletonArray = (propName) => - R.compose(R.of, R.prop(propName)); +const { GCM_METHOD } = require('./constants'); +const { + ttlAndroid, + containsValidRecipients, + propValueToSingletonArray, +} = require('./utils/tools'); const getRecipientList = R.cond([ [R.has('registrationTokens'), R.prop('registrationTokens')], @@ -138,7 +121,7 @@ const sendGCM = (regIds, data, settings) => { priority: data.priority === 'normal' ? 'normal' : 'high', contentAvailable: data.silent ? true : data.contentAvailable || false, delayWhileIdle: data.delayWhileIdle || false, - timeToLive: extractTimeToLive(data), + timeToLive: ttlAndroid(data), restrictedPackageName: data.restrictedPackageName, dryRun: data.dryRun || false, data: opts.phonegap === true ? Object.assign(custom, notification) : custom, // See https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#android-behaviour diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js new file mode 100644 index 0000000..587388b --- /dev/null +++ b/src/utils/fcmMessage.js @@ -0,0 +1,107 @@ +const { Notification: ApnsMessage } = require('@parse/node-apn'); +const { Message: GsmMessage } = require('node-gcm'); +const { + ttlAndroid, + expiryApns, + getPropValueOrUndefinedIfIsSilent, + getParsedAlertOrDefault, +} = require('./tools'); + +class FcmMessage { + constructor(params) { + this.data = params.data; + this.android = params.android; + this.apns = params.apns; + } + + build(recipients) { + return { + data: this.data, + android: this.android, + apns: this.apns, + + ...recipients, + }; + } + + static normalizeDataParams(data) { + if (!data) return {}; + return Object.entries(data).reduce((normalized, [key, value]) => { + if (value === undefined || value === null) { + return normalized; + } + + normalized[key] = + typeof value === 'string' ? value : JSON.stringify(value); + + return normalized; + }, {}); + } + + static buildAndroidMessage(params) { + const notification = params.silent + ? undefined + : params.fcm_notification || undefined; + + const message = new GsmMessage({ + collapseKey: params.collapseKey, + priority: params.priority === 'normal' ? 'normal' : 'high', + timeToLive: ttlAndroid(params), + restrictedPackageName: params.restrictedPackageName, + notification, + }); + + const androidMessage = message.toJson(); + + androidMessage.ttl = androidMessage.time_to_live * 1000; + + delete androidMessage.content_available; + delete androidMessage.delay_while_idle; + delete androidMessage.time_to_live; + + return androidMessage; + } + + static buildApnsMessage(params) { + const message = new ApnsMessage({ + expiry: expiryApns(params), + priority: params.priority === 'normal' || params.silent ? 5 : 10, + encoding: params.encoding, + badge: getPropValueOrUndefinedIfIsSilent('badge', params), + sound: getPropValueOrUndefinedIfIsSilent('sound', params), + alert: getPropValueOrUndefinedIfIsSilent( + 'alert', + getParsedAlertOrDefault(params) + ), + topic: params.topic, + category: params.category || params.clickAction, + contentAvailable: params.contentAvailable, + mdm: params.mdm, + urlArgs: params.urlArgs, + truncateAtWordEnd: params.truncateAtWordEnd, + collapseId: params.collapseKey, + mutableContent: params.mutableContent || 0, + threadId: params.threadId, + pushType: params.pushType, + }); + + if (params.rawPayload) { + message.rawPayload = params.rawPayload; + } + + const headers = message.headers() || {}; + const payload = message.toJSON() || {}; + + return { headers: this.normalizeDataParams(headers), payload }; + } + + static build(params, recipients) { + const data = this.normalizeDataParams(params.custom); + const android = this.buildAndroidMessage(params); + const apns = this.buildApnsMessage(params); + + return new this({ data, android, apns }, recipients); + } +} + +module.exports = FcmMessage; diff --git a/src/utils/tools.js b/src/utils/tools.js new file mode 100644 index 0000000..3a1c3eb --- /dev/null +++ b/src/utils/tools.js @@ -0,0 +1,80 @@ +const R = require('ramda'); +const { DEFAULT_TTL, GCM_MAX_TTL } = require('../constants'); + +const ttlFromExpiry = R.compose( + R.min(GCM_MAX_TTL), + R.max(0), + (expiry) => expiry - Math.floor(Date.now() / 1000) +); + +const extractTimeToLive = R.cond([ + [R.propIs(Number, 'expiry'), ({ expiry }) => ttlFromExpiry(expiry)], + [R.propIs(Number, 'timeToLive'), R.prop('timeToLive')], + [R.T, R.always(DEFAULT_TTL)], +]); + +const expiryFromTtl = (ttl) => ttl + Math.floor(Date.now() / 1000); + +const extractExpiry = R.cond([ + [R.propIs(Number, 'expiry'), R.prop('expiry')], + [ + R.propIs(Number, 'timeToLive'), + ({ timeToLive }) => expiryFromTtl(timeToLive), + ], + [R.T, () => expiryFromTtl(DEFAULT_TTL)], +]); + +const getPropValueOrUndefinedIfIsSilent = (propName, data) => + R.ifElse( + R.propEq('silent', true), + R.always(undefined), + R.prop(propName) + )(data); + +const toJSONorUndefined = R.tryCatch(JSON.parse, R.always(undefined)); + +const alertLocArgsToJSON = R.evolve({ + alert: { + 'title-loc-args': toJSONorUndefined, + 'loc-args': toJSONorUndefined, + }, +}); + +const getDefaultAlert = (data) => ({ + title: data.title, + body: data.body, + 'title-loc-key': data.titleLocKey, + 'title-loc-args': data.titleLocArgs, + 'loc-key': data.locKey, + 'loc-args': data.locArgs || data.bodyLocArgs, + 'launch-image': data.launchImage, + action: data.action, +}); + +const alertOrDefault = (data) => + R.when( + R.propSatisfies(R.isNil, 'alert'), + R.assoc('alert', getDefaultAlert(data)) + ); + +const getParsedAlertOrDefault = (data) => + R.pipe(alertOrDefault(data), alertLocArgsToJSON)(data); + +const pathIsString = R.pathSatisfies(R.is(String)); + +const containsValidRecipients = R.either( + pathIsString(['recipients', 'to']), + pathIsString(['recipients', 'condition']) +); + +const propValueToSingletonArray = (propName) => + R.compose(R.of, R.prop(propName)); + +module.exports = { + ttlAndroid: extractTimeToLive, + expiryApns: extractExpiry, + getPropValueOrUndefinedIfIsSilent, + getParsedAlertOrDefault, + containsValidRecipients, + propValueToSingletonArray, +}; From 3e45ea54da9d95554d54e50b9b79940906aecb68 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 13:45:19 +0300 Subject: [PATCH 08/28] update build fcm message --- src/sendAPN.js | 34 +----------- src/sendFCM.js | 2 +- src/sendGCM.js | 56 +------------------- src/utils/fcmMessage.js | 57 ++++----------------- src/utils/tools.js | 111 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 123 insertions(+), 137 deletions(-) diff --git a/src/sendAPN.js b/src/sendAPN.js index 5ffa473..a7e99bd 100644 --- a/src/sendAPN.js +++ b/src/sendAPN.js @@ -1,11 +1,7 @@ const apn = require('@parse/node-apn'); const R = require('ramda'); const { APN_METHOD } = require('./constants'); -const { - expiryApns, - getPropValueOrUndefinedIfIsSilent, - getParsedAlertOrDefault, -} = require('./utils/tools'); +const { buildApnsMessage } = require('./utils/tools'); const getDeviceTokenOrSelf = R.ifElse( R.has('device'), @@ -30,33 +26,7 @@ class APN { } sendAPN(regIds, data) { - const message = new apn.Notification({ - retryLimit: data.retries || -1, - expiry: expiryApns(data), - priority: data.priority === 'normal' || data.silent === true ? 5 : 10, - encoding: data.encoding, - payload: data.custom || {}, - badge: getPropValueOrUndefinedIfIsSilent('badge', data), - sound: getPropValueOrUndefinedIfIsSilent('sound', data), - alert: getPropValueOrUndefinedIfIsSilent( - 'alert', - getParsedAlertOrDefault(data) - ), - topic: data.topic, - category: data.category || data.clickAction, - contentAvailable: data.contentAvailable, - mdm: data.mdm, - urlArgs: data.urlArgs, - truncateAtWordEnd: data.truncateAtWordEnd, - collapseId: data.collapseKey, - mutableContent: data.mutableContent || 0, - threadId: data.threadId, - pushType: data.pushType, - }); - - if (data.rawPayload) { - message.rawPayload = data.rawPayload; - } + const message = buildApnsMessage(data); if (!this.connection) { return Promise.reject( diff --git a/src/sendFCM.js b/src/sendFCM.js index 5a55de9..91d0e74 100644 --- a/src/sendFCM.js +++ b/src/sendFCM.js @@ -16,7 +16,7 @@ const getRecipientList = R.cond([ ]); const sendChunk = (firebaseApp, recipients, message) => { - const firebaseMessage = message.build(recipients); + const firebaseMessage = message.buildWithRecipients(recipients); console.log('[firebaseMessage]', JSON.stringify(firebaseMessage, null, 5)); diff --git a/src/sendGCM.js b/src/sendGCM.js index 495a4b9..8020824 100644 --- a/src/sendGCM.js +++ b/src/sendGCM.js @@ -2,9 +2,9 @@ const gcm = require('node-gcm'); const R = require('ramda'); const { GCM_METHOD } = require('./constants'); const { - ttlAndroid, containsValidRecipients, propValueToSingletonArray, + buildGsmMessage, } = require('./utils/tools'); const getRecipientList = R.cond([ @@ -73,61 +73,9 @@ const sendGCM = (regIds, data, settings) => { delete opts.id; const GCMSender = new gcm.Sender(id, opts); const promises = []; - const notification = data.fcm_notification || { - title: data.title, // Android, iOS (Watch) - body: data.body, // Android, iOS - icon: data.icon, // Android - image: data.image, // Android - picture: data.picture, // Android - style: data.style, // Android - sound: data.sound, // Android, iOS - badge: data.badge, // iOS - tag: data.tag, // Android - color: data.color, // Android - click_action: data.clickAction || data.category, // Android, iOS - body_loc_key: data.locKey, // Android, iOS - body_loc_args: data.locArgs, // Android, iOS - title_loc_key: data.titleLocKey, // Android, iOS - title_loc_args: data.titleLocArgs, // Android, iOS - android_channel_id: data.android_channel_id, // Android - notification_count: data.notificationCount || data.badge, // Android - }; - let custom; - if (typeof data.custom === 'string') { - custom = { - message: data.custom, - }; - } else if (typeof data.custom === 'object') { - custom = { ...data.custom }; - } else { - custom = { - data: data.custom, - }; - } + const message = buildGsmMessage(data, opts); - custom.title = custom.title || data.title; - custom.message = custom.message || data.body; - custom.sound = custom.sound || data.sound; - custom.icon = custom.icon || data.icon; - custom.msgcnt = custom.msgcnt || data.badge; - if (opts.phonegap === true && data.contentAvailable) { - custom['content-available'] = 1; - } - - const message = new gcm.Message({ - // See https://developers.google.com/cloud-messaging/http-server-ref#table5 - collapseKey: data.collapseKey, - priority: data.priority === 'normal' ? 'normal' : 'high', - contentAvailable: data.silent ? true : data.contentAvailable || false, - delayWhileIdle: data.delayWhileIdle || false, - timeToLive: ttlAndroid(data), - restrictedPackageName: data.restrictedPackageName, - dryRun: data.dryRun || false, - data: opts.phonegap === true ? Object.assign(custom, notification) : custom, // See https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#android-behaviour - notification: - opts.phonegap === true || data.silent === true ? undefined : notification, - }); let chunk = 0; /* allow to override device tokens with custom `to` or `condition` field: diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 587388b..23e4a77 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -1,11 +1,4 @@ -const { Notification: ApnsMessage } = require('@parse/node-apn'); -const { Message: GsmMessage } = require('node-gcm'); -const { - ttlAndroid, - expiryApns, - getPropValueOrUndefinedIfIsSilent, - getParsedAlertOrDefault, -} = require('./tools'); +const { buildGsmMessage, buildApnsMessage } = require('./tools'); class FcmMessage { constructor(params) { @@ -14,7 +7,7 @@ class FcmMessage { this.apns = params.apns; } - build(recipients) { + buildWithRecipients(recipients) { return { data: this.data, android: this.android, @@ -39,55 +32,24 @@ class FcmMessage { } static buildAndroidMessage(params) { - const notification = params.silent - ? undefined - : params.fcm_notification || undefined; - - const message = new GsmMessage({ - collapseKey: params.collapseKey, - priority: params.priority === 'normal' ? 'normal' : 'high', - timeToLive: ttlAndroid(params), - restrictedPackageName: params.restrictedPackageName, - notification, - }); + const message = buildGsmMessage(params); const androidMessage = message.toJson(); androidMessage.ttl = androidMessage.time_to_live * 1000; delete androidMessage.content_available; + delete androidMessage.mutable_content; delete androidMessage.delay_while_idle; delete androidMessage.time_to_live; + delete androidMessage.dryRun; + delete androidMessage.data; return androidMessage; } static buildApnsMessage(params) { - const message = new ApnsMessage({ - expiry: expiryApns(params), - priority: params.priority === 'normal' || params.silent ? 5 : 10, - encoding: params.encoding, - badge: getPropValueOrUndefinedIfIsSilent('badge', params), - sound: getPropValueOrUndefinedIfIsSilent('sound', params), - alert: getPropValueOrUndefinedIfIsSilent( - 'alert', - getParsedAlertOrDefault(params) - ), - topic: params.topic, - category: params.category || params.clickAction, - contentAvailable: params.contentAvailable, - mdm: params.mdm, - urlArgs: params.urlArgs, - truncateAtWordEnd: params.truncateAtWordEnd, - collapseId: params.collapseKey, - mutableContent: params.mutableContent || 0, - threadId: params.threadId, - pushType: params.pushType, - }); - - if (params.rawPayload) { - message.rawPayload = params.rawPayload; - } + const message = buildApnsMessage(params); const headers = message.headers() || {}; const payload = message.toJSON() || {}; @@ -95,12 +57,13 @@ class FcmMessage { return { headers: this.normalizeDataParams(headers), payload }; } - static build(params, recipients) { + static build(params) { const data = this.normalizeDataParams(params.custom); + const android = this.buildAndroidMessage(params); const apns = this.buildApnsMessage(params); - return new this({ data, android, apns }, recipients); + return new this({ data, android, apns }); } } diff --git a/src/utils/tools.js b/src/utils/tools.js index 3a1c3eb..1510876 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -1,4 +1,7 @@ const R = require('ramda'); +const { Notification: ApnsMessage } = require('@parse/node-apn'); +const { Message: GsmMessage } = require('node-gcm'); + const { DEFAULT_TTL, GCM_MAX_TTL } = require('../constants'); const ttlFromExpiry = R.compose( @@ -70,11 +73,113 @@ const containsValidRecipients = R.either( const propValueToSingletonArray = (propName) => R.compose(R.of, R.prop(propName)); +const buildGsmNotification = (data) => { + const notification = data.fcm_notification || { + title: data.title, + body: data.body, + icon: data.icon, + image: data.image, + picture: data.picture, + style: data.style, + sound: data.sound, + badge: data.badge, + tag: data.tag, + color: data.color, + click_action: data.clickAction || data.category, + body_loc_key: data.locKey, + body_loc_args: data.locArgs, + title_loc_key: data.titleLocKey, + title_loc_args: data.titleLocArgs, + android_channel_id: data.android_channel_id, + notification_count: data.notificationCount || data.badge, + }; + + return notification; +}; + +const buildGsmMessage = (data, options) => { + const notification = buildGsmNotification(data); + + let custom; + if (typeof data.custom === 'string') { + custom = { + message: data.custom, + }; + } else if (typeof data.custom === 'object') { + custom = { ...data.custom }; + } else { + custom = { + data: data.custom, + }; + } + + custom.title = custom.title || data.title; + custom.message = custom.message || data.body; + custom.sound = custom.sound || data.sound; + custom.icon = custom.icon || data.icon; + custom.msgcnt = custom.msgcnt || data.badge; + if (options.phonegap === true && data.contentAvailable) { + custom['content-available'] = 1; + } + + const message = new GsmMessage({ + collapseKey: data.collapseKey, + priority: data.priority === 'normal' ? 'normal' : 'high', + contentAvailable: data.silent ? true : data.contentAvailable || false, + delayWhileIdle: data.delayWhileIdle || false, + timeToLive: extractTimeToLive(data), + restrictedPackageName: data.restrictedPackageName, + dryRun: data.dryRun || false, + data: + options.phonegap === true ? Object.assign(custom, notification) : custom, + notification: + options.phonegap === true || data.silent === true + ? undefined + : notification, + }); + + return message; +}; + +const buildApnsMessage = (data) => { + const message = new ApnsMessage({ + retryLimit: data.retries || -1, + expiry: extractExpiry(data), + priority: data.priority === 'normal' || data.silent === true ? 5 : 10, + encoding: data.encoding, + payload: data.custom || {}, + badge: getPropValueOrUndefinedIfIsSilent('badge', data), + sound: getPropValueOrUndefinedIfIsSilent('sound', data), + alert: getPropValueOrUndefinedIfIsSilent( + 'alert', + getParsedAlertOrDefault(data) + ), + topic: data.topic, + category: data.category || data.clickAction, + contentAvailable: data.contentAvailable, + mdm: data.mdm, + urlArgs: data.urlArgs, + truncateAtWordEnd: data.truncateAtWordEnd, + collapseId: data.collapseKey, + mutableContent: data.mutableContent || 0, + threadId: data.threadId, + pushType: data.pushType, + }); + + if (data.rawPayload) { + message.rawPayload = data.rawPayload; + } + + return message; +}; + module.exports = { ttlAndroid: extractTimeToLive, - expiryApns: extractExpiry, - getPropValueOrUndefinedIfIsSilent, - getParsedAlertOrDefault, + apnsExpiry: extractExpiry, + containsValidRecipients, propValueToSingletonArray, + + buildApnsMessage, + buildGsmMessage, }; From 3e3a59c48fae21a79d62ab7538227a1c8e417150 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 13:45:26 +0300 Subject: [PATCH 09/28] 2.1.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec343b8..aa728d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-pushnotifications", - "version": "2.0.4-banshiAnton", + "version": "2.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-pushnotifications", - "version": "2.0.4-banshiAnton", + "version": "2.1.4", "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", diff --git a/package.json b/package.json index eaa5253..f6b4594 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-pushnotifications", "description": "A cross-platform push service for node.js", - "version": "2.0.4-banshiAnton", + "version": "2.1.4", "author": { "name": "AppFeel", "email": "info@appfeel.com" From ee475181d53ffae8908b71cee7233e4f9687bbbe Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 13:47:53 +0300 Subject: [PATCH 10/28] 2.1.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa728d8..f71c506 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-pushnotifications", - "version": "2.1.4", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-pushnotifications", - "version": "2.1.4", + "version": "2.1.0", "license": "MIT", "dependencies": { "@parse/node-apn": "5.1.3", diff --git a/package.json b/package.json index f6b4594..34cc325 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-pushnotifications", "description": "A cross-platform push service for node.js", - "version": "2.1.4", + "version": "2.1.0", "author": { "name": "AppFeel", "email": "info@appfeel.com" From 3b84a77839cdb53876b19a85047742dc6c80d696 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 14:46:13 +0300 Subject: [PATCH 11/28] fix build android fcm message --- src/utils/fcmMessage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 23e4a77..60ec4ad 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -32,7 +32,7 @@ class FcmMessage { } static buildAndroidMessage(params) { - const message = buildGsmMessage(params); + const message = buildGsmMessage(params, {}); const androidMessage = message.toJson(); @@ -42,7 +42,7 @@ class FcmMessage { delete androidMessage.mutable_content; delete androidMessage.delay_while_idle; delete androidMessage.time_to_live; - delete androidMessage.dryRun; + delete androidMessage.dry_run; delete androidMessage.data; return androidMessage; From 224ece5cf4b7c6a2b7a90f13d4386db3cd81aeee Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 15:11:01 +0300 Subject: [PATCH 12/28] fix fcm buildApnsMessage --- .husky/pre-commit | 2 +- node-pushnotifications-2.1.0.tgz | Bin 0 -> 47779 bytes src/utils/fcmMessage.js | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 node-pushnotifications-2.1.0.tgz diff --git a/.husky/pre-commit b/.husky/pre-commit index 35d6918..f1f927b 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/zsh . "$(dirname "$0")/_/husky.sh" npx pretty-quick --staged diff --git a/node-pushnotifications-2.1.0.tgz b/node-pushnotifications-2.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ef01dc3d51afefbd3967703fe7449315e7a9efeb GIT binary patch literal 47779 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
?a!Yk=hwrNPd3p5}X?-cfi)H+oT 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 literal 0 HcmV?d00001 diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 60ec4ad..92fef89 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -50,6 +50,7 @@ class FcmMessage { static buildApnsMessage(params) { const message = buildApnsMessage(params); + delete message.payload; const headers = message.headers() || {}; const payload = message.toJSON() || {}; From 0fbaa243772282e6a9adc9d6358854ec0f1eb1e0 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Mon, 18 Sep 2023 15:12:32 +0300 Subject: [PATCH 13/28] remove pack --- .husky/pre-commit | 2 +- node-pushnotifications-2.1.0.tgz | Bin 47779 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 node-pushnotifications-2.1.0.tgz diff --git a/.husky/pre-commit b/.husky/pre-commit index f1f927b..35d6918 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ -#!/bin/zsh +#!/bin/sh . "$(dirname "$0")/_/husky.sh" npx pretty-quick --staged diff --git a/node-pushnotifications-2.1.0.tgz b/node-pushnotifications-2.1.0.tgz deleted file mode 100644 index ef01dc3d51afefbd3967703fe7449315e7a9efeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47779 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
?a!Yk=hwrNPd3p5}X?-cfi)H+oT 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 From b12972856a64b27755725d145433a282902fb7d9 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 20 Sep 2023 15:12:52 +0300 Subject: [PATCH 14/28] update toJSONorUndefined --- src/utils/tools.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utils/tools.js b/src/utils/tools.js index 1510876..e0b5d64 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -34,7 +34,10 @@ const getPropValueOrUndefinedIfIsSilent = (propName, data) => R.prop(propName) )(data); -const toJSONorUndefined = R.tryCatch(JSON.parse, R.always(undefined)); +const toJSONorUndefined = R.when( + R.is.bind(null, String), + R.tryCatch(JSON.parse, R.always(undefined)) +); const alertLocArgsToJSON = R.evolve({ alert: { @@ -87,9 +90,9 @@ const buildGsmNotification = (data) => { color: data.color, click_action: data.clickAction || data.category, body_loc_key: data.locKey, - body_loc_args: data.locArgs, + body_loc_args: toJSONorUndefined(data.locArgs), title_loc_key: data.titleLocKey, - title_loc_args: data.titleLocArgs, + title_loc_args: toJSONorUndefined(data.titleLocArgs), android_channel_id: data.android_channel_id, notification_count: data.notificationCount || data.badge, }; From d331836f69ef7e164dab1c282e7f3ce18664f2d7 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 20 Sep 2023 18:46:56 +0300 Subject: [PATCH 15/28] add FCM method spec --- src/constants.js | 1 + src/sendFCM.js | 6 +- test/push-notifications/basic.js | 40 +++++++++++++ test/send/FCM-service-account-key.json | 13 ++++ test/send/sendFCM.js | 82 ++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 test/send/FCM-service-account-key.json create mode 100644 test/send/sendFCM.js diff --git a/src/constants.js b/src/constants.js index a220e49..9c95c9a 100644 --- a/src/constants.js +++ b/src/constants.js @@ -15,6 +15,7 @@ module.exports = { fcm: { appName: null, serviceAccountKey: null, + credential: null, }, apn: { // See options at https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown diff --git a/src/sendFCM.js b/src/sendFCM.js index 91d0e74..1ffe8d9 100644 --- a/src/sendFCM.js +++ b/src/sendFCM.js @@ -22,7 +22,7 @@ const sendChunk = (firebaseApp, recipients, message) => { return firebaseAdmin .messaging(firebaseApp) - .sendEachForMulticast(firebaseMessage, message.dryRun) + .sendEachForMulticast(firebaseMessage) .then((response, err) => { const recipientList = getRecipientList(recipients); if (err) { @@ -74,7 +74,9 @@ const sendChunk = (firebaseApp, recipients, message) => { const sendFCM = (regIds, data, settings) => { const appName = `${settings.fcm.appName}`; const opts = { - credential: firebaseAdmin.credential.cert(settings.fcm.serviceAccountKey), + credential: + settings.fcm.credential || + firebaseAdmin.credential.cert(settings.fcm.serviceAccountKey), }; const firebaseApp = firebaseAdmin.initializeApp(opts, appName); firebaseAdmin.INTERNAL.appStore.removeApp(appName); diff --git a/test/push-notifications/basic.js b/test/push-notifications/basic.js index 2a6c382..e5ac51e 100644 --- a/test/push-notifications/basic.js +++ b/test/push-notifications/basic.js @@ -1,3 +1,5 @@ +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ /* eslint-env mocha */ import path from 'path'; import chai from 'chai'; @@ -11,6 +13,7 @@ import { WNS_METHOD, ADM_METHOD, GCM_METHOD, + FCM_METHOD, APN_METHOD, } from '../../src/constants'; @@ -46,6 +49,12 @@ describe('push-notifications: instantiation and class properties', () => { cert: path.resolve('test/send/cert.pem'), key: path.resolve('test/send/key.pem'), }, + fcm: { + name: 'testAppName', + serviceAccountKey: require(path.resolve( + 'test/send/FCM-service-account-key.json' + )), + }, wns: { client_id: 'client id', client_secret: 'client secret', @@ -75,6 +84,7 @@ describe('push-notifications: instantiation and class properties', () => { it('should override the given options', () => { expect(pn.settings.apn).to.eql(settings.apn); expect(pn.settings.gcm).to.eql(settings.gcm); + expect(pn.settings.fcm).to.eql(settings.fcm); expect(pn.settings.adm).to.eql(settings.adm); expect(pn.settings.wns).to.eql(settings.wns); expect(pn.settings.web).to.eql(settings.web); @@ -235,6 +245,36 @@ describe('push-notifications: instantiation and class properties', () => { ).to.equal(GCM_METHOD); }); + it('Android / FCM', () => { + const settings = { + fcm: { + name: 'testAppName', + serviceAccountKey: require(path.resolve( + 'test/send/FCM-service-account-key.json' + )), + }, + useFCMMethodInsteadOfGCM: true, + }; + const pn = new PN(settings); + + expect(pn.getPushMethodByRegId(regIds.androidRegId).regId).to.equal( + regIds.androidRegId + ); + expect(pn.getPushMethodByRegId(regIds.androidRegId).pushMethod).to.equal( + FCM_METHOD + ); + + const updateSettings = { ...settings, isAlwaysUseFCM: true }; + pn.setOptions(updateSettings); + + expect(pn.getPushMethodByRegId(regIds.iOSRegIdLong).regId).to.equal( + regIds.iOSRegIdLong + ); + expect(pn.getPushMethodByRegId(regIds.iOSRegIdLong).pushMethod).to.equal( + FCM_METHOD + ); + }); + it('iOS / APN', () => { const pn = new PN(); expect(pn.getPushMethodByRegId(regIds.iOSRegId).regId).to.equal( diff --git a/test/send/FCM-service-account-key.json b/test/send/FCM-service-account-key.json new file mode 100644 index 0000000..a1db663 --- /dev/null +++ b/test/send/FCM-service-account-key.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "tjkfdgkj-sfggtht-sdf", + "private_key_id": "45674567rtgweryer65u45687ws", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgZQKBgH3+\nYwwi1GLdC7gliFyczOt2x/LC1PFhtk2K5h2CbMZVUYO0SvTjr/E5MWDra+eKLxdO\nPPcJgipS4lYeziJMCgRD9LiY4xeuUcdt1eR\n+xqoGPVTftTZiSyplhpdABcO9B7mrOxBTf6sX4tJAoGBANq/G9uy4rQ2JwcdX7Aq\nVykfyOrirjuA+oAH7m9bnnrvLFZavvz3tlWAxgmu+3zjXdD0pbLsn7mePBmLVAdh\n28I2dHj0BAZHd95Hnn+X1tJU26+v7SAtzQjQhskEbAXrPJ8rFyhL6RrswNrzJt0f\ntDV27cmQkzhvIDIvof4f97W+\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-p7o1d@jkfdgkj-sfggtht-sdf.iam.gserviceaccount.com", + "client_id": "5475678568568568568", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-p7o1d%40agr-sdfg-gafdsarg.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/test/send/sendFCM.js b/test/send/sendFCM.js new file mode 100644 index 0000000..8056c28 --- /dev/null +++ b/test/send/sendFCM.js @@ -0,0 +1,82 @@ +/* eslint-disable import/no-unresolved */ +/* eslint-env mocha */ +import { expect } from 'chai'; +import sinon from 'sinon'; +import { Messaging as fbMessaging } from 'firebase-admin/messaging'; +import PN from '../../src'; +import { testPushSuccess } from '../util'; + +const method = 'fcm'; +const regIds = [ + 'APA91bFQCD9Ndd8uVggMhj1usfeWsKIfGyBUWMprpZLGciWrMjS-77bIY24IMQNeEHzjidCcddnDxqYo-UEV03xw6ySmtIgQyzTqhSxhPGAi1maf6KDMAQGuUWc6L5Khze8YK9YrL9I_WD1gl49P3f_9hr08ZAS5Tw', +]; +const message = { + title: 'title', + body: 'body', + sound: 'mySound.aiff', + custom: { + sender: 'banshi-test', + }, +}; +const fcmOpts = { + fcm: { + name: 'testAppName', + credential: { getAccessToken: () => Promise.resolve({}) }, + }, + useFCMMethodInsteadOfGCM: true, +}; +const pn = new PN(fcmOpts); + +const testSuccess = testPushSuccess(method, regIds); + +let sendMethod; + +function sendOkMethod() { + return sinon.stub( + fbMessaging.prototype, + 'sendEachForMulticast', + function sendFCM(firebaseMessage) { + const { custom, ...messageData } = message; + + expect(firebaseMessage.tokens).to.deep.equal(regIds); + + expect(firebaseMessage.android.priority).to.equal('high'); + expect(firebaseMessage.android.notification).to.deep.include(messageData); + + expect(firebaseMessage.apns.payload.aps.sound).to.equal( + messageData.sound + ); + + expect(firebaseMessage.apns.payload.aps.alert).to.deep.include({ + title: messageData.title, + body: messageData.body, + }); + + expect(firebaseMessage.data).to.deep.equal(custom); + + return Promise.resolve({ + successCount: 1, + failureCount: 0, + responses: [{ error: null }], + }); + } + ); +} + +describe('push-notifications-fcm', () => { + describe('send push notifications successfully', () => { + before(() => { + sendMethod = sendOkMethod(); + }); + + after(() => { + sendMethod.restore(); + }); + + it('all responses should be successful', (done) => { + pn.send(regIds, message) + .then((results) => testSuccess(null, results, done)) + .catch(done); + }); + }); +}); From a1f2b049c89f06a01f1c21a3d4d5cdec75310a44 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 4 Oct 2023 16:02:20 +0300 Subject: [PATCH 16/28] add fcm providersExclude option --- src/utils/fcmMessage.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 92fef89..6a52c1a 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -59,12 +59,22 @@ class FcmMessage { } static build(params) { + const providersExclude = params.providersExclude || []; + delete params.providersExclude; + const data = this.normalizeDataParams(params.custom); - const android = this.buildAndroidMessage(params); - const apns = this.buildApnsMessage(params); + const createParams = { data }; + + if (!providersExclude.includes('apns')) { + createParams.apns = this.buildApnsMessage(params); + } + + if (!providersExclude.includes('android')) { + createParams.android = this.buildAndroidMessage(params); + } - return new this({ data, android, apns }); + return new this(createParams); } } From f3730e1792f45d49155a3ed212ce2a9db6864d98 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 10 Jan 2024 14:58:15 +0200 Subject: [PATCH 17/28] update README.md --- README.md | 197 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 28ad128..9d16e2f 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,11 @@ const settings = { production: false // true for APN production environment, false for APN sandbox environment, ... }, + fcm: { + appName: 'localFcmAppName', + serviceAccountKey: require('../firebase-project-service-account-key.json') // firebase service-account-file.json, + credential: null // 'firebase-admin' Credential interface + }, adm: { client_id: null, client_secret: null, @@ -86,13 +91,16 @@ const settings = { contentEncoding: 'aes128gcm', headers: {} }, - isAlwaysUseFCM: false, // true all messages will be sent through node-gcm (which actually uses FCM) + isAlwaysUseFCM: false, // true all messages will be sent through node-gcm (which actually uses FCM (deprecated fcm api)) + useFCMMethodInsteadOfGCM: false // true all message that should be sent through node-gcm, will be sent through 'firebase-admin' lib }; + const push = new PushNotifications(settings); ``` - GCM options: see [node-gcm](https://github.com/ToothlessGear/node-gcm#custom-gcm-request-options) - APN options: see [node-apn](https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown) +- FCM options: see [firebase-admin](https://firebase.google.com/docs/admin/setup) (read 'FCM' section below!) - ADM options: see [node-adm](https://github.com/umano/node-adm) - WNS options: see [wns](https://github.com/tjanczuk/wns) - Web-push options: see [web-push](https://github.com/web-push-libs/web-push) @@ -308,57 +316,61 @@ push.send(registrationIds, data) The following parameters are used to create a GCM message. See https://developers.google.com/cloud-messaging/http-server-ref#table5 for more info: ```js - // Set default custom data from data - let custom; - if (typeof data.custom === 'string') { - custom = { - message: data.custom, - }; - } else if (typeof data.custom === 'object') { - custom = Object.assign({}, data.custom); - } else { - custom = { - data: data.custom, - }; - } +// Set default custom data from data +let custom; +if (typeof data.custom === 'string') { + custom = { + message: data.custom, + }; +} else if (typeof data.custom === 'object') { + custom = Object.assign({}, data.custom); +} else { + custom = { + data: data.custom, + }; +} - custom.title = custom.title || data.title; - custom.message = custom.message || data.body; - custom.sound = custom.sound || data.sound; - custom.icon = custom.icon || data.icon; - custom.msgcnt = custom.msgcnt || data.badge; - if (opts.phonegap === true && data.contentAvailable) { - custom['content-available'] = 1; - } +custom.title = custom.title || data.title; +custom.message = custom.message || data.body; +custom.sound = custom.sound || data.sound; +custom.icon = custom.icon || data.icon; +custom.msgcnt = custom.msgcnt || data.badge; +if (opts.phonegap === true && data.contentAvailable) { + custom['content-available'] = 1; +} - const message = new gcm.Message({ // See https://developers.google.com/cloud-messaging/http-server-ref#table5 - collapseKey: data.collapseKey, - priority: data.priority === 'normal' ? data.priority : 'high', - contentAvailable: data.contentAvailable || false, - delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored) - timeToLive: data.expiry - Math.floor(Date.now() / 1000) || data.timeToLive || 28 * 86400, - restrictedPackageName: data.restrictedPackageName, - dryRun: data.dryRun || false, - data: data.custom, - notification: { - title: data.title, // Android, iOS (Watch) - body: data.body, // Android, iOS - icon: data.icon, // Android - image: data.image, // Android - style: data.style, // Android - picture: data.picture, // Android - sound: data.sound, // Android, iOS - badge: data.badge, // iOS - tag: data.tag, // Android - color: data.color, // Android - click_action: data.clickAction || data.category, // Android, iOS - body_loc_key: data.locKey, // Android, iOS - body_loc_args: data.locArgs, // Android, iOS - title_loc_key: data.titleLocKey, // Android, iOS - title_loc_args: data.titleLocArgs, // Android, iOS - android_channel_id: data.android_channel_id, // Android - }, - } +const message = new gcm.Message({ + // See https://developers.google.com/cloud-messaging/http-server-ref#table5 + collapseKey: data.collapseKey, + priority: data.priority === 'normal' ? data.priority : 'high', + contentAvailable: data.contentAvailable || false, + delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored) + timeToLive: + data.expiry - Math.floor(Date.now() / 1000) || + data.timeToLive || + 28 * 86400, + restrictedPackageName: data.restrictedPackageName, + dryRun: data.dryRun || false, + data: data.custom, + notification: { + title: data.title, // Android, iOS (Watch) + body: data.body, // Android, iOS + icon: data.icon, // Android + image: data.image, // Android + style: data.style, // Android + picture: data.picture, // Android + sound: data.sound, // Android, iOS + badge: data.badge, // iOS + tag: data.tag, // Android + color: data.color, // Android + click_action: data.clickAction || data.category, // Android, iOS + body_loc_key: data.locKey, // Android, iOS + body_loc_args: data.locArgs, // Android, iOS + title_loc_key: data.titleLocKey, // Android, iOS + title_loc_args: data.titleLocArgs, // Android, iOS + android_channel_id: data.android_channel_id, // Android + }, +}); ``` _data is the parameter in `push.send(registrationIds, data)`_ @@ -519,6 +531,91 @@ const silentPushData = { } ``` +## FCM + +The following parameters are used to create an FCM message (Android/APN): +[node-gcm](https://github.com/ToothlessGear/node-gcm) lib for `GCM` method use old firebase api (will be [deprecated ](https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=en&authuser=0)) + +Settings: - `settings.fcm.appName` [firebase app name](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.app#appname) (required) - `settings.fcm.serviceAccountKey` [firebase service account file](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) use downloaded `service-account-file.json` (one of `serviceAccountKey` of `credential` required) - `settings.fcm.credential` [firebase credential](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.credential) (one of `serviceAccountKey` of `credential` required) + +```js +const tokens = [ + 'e..Gwso:APA91.......7r910HljzGUVS_f...kbyIFk2sK6......D2s6XZWn2E21x', +]; + +const notifications = { + collapseKey: Math.random().toString().replace('0.', ''), + priority: 'high', + sound: 'default', + title: 'Title 1', + body: 'Body 2', + // titleLocKey: 'GREETING', + // titleLocArgs: ['Smith', 'M'], + // fcm_notification: { + // title: 'Title 1', + // body: 'Body 2', + // sound: 'default', + // default_vibrate_timings: true, + // }, + // alert: { + // title: 'Title 2', + // body: 'Body 2' + // }, + custom: { + frined_id: 54657, + list_id: 'N7jSif1INyZkA7r910HljzGUVS', + }, +}; + +pushNotifications.send(tokens, notifications, (error, result) => { + if (error) { + console.log('[error]', error); + throw error; + } else { + console.log('[result]', result, result.at(0)); + } +}); +``` + +Fcm object that will be sent to provider ([Fcm message format](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?authuser=0#Message)) : + +```json +{ + "data": { + "frined_id": "54657", + "list_id": "N7jSif1INyZkA7r910HljzGUVS" + }, + "android": { + "collapse_key": "5658586678087056", + "priority": "high", + "notification": { + "title": "Title 1", + "body": "Body 2", + "sound": "default" + }, + "ttl": 2419200000 + }, + "apns": { + "headers": { + "apns-expiration": "1697456586", + "apns-collapse-id": "5658586678087056" + }, + "payload": { + "aps": { + "sound": "default", + "alert": { + "title": "Title 1", + "body": "Body 2" + } + } + } + }, + "tokens": [ + "e..Gwso:APA91.......7r910HljzGUVS_f...kbyIFk2sK6......D2s6XZWn2E21x" + ] +} +``` + ## WNS The following fields are used to create a WNS message: From 8d8fff3e560b87090e0aeb12e5ea133a415ebfae Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 10 Jan 2024 14:59:57 +0200 Subject: [PATCH 18/28] update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d16e2f..1629176 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ A node.js module for interfacing with Apple Push Notification, Google Cloud Mess - [Usage](#usage) - [GCM](#gcm) - [APN](#apn) +- [FCM](#fcm) - [WNS](#wns) - [ADM](#adm) - [Web-Push](#web-push) @@ -100,7 +101,7 @@ const push = new PushNotifications(settings); - GCM options: see [node-gcm](https://github.com/ToothlessGear/node-gcm#custom-gcm-request-options) - APN options: see [node-apn](https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown) -- FCM options: see [firebase-admin](https://firebase.google.com/docs/admin/setup) (read 'FCM' section below!) +- FCM options: see [firebase-admin](https://firebase.google.com/docs/admin/setup) (read #fcm section below!) - ADM options: see [node-adm](https://github.com/umano/node-adm) - WNS options: see [wns](https://github.com/tjanczuk/wns) - Web-push options: see [web-push](https://github.com/web-push-libs/web-push) From cfe17c8cea6766639dd247d828614347da412393 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 10 Jan 2024 15:03:17 +0200 Subject: [PATCH 19/28] update README.md --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1629176..afb3a69 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ const settings = { }, fcm: { appName: 'localFcmAppName', - serviceAccountKey: require('../firebase-project-service-account-key.json') // firebase service-account-file.json, + serviceAccountKey: require('../firebase-project-service-account-key.json'), // firebase service-account-file.json, credential: null // 'firebase-admin' Credential interface }, adm: { @@ -101,7 +101,7 @@ const push = new PushNotifications(settings); - GCM options: see [node-gcm](https://github.com/ToothlessGear/node-gcm#custom-gcm-request-options) - APN options: see [node-apn](https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown) -- FCM options: see [firebase-admin](https://firebase.google.com/docs/admin/setup) (read #fcm section below!) +- FCM options: see [firebase-admin](https://firebase.google.com/docs/admin/setup) (read [FCM](#fcm) section below!) - ADM options: see [node-adm](https://github.com/umano/node-adm) - WNS options: see [wns](https://github.com/tjanczuk/wns) - Web-push options: see [web-push](https://github.com/web-push-libs/web-push) @@ -537,7 +537,13 @@ const silentPushData = { The following parameters are used to create an FCM message (Android/APN): [node-gcm](https://github.com/ToothlessGear/node-gcm) lib for `GCM` method use old firebase api (will be [deprecated ](https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=en&authuser=0)) -Settings: - `settings.fcm.appName` [firebase app name](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.app#appname) (required) - `settings.fcm.serviceAccountKey` [firebase service account file](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) use downloaded `service-account-file.json` (one of `serviceAccountKey` of `credential` required) - `settings.fcm.credential` [firebase credential](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.credential) (one of `serviceAccountKey` of `credential` required) +Settings: + +- `settings.fcm.appName` [firebase app name](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.app#appname) (required) + +- `settings.fcm.serviceAccountKey` [firebase service account file](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) use downloaded `service-account-file.json` (one of `serviceAccountKey` of `credential` required) + +- `settings.fcm.credential` [firebase credential](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.credential) (one of `serviceAccountKey` of `credential` required) ```js const tokens = [ From d2b0134025af8c3c2121d0b0e3fb3d5612914016 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 10 Jan 2024 15:05:51 +0200 Subject: [PATCH 20/28] update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index afb3a69..d0aa226 100644 --- a/README.md +++ b/README.md @@ -540,10 +540,10 @@ The following parameters are used to create an FCM message (Android/APN): Settings: - `settings.fcm.appName` [firebase app name](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.app#appname) (required) +- `settings.fcm.serviceAccountKey` [firebase service account file](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) use downloaded 'service-account-file.json' +- `settings.fcm.credential` [firebase credential](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.credential) -- `settings.fcm.serviceAccountKey` [firebase service account file](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) use downloaded `service-account-file.json` (one of `serviceAccountKey` of `credential` required) - -- `settings.fcm.credential` [firebase credential](https://firebase.google.com/docs/reference/admin/node/firebase-admin.app.credential) (one of `serviceAccountKey` of `credential` required) +Note: one of `serviceAccountKey`, `credential` fcm options is required ```js const tokens = [ From ba9bce1fad8813a5e7f4b76aee95a76107e885fc Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Wed, 10 Jan 2024 17:15:01 +0200 Subject: [PATCH 21/28] add rawPayload and fcm_notification to README.md --- README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d0aa226..284996e 100644 --- a/README.md +++ b/README.md @@ -394,9 +394,9 @@ _data is the parameter in `push.send(registrationIds, data)`_ title: 'title', body: 'body', icon: undefined, - image: undefined, - style: undefined, - picture: undefined, + image: undefined, + style: undefined, + picture: undefined, sound: 'mySound.aiff', badge: undefined, tag: undefined, @@ -406,7 +406,7 @@ _data is the parameter in `push.send(registrationIds, data)`_ body_loc_args: undefined, title_loc_key: undefined, title_loc_args: undefined, - android_channel_id: undefined + android_channel_id: undefined } ``` @@ -499,7 +499,8 @@ The following parameters are used to create an APN message: collapseId: data.collapseKey, mutableContent: data.mutableContent || 0, threadId: data.threadId, - pushType: data.pushType + pushType: data.pushType, + rawPayload: data.rawPayload } ``` @@ -509,6 +510,7 @@ _data is the parameter in `push.send(registrationIds, data)`_ - **Please note** that `topic` is required ([see node-apn docs](https://github.com/node-apn/node-apn/blob/master/doc/notification.markdown#notificationtopic)). When using token-based authentication, specify the bundle ID of the app. When using certificate-based authentication, the topic is usually your app's bundle ID. More details can be found under https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns +- `rawPayload` (hidden 'node-apn' lib notification param) [source code](https://github.com/node-apn/node-apn/blob/master/lib/notification/index.js#L99) this param will replace all payload ### Silent push notifications @@ -584,6 +586,12 @@ pushNotifications.send(tokens, notifications, (error, result) => { }); ``` +`fcm_notification` - object that will be passed to + +```js + new gcm.Message({ ..., notification: data.fcm_notification }) +``` + Fcm object that will be sent to provider ([Fcm message format](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?authuser=0#Message)) : ```json From 75bc97b33a2706b965b58d31d9c97da210cf44fe Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Thu, 11 Jan 2024 15:05:04 +0200 Subject: [PATCH 22/28] rename: buildGsmMessage -> buildGcmMessage --- src/sendGCM.js | 4 ++-- src/utils/fcmMessage.js | 4 ++-- src/utils/tools.js | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sendGCM.js b/src/sendGCM.js index 8020824..f3465ff 100644 --- a/src/sendGCM.js +++ b/src/sendGCM.js @@ -4,7 +4,7 @@ const { GCM_METHOD } = require('./constants'); const { containsValidRecipients, propValueToSingletonArray, - buildGsmMessage, + buildGcmMessage, } = require('./utils/tools'); const getRecipientList = R.cond([ @@ -74,7 +74,7 @@ const sendGCM = (regIds, data, settings) => { const GCMSender = new gcm.Sender(id, opts); const promises = []; - const message = buildGsmMessage(data, opts); + const message = buildGcmMessage(data, opts); let chunk = 0; diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 6a52c1a..217f95d 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -1,4 +1,4 @@ -const { buildGsmMessage, buildApnsMessage } = require('./tools'); +const { buildGcmMessage, buildApnsMessage } = require('./tools'); class FcmMessage { constructor(params) { @@ -32,7 +32,7 @@ class FcmMessage { } static buildAndroidMessage(params) { - const message = buildGsmMessage(params, {}); + const message = buildGcmMessage(params, {}); const androidMessage = message.toJson(); diff --git a/src/utils/tools.js b/src/utils/tools.js index e0b5d64..bfcdbaf 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -1,6 +1,6 @@ const R = require('ramda'); const { Notification: ApnsMessage } = require('@parse/node-apn'); -const { Message: GsmMessage } = require('node-gcm'); +const { Message: GcmMessage } = require('node-gcm'); const { DEFAULT_TTL, GCM_MAX_TTL } = require('../constants'); @@ -76,7 +76,7 @@ const containsValidRecipients = R.either( const propValueToSingletonArray = (propName) => R.compose(R.of, R.prop(propName)); -const buildGsmNotification = (data) => { +const buildGcmNotification = (data) => { const notification = data.fcm_notification || { title: data.title, body: data.body, @@ -100,8 +100,8 @@ const buildGsmNotification = (data) => { return notification; }; -const buildGsmMessage = (data, options) => { - const notification = buildGsmNotification(data); +const buildGcmMessage = (data, options) => { + const notification = buildGcmNotification(data); let custom; if (typeof data.custom === 'string') { @@ -125,7 +125,7 @@ const buildGsmMessage = (data, options) => { custom['content-available'] = 1; } - const message = new GsmMessage({ + const message = new GcmMessage({ collapseKey: data.collapseKey, priority: data.priority === 'normal' ? 'normal' : 'high', contentAvailable: data.silent ? true : data.contentAvailable || false, @@ -184,5 +184,5 @@ module.exports = { propValueToSingletonArray, buildApnsMessage, - buildGsmMessage, + buildGcmMessage, }; From adebd638b437bc99d64d31ccad3d0a3da74553bb Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:06:00 +0200 Subject: [PATCH 23/28] add isLegacyGCM setting --- README.md | 4 ++-- src/constants.js | 2 +- src/push-notifications.js | 34 +++++++++++++++++-------------- test/push-notifications/basic.js | 11 +++++++--- test/push-notifications/regIds.js | 3 ++- test/send/sendADM.js | 1 + test/send/sendAPN.js | 1 + test/send/sendFCM.js | 2 +- test/send/sendGCM.js | 2 ++ test/send/sendWNS-accessToken.js | 1 + test/send/sendWNS.js | 1 + 11 files changed, 39 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 284996e..06ff68b 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,8 @@ const settings = { contentEncoding: 'aes128gcm', headers: {} }, - isAlwaysUseFCM: false, // true all messages will be sent through node-gcm (which actually uses FCM (deprecated fcm api)) - useFCMMethodInsteadOfGCM: false // true all message that should be sent through node-gcm, will be sent through 'firebase-admin' lib + isAlwaysUseFCM: false, // true all messages will be sent through gcm/fcm api + isLegacyGCM: false // if true gcm messages will be sent through node-gcm (deprecated api), if false gcm messages will be sent through 'firebase-admin' lib }; const push = new PushNotifications(settings); diff --git a/src/constants.js b/src/constants.js index 9c95c9a..8ad39da 100644 --- a/src/constants.js +++ b/src/constants.js @@ -71,6 +71,6 @@ module.exports = { // contentEncoding: '< Encoding type, e.g.: aesgcm or aes128gcm >' }, isAlwaysUseFCM: false, - useFCMMethodInsteadOfGCM: false, + isLegacyGCM: false, }, }; diff --git a/src/push-notifications.js b/src/push-notifications.js index 952b5c9..d097702 100644 --- a/src/push-notifications.js +++ b/src/push-notifications.js @@ -21,6 +21,9 @@ import { class PN { constructor(options) { this.setOptions(options); + this.useFcmOrGcmMethod = this.settings.isLegacyGCM + ? GCM_METHOD + : FCM_METHOD; } setOptions(opts) { @@ -51,17 +54,16 @@ class PN { if (typeof regId === 'object' && regId.id && regId.type) { return { regId: regId.id, - pushMethod: this.settings.isAlwaysUseFCM ? GCM_METHOD : regId.type, + pushMethod: this.settings.isAlwaysUseFCM + ? this.useFcmOrGcmMethod + : regId.type, }; } // TODO: deprecated, remove of all cases below in v3.0 // and review test cases if (this.settings.isAlwaysUseFCM) { - const pushMethod = this.settings.useFCMMethodInsteadOfGCM - ? FCM_METHOD - : GCM_METHOD; - return { regId, pushMethod }; + return { regId, pushMethod: this.useFcmOrGcmMethod }; } if (regId.substring(0, 4) === 'http') { @@ -80,10 +82,7 @@ class PN { } if (regId.length > 64) { - const pushMethod = this.settings.useFCMMethodInsteadOfGCM - ? FCM_METHOD - : GCM_METHOD; - return { regId, pushMethod }; + return { regId, pushMethod: this.useFcmOrGcmMethod }; } return { regId, pushMethod: UNKNOWN_METHOD }; @@ -91,6 +90,7 @@ class PN { send(_regIds, data, callback) { const promises = []; + const regIdsGCM = []; const regIdsFCM = []; const regIdsAPN = []; const regIdsWNS = []; @@ -105,7 +105,9 @@ class PN { if (pushMethod === WEB_METHOD) { regIdsWebPush.push(regId); - } else if (pushMethod === GCM_METHOD || pushMethod === FCM_METHOD) { + } else if (pushMethod === GCM_METHOD) { + regIdsGCM.push(regId); + } else if (pushMethod === FCM_METHOD) { regIdsFCM.push(regId); } else if (pushMethod === WNS_METHOD) { regIdsWNS.push(regId); @@ -119,12 +121,14 @@ class PN { }); try { - // Android GCM / FCM (Android/iOS) + // Android GCM / FCM (Android/iOS) Legacy + if (regIdsGCM.length > 0) { + promises.push(this.sendWith(sendGCM, regIdsGCM, data)); + } + + // FCM (Android/iOS) if (regIdsFCM.length > 0) { - const method = this.settings.useFCMMethodInsteadOfGCM - ? sendFCM - : sendGCM; - promises.push(this.sendWith(method, regIdsFCM, data)); + promises.push(this.sendWith(sendFCM, regIdsFCM, data)); } // iOS APN diff --git a/test/push-notifications/basic.js b/test/push-notifications/basic.js index e5ac51e..517d1cb 100644 --- a/test/push-notifications/basic.js +++ b/test/push-notifications/basic.js @@ -27,6 +27,7 @@ describe('push-notifications: instantiation and class properties', () => { const pn = new PN(); expect(pn).to.have.property('send'); expect(pn.settings).to.have.property('gcm'); + expect(pn.settings).to.have.property('fcm'); expect(pn.settings).to.have.property('apn'); expect(pn.settings).to.have.property('adm'); expect(pn.settings).to.have.property('wns'); @@ -197,7 +198,7 @@ describe('push-notifications: instantiation and class properties', () => { }; it('Android / GCM', () => { - let pn = new PN(); + let pn = new PN({ isLegacyGCM: true }); expect(pn.getPushMethodByRegId(regIds.androidRegId).regId).to.equal( regIds.androidRegId ); @@ -221,6 +222,7 @@ describe('push-notifications: instantiation and class properties', () => { const settings = { isAlwaysUseFCM: true, + isLegacyGCM: true, }; pn = new PN(settings); expect(pn.getPushMethodByRegId(regIds.unknownRegId).regId).to.equal( @@ -253,7 +255,7 @@ describe('push-notifications: instantiation and class properties', () => { 'test/send/FCM-service-account-key.json' )), }, - useFCMMethodInsteadOfGCM: true, + isLegacyGCM: false, }; const pn = new PN(settings); @@ -264,7 +266,10 @@ describe('push-notifications: instantiation and class properties', () => { FCM_METHOD ); - const updateSettings = { ...settings, isAlwaysUseFCM: true }; + const updateSettings = { + ...settings, + isAlwaysUseFCM: true, + }; pn.setOptions(updateSettings); expect(pn.getPushMethodByRegId(regIds.iOSRegIdLong).regId).to.equal( diff --git a/test/push-notifications/regIds.js b/test/push-notifications/regIds.js index 589cb08..556d0a1 100644 --- a/test/push-notifications/regIds.js +++ b/test/push-notifications/regIds.js @@ -35,7 +35,7 @@ describe('push-notifications: call with registration ids for android, ios, windo let sendWith; before(() => { - pn = new PN(); + pn = new PN({ isLegacyGCM: true }); const sendApnFunctionName = pn.apn.sendAPN.bind(pn.apn).name; sendWith = sinon.stub( @@ -48,6 +48,7 @@ describe('push-notifications: call with registration ids for android, ios, windo failure: 0, message: _regIds.map((regId) => ({ regId })), }; + switch (regIds.indexOf(_regIds[0])) { case 0: case 1: diff --git a/test/send/sendADM.js b/test/send/sendADM.js index c39939b..f05ac31 100644 --- a/test/send/sendADM.js +++ b/test/send/sendADM.js @@ -168,6 +168,7 @@ describe('push-notifications-adm', () => { describe('send push notifications using FCM', () => { const pnGCM = new PN({ isAlwaysUseFCM: true, + isLegacyGCM: true, }); before(() => { sendMethod = sendOkMethodGCM(regIds, data); diff --git a/test/send/sendAPN.js b/test/send/sendAPN.js index 83dba73..7df440b 100644 --- a/test/send/sendAPN.js +++ b/test/send/sendAPN.js @@ -760,6 +760,7 @@ describe('push-notifications-apn', () => { describe('send push notifications successfully using FCM', () => { const pnGCM = new PN({ isAlwaysUseFCM: true, + isLegacyGCM: true, }); before(() => { sendMethod = sendOkMethodGCM(regIds, data); diff --git a/test/send/sendFCM.js b/test/send/sendFCM.js index 8056c28..35ae46b 100644 --- a/test/send/sendFCM.js +++ b/test/send/sendFCM.js @@ -23,7 +23,7 @@ const fcmOpts = { name: 'testAppName', credential: { getAccessToken: () => Promise.resolve({}) }, }, - useFCMMethodInsteadOfGCM: true, + isLegacyGCM: false, }; const pn = new PN(fcmOpts); diff --git a/test/send/sendGCM.js b/test/send/sendGCM.js index 106302f..da732a6 100644 --- a/test/send/sendGCM.js +++ b/test/send/sendGCM.js @@ -36,6 +36,7 @@ const gcmOpts = { gcm: { id: 'your id', }, + isLegacyGCM: true, }; const notificationOptions = { title: 'Notification Title', @@ -914,6 +915,7 @@ describe('push-notifications-gcm', () => { gcm: { phonegap: true, }, + isLegacyGCM: true, }); before(() => { diff --git a/test/send/sendWNS-accessToken.js b/test/send/sendWNS-accessToken.js index a9c0d44..19acea3 100644 --- a/test/send/sendWNS-accessToken.js +++ b/test/send/sendWNS-accessToken.js @@ -227,6 +227,7 @@ describe('push-notifications-wns-access-token', () => { describe('send push notifications successfully using FCM', () => { const pnGCM = new PN({ isAlwaysUseFCM: true, + isLegacyGCM: true, }); before(() => { sendMethod = sendOkMethodGCM(regIds, data); diff --git a/test/send/sendWNS.js b/test/send/sendWNS.js index 6dfe5b2..6ab4a46 100644 --- a/test/send/sendWNS.js +++ b/test/send/sendWNS.js @@ -264,6 +264,7 @@ describe('push-notifications-wns', () => { describe('send push notifications successfully using FCM', () => { const pnGCM = new PN({ isAlwaysUseFCM: true, + isLegacyGCM: true, }); before(() => { sendMethod = sendOkMethodGCM(regIds, data); From 0a2787c2aae5aa17c91dabbf651a7f0efa5bb372 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:06:22 +0200 Subject: [PATCH 24/28] remove .bind from toJSONorUndefined func --- src/utils/tools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/tools.js b/src/utils/tools.js index bfcdbaf..ff2fc93 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -35,7 +35,7 @@ const getPropValueOrUndefinedIfIsSilent = (propName, data) => )(data); const toJSONorUndefined = R.when( - R.is.bind(null, String), + R.is(String), R.tryCatch(JSON.parse, R.always(undefined)) ); From 89a2c09a5ee889f35fa17e7578c9249e2035f74c Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:23:47 +0200 Subject: [PATCH 25/28] back 'no-param-reassign' eslint rule --- .eslintrc | 3 --- src/sendFCM.js | 5 +++-- src/utils/fcmMessage.js | 13 +++++++------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.eslintrc b/.eslintrc index 29413ac..3f03e1f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,8 +2,5 @@ "extends": ["airbnb-base", "plugin:prettier/recommended"], "env": { "node": true - }, - "rules": { - "no-param-reassign": "off" } } diff --git a/src/sendFCM.js b/src/sendFCM.js index 1ffe8d9..2818d96 100644 --- a/src/sendFCM.js +++ b/src/sendFCM.js @@ -78,6 +78,7 @@ const sendFCM = (regIds, data, settings) => { settings.fcm.credential || firebaseAdmin.credential.cert(settings.fcm.serviceAccountKey), }; + const firebaseApp = firebaseAdmin.initializeApp(opts, appName); firebaseAdmin.INTERNAL.appStore.removeApp(appName); @@ -89,9 +90,9 @@ const sendFCM = (regIds, data, settings) => { if (containsValidRecipients(data)) { if (data.recipients.to) { - data.recipients.topic = data.recipients.to; - delete data.recipients.to; + Object.assign(data.recipients, { topic: data.recipients.to }); } + promises.push(sendChunk(firebaseApp, data.recipients, fcmMessage)); } else { do { diff --git a/src/utils/fcmMessage.js b/src/utils/fcmMessage.js index 217f95d..5ce56d3 100644 --- a/src/utils/fcmMessage.js +++ b/src/utils/fcmMessage.js @@ -24,9 +24,11 @@ class FcmMessage { return normalized; } - normalized[key] = + const stringifyValue = typeof value === 'string' ? value : JSON.stringify(value); + Object.assign(normalized, { [key]: stringifyValue }); + return normalized; }, {}); } @@ -59,19 +61,18 @@ class FcmMessage { } static build(params) { - const providersExclude = params.providersExclude || []; - delete params.providersExclude; + const { providersExclude = [], ...fcmMessageParams } = params; - const data = this.normalizeDataParams(params.custom); + const data = this.normalizeDataParams(fcmMessageParams.custom); const createParams = { data }; if (!providersExclude.includes('apns')) { - createParams.apns = this.buildApnsMessage(params); + createParams.apns = this.buildApnsMessage(fcmMessageParams); } if (!providersExclude.includes('android')) { - createParams.android = this.buildAndroidMessage(params); + createParams.android = this.buildAndroidMessage(fcmMessageParams); } return new this(createParams); From 9550623c795fb7248b3c5dce8db90dbb8fb48111 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:26:46 +0200 Subject: [PATCH 26/28] back formatting / whitespace README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 06ff68b..aa9d2b6 100644 --- a/README.md +++ b/README.md @@ -394,9 +394,9 @@ _data is the parameter in `push.send(registrationIds, data)`_ title: 'title', body: 'body', icon: undefined, - image: undefined, - style: undefined, - picture: undefined, + image: undefined, + style: undefined, + picture: undefined, sound: 'mySound.aiff', badge: undefined, tag: undefined, @@ -406,7 +406,7 @@ _data is the parameter in `push.send(registrationIds, data)`_ body_loc_args: undefined, title_loc_key: undefined, title_loc_args: undefined, - android_channel_id: undefined + android_channel_id: undefined } ``` From 8c661f4a1abe611d0116bcef71960b80cf92abb7 Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:30:56 +0200 Subject: [PATCH 27/28] back whitespaces From 0256e2bce580675f7e5fa89d3534c195967a559b Mon Sep 17 00:00:00 2001 From: AntonSelezev Date: Fri, 12 Jan 2024 19:33:40 +0200 Subject: [PATCH 28/28] remove ) --- README.md | 102 ++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index aa9d2b6..618b200 100644 --- a/README.md +++ b/README.md @@ -317,61 +317,57 @@ push.send(registrationIds, data) The following parameters are used to create a GCM message. See https://developers.google.com/cloud-messaging/http-server-ref#table5 for more info: ```js -// Set default custom data from data -let custom; -if (typeof data.custom === 'string') { - custom = { - message: data.custom, - }; -} else if (typeof data.custom === 'object') { - custom = Object.assign({}, data.custom); -} else { - custom = { - data: data.custom, - }; -} + // Set default custom data from data + let custom; + if (typeof data.custom === 'string') { + custom = { + message: data.custom, + }; + } else if (typeof data.custom === 'object') { + custom = Object.assign({}, data.custom); + } else { + custom = { + data: data.custom, + }; + } -custom.title = custom.title || data.title; -custom.message = custom.message || data.body; -custom.sound = custom.sound || data.sound; -custom.icon = custom.icon || data.icon; -custom.msgcnt = custom.msgcnt || data.badge; -if (opts.phonegap === true && data.contentAvailable) { - custom['content-available'] = 1; -} + custom.title = custom.title || data.title; + custom.message = custom.message || data.body; + custom.sound = custom.sound || data.sound; + custom.icon = custom.icon || data.icon; + custom.msgcnt = custom.msgcnt || data.badge; + if (opts.phonegap === true && data.contentAvailable) { + custom['content-available'] = 1; + } -const message = new gcm.Message({ - // See https://developers.google.com/cloud-messaging/http-server-ref#table5 - collapseKey: data.collapseKey, - priority: data.priority === 'normal' ? data.priority : 'high', - contentAvailable: data.contentAvailable || false, - delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored) - timeToLive: - data.expiry - Math.floor(Date.now() / 1000) || - data.timeToLive || - 28 * 86400, - restrictedPackageName: data.restrictedPackageName, - dryRun: data.dryRun || false, - data: data.custom, - notification: { - title: data.title, // Android, iOS (Watch) - body: data.body, // Android, iOS - icon: data.icon, // Android - image: data.image, // Android - style: data.style, // Android - picture: data.picture, // Android - sound: data.sound, // Android, iOS - badge: data.badge, // iOS - tag: data.tag, // Android - color: data.color, // Android - click_action: data.clickAction || data.category, // Android, iOS - body_loc_key: data.locKey, // Android, iOS - body_loc_args: data.locArgs, // Android, iOS - title_loc_key: data.titleLocKey, // Android, iOS - title_loc_args: data.titleLocArgs, // Android, iOS - android_channel_id: data.android_channel_id, // Android - }, -}); + const message = new gcm.Message({ // See https://developers.google.com/cloud-messaging/http-server-ref#table5 + collapseKey: data.collapseKey, + priority: data.priority === 'normal' ? data.priority : 'high', + contentAvailable: data.contentAvailable || false, + delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored) + timeToLive: data.expiry - Math.floor(Date.now() / 1000) || data.timeToLive || 28 * 86400, + restrictedPackageName: data.restrictedPackageName, + dryRun: data.dryRun || false, + data: data.custom, + notification: { + title: data.title, // Android, iOS (Watch) + body: data.body, // Android, iOS + icon: data.icon, // Android + image: data.image, // Android + style: data.style, // Android + picture: data.picture, // Android + sound: data.sound, // Android, iOS + badge: data.badge, // iOS + tag: data.tag, // Android + color: data.color, // Android + click_action: data.clickAction || data.category, // Android, iOS + body_loc_key: data.locKey, // Android, iOS + body_loc_args: data.locArgs, // Android, iOS + title_loc_key: data.titleLocKey, // Android, iOS + title_loc_args: data.titleLocArgs, // Android, iOS + android_channel_id: data.android_channel_id, // Android + }, + } ``` _data is the parameter in `push.send(registrationIds, data)`_