diff --git a/.gitignore b/.gitignore index 6704566..6ad73e5 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ dist # TernJS port file .tern-port + +fcm-admin.json diff --git a/package-lock.json b/package-lock.json index 0da33bd..249bb6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "class-validator-mongo-object-id": "^1.3.0", "cross-env": "^7.0.3", "express-basic-auth": "^1.2.1", + "firebase-admin": "^10.2.0", "hbs": "^4.1.2", "joi": "^17.4.2", "moment-timezone": "^0.5.34", @@ -872,6 +873,292 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/@firebase/app": { + "version": "0.7.24", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.24.tgz", + "integrity": "sha512-HIbAhayEykbCez1Rl6pmzAWbIx63Mc9+t3ngWKqZdkMnBNAAJvYaUdx7Krus7O9XHUKNw/gzBUETAEYt93jusA==", + "peer": true, + "dependencies": { + "@firebase/component": "0.5.14", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.6.0", + "idb": "7.0.1", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-compat": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.25.tgz", + "integrity": "sha512-FdCnYwIM3R+OuRE7nrAdVT5oNlvSAHQHN1ictB/gjCFs58lXMCe0DCIRDrA7zxaOFIKeWPtx35ZNXv3EdPFNpQ==", + "peer": true, + "dependencies": { + "@firebase/app": "0.7.24", + "@firebase/component": "0.5.14", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.6.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz", + "integrity": "sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==" + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.14.tgz", + "integrity": "sha512-ct2p1MTMV5P/nGIlkC3XjAVwHwjsIZaeo8JVyDAkJCNTROu5mYX3FBK16hjIUIIVJDpgnnzFh9nP74gciL4WrA==", + "peer": true, + "dependencies": { + "@firebase/util": "1.6.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz", + "integrity": "sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.13", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.5.2", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz", + "integrity": "sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A==", + "dependencies": { + "@firebase/component": "0.5.13", + "@firebase/database": "0.12.8", + "@firebase/database-types": "0.9.7", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/database-compat/node_modules/@firebase/component": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", + "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", + "dependencies": { + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat/node_modules/@firebase/database-types": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz", + "integrity": "sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw==", + "dependencies": { + "@firebase/app-types": "0.7.0", + "@firebase/util": "1.5.2" + } + }, + "node_modules/@firebase/database-compat/node_modules/@firebase/util": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", + "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz", + "integrity": "sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w==", + "dependencies": { + "@firebase/app-types": "0.7.0", + "@firebase/util": "1.6.0" + } + }, + "node_modules/@firebase/database/node_modules/@firebase/component": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", + "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", + "dependencies": { + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database/node_modules/@firebase/util": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", + "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/logger": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz", + "integrity": "sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz", + "integrity": "sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz", + "integrity": "sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA==", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^2.24.1", + "protobufjs": "^6.8.6" + }, + "engines": { + "node": ">=10.10.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": "2.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", + "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/storage": { + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "abort-controller": "^3.0.0", + "arrify": "^2.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "configstore": "^5.0.0", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.1", + "hash-stream-validation": "^0.2.2", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "pumpify": "^2.0.0", + "retry-request": "^4.2.2", + "stream-events": "^1.0.4", + "teeny-request": "^7.1.3", + "uuid": "^8.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/storage/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/@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/@grpc/grpc-js": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz", + "integrity": "sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.6.4", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", + "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", + "optional": true, + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@hapi/hoek": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", @@ -2056,6 +2343,78 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==", + "engines": { + "node": ">=10.13.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/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -2184,7 +2543,6 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -2209,7 +2567,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -2260,7 +2617,6 @@ "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -2272,7 +2628,6 @@ "version": "4.17.28", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -2440,11 +2795,16 @@ "@types/node": "*" } }, + "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/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { "version": "16.11.25", @@ -2466,14 +2826,12 @@ "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" }, "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==", - "dev": true + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/redis": { "version": "2.8.32", @@ -2488,7 +2846,6 @@ "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -2875,6 +3232,18 @@ "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "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/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2952,7 +3321,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "devOptional": true, "dependencies": { "debug": "4" }, @@ -3113,6 +3482,15 @@ "node": ">=8" } }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3128,6 +3506,15 @@ "node": ">=8" } }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3307,6 +3694,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "optional": true, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3861,6 +4257,18 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, + "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", @@ -3912,6 +4320,23 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -4050,6 +4475,15 @@ "node": ">= 8" } }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -4089,9 +4523,9 @@ } }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "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" }, @@ -4272,6 +4706,18 @@ "node": ">=8" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "optional": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", @@ -4288,6 +4734,41 @@ "node": ">=12" } }, + "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/duplexify/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -4336,7 +4817,7 @@ "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" } @@ -4426,6 +4907,12 @@ "node": ">=8.6" } }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "optional": true + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4884,6 +5371,15 @@ "node": ">= 0.6" } }, + "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/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -5006,6 +5502,12 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -5024,7 +5526,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "devOptional": true }, "node_modules/fast-diff": { "version": "1.2.0", @@ -5065,6 +5567,12 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, + "node_modules/fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "optional": true + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -5074,6 +5582,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/fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -5174,6 +5693,47 @@ "node": ">=8" } }, + "node_modules/firebase-admin": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz", + "integrity": "sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA==", + "dependencies": { + "@firebase/database-compat": "^0.1.8", + "@firebase/database-types": "^0.9.7", + "@types/node": ">=12.12.47", + "dicer": "^0.3.0", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.2", + "node-forge": "^1.3.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^4.15.1", + "@google-cloud/storage": "^5.18.3" + } + }, + "node_modules/firebase-admin/node_modules/dicer": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.1.tgz", + "integrity": "sha512-ObioMtXnmjYs3aRtpIJt9rgQSPCIhKVkFPip+E9GUDyWl8N435znUxK/JfNwGZJ2wnn5JKQ7Ly3vOK5Q5dylGA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/firebase-admin/node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -5392,7 +5952,36 @@ "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": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "optional": true, + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -5528,11 +6117,164 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "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": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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": "2.30.4", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.4.tgz", + "integrity": "sha512-/W4wWKjYcCXtd3Vz+ux7fN3MElbLVKGmHCCgA6kotigQgoDrLLueSvnXsck7qZaF39ooYnFhA58Rjr7RHe2heA==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.2", + "retry-request": "^4.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-gax/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/google-gax/node_modules/protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "optional": true, + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true + "devOptional": true + }, + "node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "optional": true, + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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/handlebars": { "version": "4.7.7", @@ -5592,6 +6334,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-stream-validation": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", + "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==", + "optional": true + }, "node_modules/hbs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hbs/-/hbs-4.2.0.tgz", @@ -5656,6 +6404,11 @@ "node": ">= 0.6" } }, + "node_modules/http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -5674,7 +6427,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, + "devOptional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -5703,6 +6456,12 @@ "node": ">=0.10.0" } }, + "node_modules/idb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==", + "peer": true + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -5770,7 +6529,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.8.19" } @@ -5980,6 +6739,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -5990,7 +6758,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" }, @@ -5998,11 +6766,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "devOptional": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -6983,6 +7757,20 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jose": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz", + "integrity": "sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==", + "dependencies": { + "@panva/asn1.js": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0 < 13 || >=13.7.0" + }, + "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", @@ -7060,6 +7848,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-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -7156,6 +7953,21 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jwks-rsa": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.3.tgz", + "integrity": "sha512-+zSFnZYHckwxEIgjEu81AAWDyqx8z5/OVtmhuXPbchUA9Y4bipVDqvL/5Z5Qhe088e/uxPvp8QDpIDOmI2cEBg==", + "dependencies": { + "@types/express": "^4.17.13", + "debug": "^4.3.4", + "jose": "^2.0.5", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + }, + "engines": { + "node": ">=10 < 13 || >=14" + } + }, "node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -7206,6 +8018,11 @@ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.49.tgz", "integrity": "sha512-/wEOIONcVboFky+lWlCaF7glm1FhBz11M5PHeCApA+xDdVfmhKjHktHS8KjyGxouV5CSXIr4f3GvLSpJa4qMSg==" }, + "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.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -7238,6 +8055,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": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -7338,6 +8166,12 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7349,6 +8183,29 @@ "node": ">=10" } }, + "node_modules/lru-memoizer": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", + "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", + "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": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "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": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, "node_modules/luxon": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", @@ -7382,7 +8239,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, + "devOptional": true, "dependencies": { "semver": "^6.0.0" }, @@ -7397,7 +8254,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, + "devOptional": true, "bin": { "semver": "bin/semver.js" } @@ -8009,6 +8866,14 @@ "webidl-conversions": "^3.0.0" } }, + "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/node-gyp-build-optional-packages": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-4.3.2.tgz", @@ -8543,6 +9408,41 @@ "node": ">= 6" } }, + "node_modules/proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "optional": true, + "dependencies": { + "protobufjs": "^6.11.2" + } + }, + "node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -8555,6 +9455,11 @@ "node": ">= 0.10" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -8565,10 +9470,21 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, + "devOptional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" } }, "node_modules/punycode": { @@ -8819,6 +9735,28 @@ "node": ">=8" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -9140,7 +10078,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "devOptional": true }, "node_modules/sisteransi": { "version": "1.0.5", @@ -9313,6 +10251,21 @@ "node": ">= 0.6" } }, + "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/streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", @@ -9393,6 +10346,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "optional": true + }, "node_modules/superagent": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", @@ -9587,6 +10546,45 @@ "node": ">=6" } }, + "node_modules/teeny-request": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", + "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "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": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/teeny-request/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/teeny-request/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/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -10124,7 +11122,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, + "devOptional": true, "dependencies": { "is-typedarray": "^1.0.0" } @@ -10355,6 +11353,18 @@ "node": ">=0.8.0" } }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -10642,6 +11652,27 @@ "node": ">=6" } }, + "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-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -10786,7 +11817,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, + "devOptional": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -10815,6 +11846,15 @@ } } }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -10913,6 +11953,18 @@ "node": ">=6" } }, + "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" + } + }, "node_modules/zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", @@ -11547,6 +12599,256 @@ } } }, + "@firebase/app": { + "version": "0.7.24", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.24.tgz", + "integrity": "sha512-HIbAhayEykbCez1Rl6pmzAWbIx63Mc9+t3ngWKqZdkMnBNAAJvYaUdx7Krus7O9XHUKNw/gzBUETAEYt93jusA==", + "peer": true, + "requires": { + "@firebase/component": "0.5.14", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.6.0", + "idb": "7.0.1", + "tslib": "^2.1.0" + } + }, + "@firebase/app-compat": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.25.tgz", + "integrity": "sha512-FdCnYwIM3R+OuRE7nrAdVT5oNlvSAHQHN1ictB/gjCFs58lXMCe0DCIRDrA7zxaOFIKeWPtx35ZNXv3EdPFNpQ==", + "peer": true, + "requires": { + "@firebase/app": "0.7.24", + "@firebase/component": "0.5.14", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.6.0", + "tslib": "^2.1.0" + } + }, + "@firebase/app-types": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz", + "integrity": "sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==" + }, + "@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "requires": {} + }, + "@firebase/component": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.14.tgz", + "integrity": "sha512-ct2p1MTMV5P/nGIlkC3XjAVwHwjsIZaeo8JVyDAkJCNTROu5mYX3FBK16hjIUIIVJDpgnnzFh9nP74gciL4WrA==", + "peer": true, + "requires": { + "@firebase/util": "1.6.0", + "tslib": "^2.1.0" + } + }, + "@firebase/database": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz", + "integrity": "sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA==", + "requires": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.13", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.5.2", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/component": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", + "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", + "requires": { + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + } + }, + "@firebase/util": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", + "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@firebase/database-compat": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz", + "integrity": "sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A==", + "requires": { + "@firebase/component": "0.5.13", + "@firebase/database": "0.12.8", + "@firebase/database-types": "0.9.7", + "@firebase/logger": "0.3.2", + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + }, + "dependencies": { + "@firebase/component": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", + "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", + "requires": { + "@firebase/util": "1.5.2", + "tslib": "^2.1.0" + } + }, + "@firebase/database-types": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz", + "integrity": "sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw==", + "requires": { + "@firebase/app-types": "0.7.0", + "@firebase/util": "1.5.2" + } + }, + "@firebase/util": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", + "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@firebase/database-types": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz", + "integrity": "sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w==", + "requires": { + "@firebase/app-types": "0.7.0", + "@firebase/util": "1.6.0" + } + }, + "@firebase/logger": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz", + "integrity": "sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@firebase/util": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz", + "integrity": "sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@google-cloud/firestore": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz", + "integrity": "sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^2.24.1", + "protobufjs": "^6.8.6" + } + }, + "@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": "2.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", + "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==", + "optional": true + }, + "@google-cloud/promisify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", + "optional": true + }, + "@google-cloud/storage": { + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", + "optional": true, + "requires": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "abort-controller": "^3.0.0", + "arrify": "^2.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "configstore": "^5.0.0", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.1", + "hash-stream-validation": "^0.2.2", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "pumpify": "^2.0.0", + "retry-request": "^4.2.2", + "stream-events": "^1.0.4", + "teeny-request": "^7.1.3", + "uuid": "^8.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true + }, + "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" + } + } + } + }, + "@grpc/grpc-js": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz", + "integrity": "sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw==", + "optional": true, + "requires": { + "@grpc/proto-loader": "^0.6.4", + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", + "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", + "optional": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.2.0" + } + }, "@hapi/hoek": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", @@ -12362,6 +13664,75 @@ } } }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, + "@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 + }, "@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -12484,7 +13855,6 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, "requires": { "@types/connect": "*", "@types/node": "*" @@ -12509,7 +13879,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, "requires": { "@types/node": "*" } @@ -12560,7 +13929,6 @@ "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -12572,7 +13940,6 @@ "version": "4.17.28", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, "requires": { "@types/node": "*", "@types/qs": "*", @@ -12721,11 +14088,16 @@ "@types/node": "*" } }, + "@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/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "@types/node": { "version": "16.11.25", @@ -12747,14 +14119,12 @@ "@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" }, "@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==", - "dev": true + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "@types/redis": { "version": "2.8.32", @@ -12769,7 +14139,6 @@ "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, "requires": { "@types/mime": "^1", "@types/node": "*" @@ -13082,6 +14451,15 @@ "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "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" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -13139,7 +14517,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "devOptional": true, "requires": { "debug": "4" } @@ -13254,6 +14632,12 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -13266,6 +14650,15 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "requires": { + "retry": "0.13.1" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -13399,6 +14792,12 @@ } } }, + "bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "optional": true + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -13823,6 +15222,15 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, + "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", @@ -13873,6 +15281,20 @@ } } }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, "consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", @@ -13983,6 +15405,12 @@ "which": "^2.0.1" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true + }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -14018,9 +15446,9 @@ } }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "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" } @@ -14156,6 +15584,15 @@ } } }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "optional": true, + "requires": { + "is-obj": "^2.0.0" + } + }, "dotenv": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", @@ -14166,6 +15603,40 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.1.tgz", "integrity": "sha512-j/Ih7bIERDR5PzI89Zu8ayd3tXZ6E3dbY0ljQ9Db0K87qBO8zdLsi2dIvDHMWtjC3Yxb8XixOTHAtia0fDHRpg==" }, + "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" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -14205,7 +15676,7 @@ "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" } @@ -14270,6 +15741,12 @@ "ansi-colors": "^4.1.1" } }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "optional": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -14601,6 +16078,12 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "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 + }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -14707,6 +16190,12 @@ "basic-auth": "^2.0.1" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -14722,7 +16211,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "devOptional": true }, "fast-diff": { "version": "1.2.0", @@ -14760,6 +16249,12 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "optional": true + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -14769,6 +16264,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" + } + }, "fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -14852,6 +16355,38 @@ "path-exists": "^4.0.0" } }, + "firebase-admin": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz", + "integrity": "sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA==", + "requires": { + "@firebase/database-compat": "^0.1.8", + "@firebase/database-types": "^0.9.7", + "@google-cloud/firestore": "^4.15.1", + "@google-cloud/storage": "^5.18.3", + "@types/node": ">=12.12.47", + "dicer": "^0.3.0", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.2", + "node-forge": "^1.3.1", + "uuid": "^8.3.2" + }, + "dependencies": { + "dicer": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.1.tgz", + "integrity": "sha512-ObioMtXnmjYs3aRtpIJt9rgQSPCIhKVkFPip+E9GUDyWl8N435znUxK/JfNwGZJ2wnn5JKQ7Ly3vOK5Q5dylGA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + } + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -15002,7 +16537,30 @@ "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": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "optional": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } }, "gensync": { "version": "1.0.0-beta.2", @@ -15093,11 +16651,144 @@ "slash": "^3.0.0" } }, + "google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "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": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "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": "2.30.4", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.4.tgz", + "integrity": "sha512-/W4wWKjYcCXtd3Vz+ux7fN3MElbLVKGmHCCgA6kotigQgoDrLLueSvnXsck7qZaF39ooYnFhA58Rjr7RHe2heA==", + "optional": true, + "requires": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.2", + "retry-request": "^4.0.0" + }, + "dependencies": { + "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 + }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + } + } + }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "optional": true, + "requires": { + "node-forge": "^1.3.1" + } + }, "graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true + "devOptional": true + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "optional": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "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" + } + } + } }, "handlebars": { "version": "4.7.7", @@ -15136,6 +16827,12 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, + "hash-stream-validation": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", + "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==", + "optional": true + }, "hbs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hbs/-/hbs-4.2.0.tgz", @@ -15184,6 +16881,11 @@ "toidentifier": "1.0.1" } }, + "http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -15199,7 +16901,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, + "devOptional": true, "requires": { "agent-base": "6", "debug": "4" @@ -15219,6 +16921,12 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "idb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==", + "peer": true + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -15254,7 +16962,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "devOptional": true }, "inflight": { "version": "1.0.6", @@ -15414,6 +17122,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true + }, "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -15424,13 +17138,19 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "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-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "devOptional": true }, "is-unicode-supported": { "version": "0.1.0", @@ -16189,6 +17909,14 @@ "@sideway/pinpoint": "^2.0.0" } }, + "jose": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz", + "integrity": "sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -16246,6 +17974,15 @@ "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-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -16329,6 +18066,18 @@ "safe-buffer": "^5.0.1" } }, + "jwks-rsa": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.3.tgz", + "integrity": "sha512-+zSFnZYHckwxEIgjEu81AAWDyqx8z5/OVtmhuXPbchUA9Y4bipVDqvL/5Z5Qhe088e/uxPvp8QDpIDOmI2cEBg==", + "requires": { + "@types/express": "^4.17.13", + "debug": "^4.3.4", + "jose": "^2.0.5", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + } + }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -16370,6 +18119,11 @@ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.49.tgz", "integrity": "sha512-/wEOIONcVboFky+lWlCaF7glm1FhBz11M5PHeCApA+xDdVfmhKjHktHS8KjyGxouV5CSXIr4f3GvLSpJa4qMSg==" }, + "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.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -16396,6 +18150,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": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -16486,6 +18251,12 @@ } } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -16494,6 +18265,31 @@ "yallist": "^4.0.0" } }, + "lru-memoizer": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", + "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", + "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": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "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": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, "luxon": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", @@ -16518,7 +18314,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, + "devOptional": true, "requires": { "semver": "^6.0.0" }, @@ -16527,7 +18323,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "devOptional": true } } }, @@ -16984,6 +18780,11 @@ } } }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, "node-gyp-build-optional-packages": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-4.3.2.tgz", @@ -17373,6 +19174,36 @@ "sisteransi": "^1.0.5" } }, + "proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "optional": true, + "requires": { + "protobufjs": "^6.11.2" + } + }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -17382,6 +19213,11 @@ "ipaddr.js": "1.9.1" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -17392,12 +19228,23 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, + "devOptional": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -17571,6 +19418,22 @@ "signal-exit": "^3.0.2" } }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true + }, + "retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "optional": true, + "requires": { + "debug": "^4.1.1", + "extend": "^3.0.2" + } + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -17808,7 +19671,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "devOptional": true }, "sisteransi": { "version": "1.0.5", @@ -17947,6 +19810,21 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "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 + }, "streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", @@ -18003,6 +19881,12 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "optional": true + }, "superagent": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", @@ -18148,6 +20032,38 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, + "teeny-request": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", + "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "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": "^8.0.0" + }, + "dependencies": { + "@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 + }, + "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" + } + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -18527,7 +20443,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, + "devOptional": true, "requires": { "is-typedarray": "^1.0.0" } @@ -18639,6 +20555,15 @@ "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", "optional": true }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -18861,6 +20786,21 @@ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": 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-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -18968,7 +20908,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, + "devOptional": true, "requires": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -18983,6 +20923,12 @@ "dev": true, "requires": {} }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -19057,6 +21003,12 @@ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "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 + }, "zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", diff --git a/package.json b/package.json index ce72cc5..e93eb73 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "class-validator-mongo-object-id": "^1.3.0", "cross-env": "^7.0.3", "express-basic-auth": "^1.2.1", + "firebase-admin": "^10.2.0", "hbs": "^4.1.2", "joi": "^17.4.2", "moment-timezone": "^0.5.34", diff --git a/src/apis/alarm/alarm.module.ts b/src/apis/alarm/alarm.module.ts index fcaa75a..cfe2c52 100644 --- a/src/apis/alarm/alarm.module.ts +++ b/src/apis/alarm/alarm.module.ts @@ -8,6 +8,10 @@ import { BullModule } from '@nestjs/bull'; import { PushAlarmProcessor } from './pushAlarm.processor'; import { PUSH_ALARM, SAVE_ALARM } from 'src/common/consts/enum'; import { SaveAlarmProcessor } from './saveAlarm.processor'; +import { NotiController } from './noti.controller'; +import { FcmModule } from 'src/fcm/fcm.module'; +import * as path from 'path'; +import { RoomsModule } from '../rooms/rooms.module'; @Module({ imports: [ @@ -21,7 +25,12 @@ import { SaveAlarmProcessor } from './saveAlarm.processor'; name: SAVE_ALARM, }, ), + FcmModule.forRoot({ + credentialPath: path.join(__dirname, '../../../fcm-admin.json'), + }), + RoomsModule, ], + controllers: [NotiController], providers: [ AlarmService, AlarmRepository, diff --git a/src/apis/alarm/alarm.service.ts b/src/apis/alarm/alarm.service.ts index 8fbfcdb..9d95196 100644 --- a/src/apis/alarm/alarm.service.ts +++ b/src/apis/alarm/alarm.service.ts @@ -18,6 +18,11 @@ import { Room } from 'src/models/room.model'; import { AlarmIdDto } from 'src/common/dtos/AlarmId.dto'; import { AlarmShowDto } from './dto/alarmShow.dto'; import { plainToInstance } from 'class-transformer'; +import { QuestionIdDto } from 'src/common/dtos/QuestionId.dto'; +import { PageLastIdDto } from 'src/common/dtos/PageLastIdDto'; +import { AlarmPaginationShowDto } from './dto/alarmPaginationShow.dto'; +import { FcmService } from 'src/fcm/fcm.service'; +import { LetterRoomIdDto } from 'src/common/dtos/LetterRoomId.dto'; @Injectable() export class AlarmService { constructor( @@ -68,12 +73,18 @@ export class AlarmService { // 나한테 편지가 왔을 때 // 푸시알림만 해야함 - async pushLetterAlarm(sender: User, receiver: UserIdDto, letter: Letter) { + async pushLetterAlarm( + sender: User, + receiver: UserIdDto, + letter: Letter, + letterRoomIdDto: LetterRoomIdDto, + ) { const sendPushAlarmObj: SendPushAlarmPubDto = { nickname: sender.nickname, content: letter.message, pushAlarmType: PUSH_ALARM_TYPE.LETTER, receivers: [receiver.userId], + letterRoomId: letterRoomIdDto.letterRoomId.toString(), }; // const redis = await this.pushAlarmQueue.isReady(); // console.log('check', redis); @@ -87,10 +98,22 @@ export class AlarmService { nickname: sender.nickname, user: receiver.userId.toString(), alarmType: ALARM_STORE_TYPE.LIGHTNING, - deepLink: '', }; await this.saveAlarmQueue.add(ALARM_STORE_TYPE.LIGHTNING, saveAlarmDto); } + // 내 레벨이 올랐을 때 (기획 기달려야함) + + async handleLevelUpAlarm(receiver: UserIdDto, level: string) { + const saveAlarmDto: SaveAlarmDto = { + user: receiver.userId.toString(), + content: level, + alarmType: ALARM_STORE_TYPE.LIGHTNING_LEVELUP, + }; + await this.saveAlarmQueue.add( + ALARM_STORE_TYPE.LIGHTNING_LEVELUP, + saveAlarmDto, + ); + } // 내 질문에 댓글 달렸을 때 ( 내 댓글이면 제외 시켜야함. (이또한 책임을 알람 서비스로 넘김 )) @@ -99,6 +122,7 @@ export class AlarmService { receiver: UserIdDto, room: Room, comment: string, + questionIdDto: QuestionIdDto, ) { // console.log('check', sender); const saveAlarmDto: SaveAlarmDto = { @@ -107,7 +131,7 @@ export class AlarmService { content: comment, roomName: room.name, alarmType: ALARM_STORE_TYPE.COMMENT, - deepLink: '', + questionId: questionIdDto.questionId.toString(), }; await this.saveAlarmQueue.add(ALARM_STORE_TYPE.COMMENT, saveAlarmDto); @@ -116,13 +140,11 @@ export class AlarmService { content: comment, receivers: [receiver.userId], pushAlarmType: PUSH_ALARM_TYPE.COMMENT, + questionId: questionIdDto.questionId.toString(), }; await this.pushAlarmQueue.add(PUSH_ALARM_TYPE.COMMENT, sendPushAlarmObj); } - // 내 레벨이 올랐을 때 (기획 기달려야함) - async handleLevelUpAlarm() {} - // 서비스 공식알림 ( 추후 추가 ) // 알림 읽었을 때 @@ -141,12 +163,37 @@ export class AlarmService { await this.alarmRepository.watchAllAlarm(userIdDto); } - async getMyAlarms(userIdDto: UserIdDto): Promise { - const alarmRawList = await this.alarmRepository.findAlarmByUserId( - userIdDto, - ); + async getMyAlarms( + userIdDto: UserIdDto, + pageLastIdDto: PageLastIdDto, + ): Promise { + console.log(userIdDto); + let alarmRawList = []; + if (!pageLastIdDto.lastId) { + alarmRawList = await this.alarmRepository.findAlarmByUserIdFirst( + userIdDto, + 50, + ); + } else { + alarmRawList = await this.alarmRepository.findAlarmByUserIdAndLastId( + userIdDto, + pageLastIdDto, + 50, + ); + } + + const alarmList = plainToInstance(AlarmShowDto, alarmRawList, { + excludeExtraneousValues: true, + }); + const isLast = alarmList.length === 50 ? false : true; + let lastId; + if (alarmList.length === 50) { + lastId = alarmList[49]._id.toString(); + } else { + lastId = null; + } - return plainToInstance(AlarmShowDto, alarmRawList); + return new AlarmPaginationShowDto(alarmList, isLast, lastId); } // 안읽은 알림 갯수 diff --git a/src/apis/alarm/dto/alarmPaginationShow.dto.ts b/src/apis/alarm/dto/alarmPaginationShow.dto.ts new file mode 100644 index 0000000..c74cafd --- /dev/null +++ b/src/apis/alarm/dto/alarmPaginationShow.dto.ts @@ -0,0 +1,36 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Expose, Transform, Type } from 'class-transformer'; +import { Types } from 'mongoose'; +import { ALARM_STORE_TYPE } from 'src/common/consts/enum'; +import { AlarmShowDto } from './alarmShow.dto'; + +// use for message transfor +export class AlarmPaginationShowDto { + constructor(noti_list: AlarmShowDto[], isLast: boolean, lastId: string) { + this.isLast = isLast; + this.lastId = lastId; + this.noti_list = noti_list; + } + // 직렬화 + @ApiProperty({ + type: String, + description: '알림 리스트', + }) + @Expose() + @Type(() => AlarmShowDto) + noti_list: AlarmShowDto[]; + + @ApiProperty({ + type: String, + description: '마지막인지 여부 ', + }) + @Expose() + isLast: boolean; + + @ApiProperty({ + type: String, + description: '마지막 콘텐트의 아이디', + }) + @Expose() + lastId: string; +} diff --git a/src/apis/alarm/dto/alarmShow.dto.ts b/src/apis/alarm/dto/alarmShow.dto.ts index 2fc467d..d5539d5 100644 --- a/src/apis/alarm/dto/alarmShow.dto.ts +++ b/src/apis/alarm/dto/alarmShow.dto.ts @@ -1,25 +1,34 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Exclude, Expose, Transform, Type } from 'class-transformer'; +import { Exclude, Expose, Transform } from 'class-transformer'; +import { ALARM_STORE_TYPE, DEEPLINK_BASEURL } from 'src/common/consts/enum'; +import { TransformObjectIdToString } from 'src/common/decorators/Expose.decorator'; +import { toKRTimeZone } from 'src/common/funcs/toKRTimezone'; import { Types } from 'mongoose'; -import { ALARM_STORE_TYPE } from 'src/common/consts/enum'; // use for message transfor export class AlarmShowDto { // 직렬화 + @ApiProperty({ + type: String, + description: '알림의 고유 아이디 정보', + }) + @TransformObjectIdToString({ toClassOnly: true }) + @Expose() + _id: Types.ObjectId; - @Exclude({ toPlainOnly: false }) + @Exclude({ toPlainOnly: true }) @Expose({ toClassOnly: true }) roomName?: string; - @Exclude({ toPlainOnly: false }) + @Exclude({ toPlainOnly: true }) @Expose({ toClassOnly: true }) nickname: string; - @Exclude({ toPlainOnly: false }) + @Exclude({ toPlainOnly: true }) @Expose({ toClassOnly: true }) user: string; - @Exclude({ toPlainOnly: false }) + @Exclude({ toPlainOnly: true }) @Expose({ toClassOnly: true }) content?: string; @@ -30,7 +39,18 @@ export class AlarmShowDto { description: '딥링크 정보', }) @Expose() - deepLink: string; + get deepLink(): string { + switch (this.alarmType) { + case ALARM_STORE_TYPE.LIGHTNING: + return DEEPLINK_BASEURL + 'screen-type?mypage'; + case ALARM_STORE_TYPE.COMMENT: + return ( + DEEPLINK_BASEURL + 'question-detail?question_id=' + this.questionId + ); + case ALARM_STORE_TYPE.LIGHTNING_LEVELUP: + return DEEPLINK_BASEURL + 'screen-type?mypage'; + } + } @ApiProperty({ type: String, @@ -42,7 +62,11 @@ export class AlarmShowDto { case ALARM_STORE_TYPE.LIGHTNING: return this.nickname + '님이 번개를 줬어요 ⚡️'; case ALARM_STORE_TYPE.COMMENT: - return this.nickname + `님이 댓글을 남겼어요 "${this.content}"`; + return ( + this.nickname + '님이 댓글을 남겼어요 ' + '“' + this.content + '“' + ); + case ALARM_STORE_TYPE.LIGHTNING_LEVELUP: + return `${this.content}로 레벨업을 했어요 축하드려요!`; case ALARM_STORE_TYPE.OFFICIAL: return '서비스 공식알림'; } @@ -58,6 +82,8 @@ export class AlarmShowDto { return this.nickname; case ALARM_STORE_TYPE.COMMENT: return this.roomName; + case ALARM_STORE_TYPE.LIGHTNING_LEVELUP: + return `레벨 업 축하`; case ALARM_STORE_TYPE.OFFICIAL: return '티키타카 비밀 운영자'; } @@ -70,4 +96,22 @@ export class AlarmShowDto { }) @Expose() alarmType: ALARM_STORE_TYPE; + + @ApiProperty({ + type: String, + description: '한국시간으로 보정된 시간값', + }) + @Transform(({ value }) => toKRTimeZone(value), { toClassOnly: true }) + @Expose() + createdAt: Date; + + @Exclude({ toPlainOnly: true }) + @Expose({ toClassOnly: true }) + questionId?: string; + @ApiProperty({ + type: Boolean, + description: '내가 봤는지 ', + }) + @Expose() + iWatch: boolean; } diff --git a/src/apis/alarm/dto/chatAlarm.sub.dto.ts b/src/apis/alarm/dto/chatAlarm.sub.dto.ts new file mode 100644 index 0000000..dd2f81a --- /dev/null +++ b/src/apis/alarm/dto/chatAlarm.sub.dto.ts @@ -0,0 +1,27 @@ +import { Expose, Transform, Type } from 'class-transformer'; +import { ALARM_STORE_TYPE } from 'src/common/consts/enum'; +import { Types } from 'mongoose'; + +// use for message transfor +export class ChatAlarmSubDto { + // 직렬화 + @Expose() + roomId: string; + + @Expose() + chatId: string; + + @Expose() + nickname: string; + + @Expose() // message 내용 + content: string; + + @Expose() + sender: string; +} + +// nickname +// content : message +// chatId : string +// roomId : string diff --git a/src/apis/alarm/dto/saveAlarm.dto.ts b/src/apis/alarm/dto/saveAlarm.dto.ts index 281c6f8..6888dd5 100644 --- a/src/apis/alarm/dto/saveAlarm.dto.ts +++ b/src/apis/alarm/dto/saveAlarm.dto.ts @@ -1,6 +1,6 @@ import { Expose, Transform, Type } from 'class-transformer'; -import { Types } from 'mongoose'; import { ALARM_STORE_TYPE } from 'src/common/consts/enum'; +import { Types } from 'mongoose'; // use for message transfor export class SaveAlarmDto { @@ -8,7 +8,7 @@ export class SaveAlarmDto { @Expose() roomName?: string; @Expose() - nickname: string; + nickname?: string; @Expose() @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) @@ -17,9 +17,21 @@ export class SaveAlarmDto { @Expose() content?: string; - //need to be updated 딥링크 양식 정의 필요 ( 클라와 함께) @Expose() - deepLink: string; + questionId?: string; + + //need to be updated 딥링크 양식 정의 필요 ( 클라와 함께) + // @Expose() + // get deepLink(): string { + // switch (this.alarmType) { + // case ALARM_STORE_TYPE.LIGHTNING: + // return this.roomName + ' 채팅방'; + // case ALARM_STORE_TYPE.COMMENT: + // return '내 질문에 새로운 댓글이 달렸어요'; + // // case ALARM_STORE_TYPE.OFFICIAL: + // // return '쪽지가 도착했어요'; + // } + // } @Expose() alarmType: ALARM_STORE_TYPE; diff --git a/src/apis/alarm/dto/sendPushAlarm.pub.dto.ts b/src/apis/alarm/dto/sendPushAlarm.pub.dto.ts index b201ca0..4f2e822 100644 --- a/src/apis/alarm/dto/sendPushAlarm.pub.dto.ts +++ b/src/apis/alarm/dto/sendPushAlarm.pub.dto.ts @@ -9,4 +9,8 @@ export class SendPushAlarmPubDto extends PickType(SendPushAlarmSubDto, [ 'content', 'pushAlarmType', 'receivers', + 'questionId', + 'letterRoomId', + 'chatId', + 'roomId', ] as const) {} diff --git a/src/apis/alarm/dto/sendPushAlarm.sub.dto.ts b/src/apis/alarm/dto/sendPushAlarm.sub.dto.ts index 69e18bd..8a69774 100644 --- a/src/apis/alarm/dto/sendPushAlarm.sub.dto.ts +++ b/src/apis/alarm/dto/sendPushAlarm.sub.dto.ts @@ -1,5 +1,5 @@ import { Expose, Transform } from 'class-transformer'; -import { PUSH_ALARM_TYPE } from 'src/common/consts/enum'; +import { DEEPLINK_BASEURL, PUSH_ALARM_TYPE } from 'src/common/consts/enum'; import { Types } from 'mongoose'; // use for message transfor @@ -23,11 +23,30 @@ export class SendPushAlarmSubDto { toClassOnly: true, }, ) - receivers: Types.ObjectId[]; + receivers?: Types.ObjectId[]; //need to be updated 딥링크 양식 정의 필요 ( 클라와 함께) @Expose() - deepLink: string; + get deepLink(): string { + switch (this.pushAlarmType) { + case PUSH_ALARM_TYPE.CHAT: + return ( + DEEPLINK_BASEURL + + 'chat-room?chat-room_id=' + + this.roomId + + '&message_id=' + + this.chatId + ); + case PUSH_ALARM_TYPE.COMMENT: + return ( + DEEPLINK_BASEURL + 'question-detail?question_id=' + this.questionId + ); + case PUSH_ALARM_TYPE.LETTER: + return ( + DEEPLINK_BASEURL + 'letter-room?letter-room_id=' + this.letterRoomId + ); + } + } @Expose() get title(): string { @@ -42,7 +61,19 @@ export class SendPushAlarmSubDto { } @Expose() - get subTitle(): string { + get body(): string { return this.nickname + ' : ' + this.content; } + + @Expose() + questionId?: string; + + @Expose() + letterRoomId?: string; + + @Expose() + chatId?: string; + + @Expose() + roomId?: string; } diff --git a/src/apis/alarm/dto/userFcmInfo.dto.ts b/src/apis/alarm/dto/userFcmInfo.dto.ts new file mode 100644 index 0000000..fbec6f9 --- /dev/null +++ b/src/apis/alarm/dto/userFcmInfo.dto.ts @@ -0,0 +1,23 @@ +import { Types } from 'mongoose'; +import { Expose } from 'class-transformer'; + +// use for message transfor + +export const userFcmInfoSelect = { + _id: 1, + FCMToken: 1, + appAlarm: 1, + chatAlarm: 1, +}; +export class UserFcmInfoDto { + // @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + _id: Types.ObjectId; + + @Expose() + FCMToken: string; + @Expose() + appAlarm: boolean; + + @Expose() + chatAlarm: boolean; +} diff --git a/src/apis/alarm/noti.controller.ts b/src/apis/alarm/noti.controller.ts new file mode 100644 index 0000000..650d953 --- /dev/null +++ b/src/apis/alarm/noti.controller.ts @@ -0,0 +1,83 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + Query, + UsePipes, + SerializeOptions, + UseGuards, + ClassSerializerInterceptor, + UseInterceptors, +} from '@nestjs/common'; + +import { + ApiBearerAuth, + ApiBody, + ApiOperation, + ApiParam, + ApiQuery, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; + +import { UserIdDto } from 'src/common/dtos/UserId.dto'; + +import { User } from 'src/models/user.model'; +import { JwtAuthGuard } from 'src/auth/guards/jwt.guard'; + +import { AlarmService } from './alarm.service'; +import { AlarmShowDto } from './dto/alarmShow.dto'; +import { ReqUser } from 'src/common/decorators/user.decorator'; +import { AlarmIdDto } from 'src/common/dtos/AlarmId.dto'; +import { PageLastIdDto } from 'src/common/dtos/PageLastIdDto'; + +@ApiTags('notis') +@Controller('notis') +@ApiBearerAuth('accessToken') +@UseGuards(JwtAuthGuard) +export class NotiController { + constructor(private readonly alarmService: AlarmService) {} + + @ApiOperation({ + summary: '내 알림을 불러온다.', + }) + @Get('') + @ApiResponse({ + status: 201, + description: '요청 성공시', + type: [AlarmShowDto], + }) + getMyAllAlarm(@ReqUser() user: User, @Query() pageLastIdDto: PageLastIdDto) { + console.log('asdfasdfasdf', pageLastIdDto); + return this.alarmService.getMyAlarms(user.userIdDto, pageLastIdDto); + } + + @ApiOperation({ + summary: '내 알림을 다 보게끔 한다.', + }) + @Patch('watchAll') + @ApiResponse({ + status: 201, + description: '요청 성공시', + type: [AlarmShowDto], + }) + watchAllAlarm(@ReqUser() user: User) { + return this.alarmService.watchAllAlarm(user.userIdDto); + } + + @ApiOperation({ + summary: '내 알림 보는걸로 처리', + }) + @Patch(':alarmId') + @ApiResponse({ + status: 200, + description: '성공 응답만 리턴', + }) + watchOneAlarm(@ReqUser() user: User, @Param() alarmIdDto: AlarmIdDto) { + return this.alarmService.watchAlarm(user.userIdDto, alarmIdDto); + } +} diff --git a/src/apis/alarm/pushAlarm.processor.ts b/src/apis/alarm/pushAlarm.processor.ts index 386ff29..5db5773 100644 --- a/src/apis/alarm/pushAlarm.processor.ts +++ b/src/apis/alarm/pushAlarm.processor.ts @@ -1,18 +1,55 @@ -import { Process, Processor } from '@nestjs/bull'; +import { OnQueueFailed, Process, Processor } from '@nestjs/bull'; +import { Inject } from '@nestjs/common'; import { Job } from 'bull'; import { instanceToPlain, plainToInstance } from 'class-transformer'; import { PUSH_ALARM, PUSH_ALARM_TYPE } from 'src/common/consts/enum'; +import { RoomIdDto } from 'src/common/dtos/RoomId.dto'; +import { FcmService } from 'src/fcm/fcm.service'; +import { FCM_ADMIN } from 'src/fcm/fcmAdminProvider'; +import { RoomRepository } from 'src/repositories/room.repository'; +import { UserRepository } from 'src/repositories/user.repository'; +import { ChatAlarmSubDto } from './dto/chatAlarm.sub.dto'; +import { SendPushAlarmPubDto } from './dto/sendPushAlarm.pub.dto'; import { SendPushAlarmSubDto } from './dto/sendPushAlarm.sub.dto'; @Processor(PUSH_ALARM) export class PushAlarmProcessor { + constructor( + private fcmService: FcmService, + private userRepository: UserRepository, + private roomRepository: RoomRepository, + ) {} + + private async sendPushAlarm(sendPushAlarmDto: SendPushAlarmSubDto) { + const findUserFcmToken = await this.userRepository.findUserFcmToken( + sendPushAlarmDto.receivers, + ); + console.log(findUserFcmToken); + + const TokenArray = findUserFcmToken + .filter((e) => (e.appAlarm && e.FCMToken.length === 0 ? false : true)) + .map((e) => e.FCMToken); + console.log(TokenArray); + if (TokenArray.length) { + const result = await this.fcmService.sendNotification( + TokenArray, + sendPushAlarmDto, + ); + console.log(result); + } + } + @OnQueueFailed() + errorhandler(job: Job, err: Error) { + console.log(err); + } + @Process(PUSH_ALARM_TYPE.LETTER) async handleLetterAlarm(job: Job) { // job.data console.log('processor Letter ', job.data); const sendPushAlarmDto = plainToInstance(SendPushAlarmSubDto, job.data); - console.log(sendPushAlarmDto.subTitle, sendPushAlarmDto.title); + await this.sendPushAlarm(sendPushAlarmDto); } @Process(PUSH_ALARM_TYPE.COMMENT) @@ -20,7 +57,45 @@ export class PushAlarmProcessor { // job.data console.log('processor ALARM Comment ', job.data); - const saveAlarmDto = plainToInstance(SendPushAlarmSubDto, job.data); - console.log(saveAlarmDto); + const sendPushAlarmDto = plainToInstance(SendPushAlarmSubDto, job.data); + await this.sendPushAlarm(sendPushAlarmDto); + } + + @Process(PUSH_ALARM_TYPE.CHAT) + async handleChatAlarm(job: Job) { + // job.data + console.log('processor ALARM Comment ', job.data); + + const chatAlarmSubDto = plainToInstance(ChatAlarmSubDto, job.data); + const roomNameAndUserAlarmInfoArray = + await this.roomRepository.getUserAlarmInfoInRoom( + new RoomIdDto(chatAlarmSubDto.roomId), + ); + const TokenArray = roomNameAndUserAlarmInfoArray.userFcmInfoList + .filter((e) => + e.appAlarm && + !e._id.equals(chatAlarmSubDto.sender) && + e.FCMToken.length === 0 + ? false + : true, + ) + .map((e) => e.FCMToken); + + const sendPushAlarmObj: SendPushAlarmPubDto = { + nickname: chatAlarmSubDto.nickname, + content: chatAlarmSubDto.content, + pushAlarmType: PUSH_ALARM_TYPE.CHAT, + chatId: chatAlarmSubDto.chatId, + roomId: chatAlarmSubDto.roomId.toString(), + roomName: roomNameAndUserAlarmInfoArray.roomName, + }; + + if (TokenArray.length) { + const result = await this.fcmService.sendNotification( + TokenArray, + plainToInstance(SendPushAlarmSubDto, sendPushAlarmObj), + ); + console.log(result); + } } } diff --git a/src/apis/alarm/saveAlarm.processor.ts b/src/apis/alarm/saveAlarm.processor.ts index 0f83945..ca0e953 100644 --- a/src/apis/alarm/saveAlarm.processor.ts +++ b/src/apis/alarm/saveAlarm.processor.ts @@ -17,11 +17,7 @@ export class SaveAlarmProcessor { // job.data const saveAlarmDto = plainToInstance(SaveAlarmDto, job.data); - console.log( - 'asdfasdfasdfasdfasdfasdf', - saveAlarmDto, - instanceToPlain(saveAlarmDto), - ); + console.log('asdfasdfasdfasdfasdfasdf', saveAlarmDto); // console.log('processor Commentasdfasdfasdfasdf ', job.data); await this.alarmRepository.createAlarm(saveAlarmDto); } @@ -35,4 +31,14 @@ export class SaveAlarmProcessor { console.log(saveAlarmDto, instanceToPlain(saveAlarmDto)); await this.alarmRepository.createAlarm(saveAlarmDto); } + + @Process(ALARM_STORE_TYPE.LIGHTNING_LEVELUP) + async handleLightningLevelUpSaveAlarm(job: Job) { + // job.data + console.log('processor Lightning ', job.data); + + const saveAlarmDto = plainToInstance(SaveAlarmDto, job.data); + console.log(saveAlarmDto, instanceToPlain(saveAlarmDto)); + await this.alarmRepository.createAlarm(saveAlarmDto); + } } diff --git a/src/apis/letter/letter.service.ts b/src/apis/letter/letter.service.ts index 4ce94b3..a41712c 100644 --- a/src/apis/letter/letter.service.ts +++ b/src/apis/letter/letter.service.ts @@ -62,6 +62,7 @@ export class LetterService { senderUserInfo, new UserIdDto(twoUserList.recevier), newLetter, + new LetterRoomIdDto(letterRoom._id), ); return new ResLetterDto( newLetter, diff --git a/src/apis/questions/questions.service.ts b/src/apis/questions/questions.service.ts index 0a7750c..fd58e8e 100644 --- a/src/apis/questions/questions.service.ts +++ b/src/apis/questions/questions.service.ts @@ -185,6 +185,10 @@ export class QuestionsService { commentStringDto, questionIdDto, ); + if (!question) { + throw new BadRequestException('질문 없음'); + } + const room = await this.roomsService.findOneByRoomId( new RoomIdDto(question.room._id), ); @@ -193,6 +197,7 @@ export class QuestionsService { new UserIdDto(question.user._id), room, commentStringDto.comment, + questionIdDto, ); return question.commentList; } diff --git a/src/apis/users/user.controller.ts b/src/apis/users/user.controller.ts index 006cefd..c9d796e 100644 --- a/src/apis/users/user.controller.ts +++ b/src/apis/users/user.controller.ts @@ -13,6 +13,8 @@ import { Delete, UseInterceptors, ClassSerializerInterceptor, + Query, + ValidationPipe, } from '@nestjs/common'; import { ApiBody, @@ -34,6 +36,7 @@ import { SendLightningSuccessDtoResDto } from './dto/sendLigningSuccessDto.res.d import { AlarmShowDto } from '../alarm/dto/alarmShow.dto'; import { AlarmService } from '../alarm/alarm.service'; import { AlarmIdDto } from 'src/common/dtos/AlarmId.dto'; +import { PageLastIdDto } from 'src/common/dtos/PageLastIdDto'; @ApiTags('user') @Controller('user') @@ -85,6 +88,7 @@ export class UserController { getMyBlockUser(@ReqUser() user: User) { return this.userService.getMyBlockUser(user.userIdDto); } + // @ApiOperation({ summary: '상대방 유저정보를 가져온다.' }) @ApiResponse({ @@ -193,43 +197,4 @@ export class UserController { user, ); } - - @ApiOperation({ - summary: '내 알림을 불러온다.', - }) - @Get('noti') - @ApiResponse({ - status: 201, - description: '요청 성공시', - type: [AlarmShowDto], - }) - getMyAllAlarm(@ReqUser() user: User) { - return this.alarmService.getMyAlarms(user.userIdDto); - } - - @ApiOperation({ - summary: '내 알림을 다 보게끔 한다.', - }) - @Patch('noti/watchAll') - @ApiResponse({ - status: 201, - description: '요청 성공시', - type: [AlarmShowDto], - }) - watchAllAlarm(@ReqUser() user: User) { - return this.alarmService.watchAllAlarm(user.userIdDto); - } - - @ApiOperation({ - summary: '내 알림 보는걸로 처리', - }) - @Patch('noti/:alarmId') - @ApiResponse({ - status: 201, - description: '요청 성공시', - type: [AlarmShowDto], - }) - watchOneAlarm(@ReqUser() user: User, @Param() alarmIdDto: AlarmIdDto) { - return this.alarmService.watchAlarm(user.userIdDto, alarmIdDto); - } } diff --git a/src/apis/users/user.service.ts b/src/apis/users/user.service.ts index b064e60..0ed6214 100644 --- a/src/apis/users/user.service.ts +++ b/src/apis/users/user.service.ts @@ -215,19 +215,19 @@ export class UserService { switch (addUserScore.lightningScore) { case USER_LEVELUP_COUNT_TYPE.LEVEL1: await Promise.all([ - this.alarmService.handleLevelUpAlarm(), + this.alarmService.handleLevelUpAlarm(receive, '1'), this.userRepository.levelUpUser(receive, USER_LEVEL_TYPE.LEVEL1), ]); break; case USER_LEVELUP_COUNT_TYPE.LEVEL2: await Promise.all([ - this.alarmService.handleLevelUpAlarm(), + this.alarmService.handleLevelUpAlarm(receive, '2'), this.userRepository.levelUpUser(receive, USER_LEVEL_TYPE.LEVEL2), ]); break; case USER_LEVELUP_COUNT_TYPE.LEVEL3: await Promise.all([ - this.alarmService.handleLevelUpAlarm(), + this.alarmService.handleLevelUpAlarm(receive, '3'), this.userRepository.levelUpUser(receive, USER_LEVEL_TYPE.LEVEL3), ]); break; diff --git a/src/app.module.ts b/src/app.module.ts index f6a552c..73bec9d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -14,6 +14,7 @@ import { QuestionsModule } from './apis/questions/questions.module'; import { AlarmModule } from './apis/alarm/alarm.module'; import mongooseLeanDefaults from 'mongoose-lean-defaults'; import { BullModule } from '@nestjs/bull'; +import { FcmModule } from './fcm/fcm.module'; @Module({ imports: [ @@ -48,6 +49,7 @@ import { BullModule } from '@nestjs/bull'; LetterModule, QuestionsModule, AlarmModule, + FcmModule, ], providers: [ { diff --git a/src/common/consts/enum.ts b/src/common/consts/enum.ts index 7a0afda..04712bf 100644 --- a/src/common/consts/enum.ts +++ b/src/common/consts/enum.ts @@ -153,6 +153,7 @@ enum ALARM_STORE_TYPE { COMMENT = 'comment', // 번개 줬을 떄 LIGHTNING = 'lightning', + LIGHTNING_LEVELUP = 'lightningLevelUp', // 번개 라이트닝 레벨업? // LIGHTNING = 'lightning', @@ -163,7 +164,10 @@ enum ALARM_STORE_TYPE { const PUSH_ALARM = 'pushAlarm'; const SAVE_ALARM = 'saveAlarm'; +const DEEPLINK_BASEURL = 'tiquitaca-app://navigation/'; + export { + DEEPLINK_BASEURL, PUSH_ALARM_TYPE, ALARM_STORE_TYPE, PUSH_ALARM, diff --git a/src/common/decorators/MongoIdTransfrom.ts b/src/common/decorators/MongoIdTransfrom.ts new file mode 100644 index 0000000..0520a80 --- /dev/null +++ b/src/common/decorators/MongoIdTransfrom.ts @@ -0,0 +1,20 @@ +import { ExposeOptions, Transform } from 'class-transformer'; +import * as mongoose from 'mongoose'; +import { Types } from 'mongoose'; + +export const failToConvertMongoId = 'mongoIdCheckFail'; +/** + * 몽고 아이디 (기댓값을 받아) 비정상일경우 null 리턴 , 아닐경우 transform + * @param fieldName + * @param options + * @returns null | mongoIdObject + */ +export const MongoIdTransfrom = + (options?: ExposeOptions) => (target, propertyKey) => { + Transform((value) => { + if (!mongoose.isValidObjectId(value.obj[propertyKey])) + return failToConvertMongoId; + return new Types.ObjectId(value.obj[propertyKey]); + }, options)(target, propertyKey); + }; +// @Transform((value) => value.obj._id.toString()) diff --git a/src/common/decorators/MongoIdValidationTransfrom.decorator.ts b/src/common/decorators/MongoIdValidationTransfrom.decorator.ts new file mode 100644 index 0000000..c2910c0 --- /dev/null +++ b/src/common/decorators/MongoIdValidationTransfrom.decorator.ts @@ -0,0 +1,39 @@ +import { applyDecorators } from '@nestjs/common'; +import { ApiConflictResponse, ApiCreatedResponse } from '@nestjs/swagger'; +import { ExposeOptions } from 'class-transformer'; +import { Equals, IsNotEmpty, NotEquals } from 'class-validator'; +import { failToConvertMongoId, MongoIdTransfrom } from './MongoIdTransfrom'; +import 'reflect-metadata'; +/** + * 몽고 아이디 (기댓값을 받아) 비정상일경우 에러메시지. + * @param fieldName + * @param options + * @returns null | mongoIdObject + */ +export function MongoIdValidationTransfrom(options?: ExposeOptions) { + // console.log('tests'); + return applyDecorators( + // passDecoratedPropertyName(), + MongoIdTransfrom(options), + NotEquals(failToConvertMongoId, { + message: 'MongoId 형식 오류', + }), + ); +} + +// // function second() {} +// const PropertyNameKey = Symbol('PropertyNameKey'); +// function savePropertyName(decoratedPropertyName: string) { +// return Reflect.metadata(PropertyNameKey, decoratedPropertyName); +// } +// function getFormat(target: any, propertyKey: string) { +// return Reflect.getMetadata(PropertyNameKey, target, propertyKey); +// } + +// function passDecoratedPropertyName() { +// console.log('tests'); +// return function (target: any, decoratedPropertyName: string) { +// console.log('second(): factory evaluated', decoratedPropertyName); +// savePropertyName(decoratedPropertyName); +// }; +// } diff --git a/src/common/dtos/AlarmId.dto.ts b/src/common/dtos/AlarmId.dto.ts index e86671a..dee7588 100644 --- a/src/common/dtos/AlarmId.dto.ts +++ b/src/common/dtos/AlarmId.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO */ @@ -20,8 +21,6 @@ export class AlarmIdDto { title: '알람 아이디', description: '알람의 아이디입니다 ', }) - @IsNotEmpty() - @IsObjectId({ message: '알람 아이디가 몽고아이디 형식이 아닙니다.' }) - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) alarmId: Types.ObjectId; } diff --git a/src/common/dtos/CommentId.dto.ts b/src/common/dtos/CommentId.dto.ts index b28e757..d0e2daa 100644 --- a/src/common/dtos/CommentId.dto.ts +++ b/src/common/dtos/CommentId.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO */ @@ -17,8 +18,6 @@ export class CommentIdDto { description: '몽고아이디 형식입니다 . 질문의 댓글의 아이디를 받아옵니다.', // example: '624c24cae25c551b68a6645c', }) - @IsNotEmpty() - @IsObjectId({ message: '질문의 댓글 아이디가 몽고아이디 형식이 아닙니다.' }) - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) commentId: Types.ObjectId; } diff --git a/src/common/dtos/LetterRoomId.dto.ts b/src/common/dtos/LetterRoomId.dto.ts index e5af258..2d6a5fa 100644 --- a/src/common/dtos/LetterRoomId.dto.ts +++ b/src/common/dtos/LetterRoomId.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO */ @@ -17,8 +18,6 @@ export class LetterRoomIdDto { description: '몽고아이디 형식입니다.', // example: '624c24cae25c551b68a6645c', }) - @IsNotEmpty() - @IsObjectId({ message: '쪽지방 아이디가 몽고아이디 형식이 아닙니다.' }) - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) letterRoomId: Types.ObjectId; } diff --git a/src/common/dtos/MongoId.dto.ts b/src/common/dtos/MongoId.dto.ts index a1ab33e..92d0504 100644 --- a/src/common/dtos/MongoId.dto.ts +++ b/src/common/dtos/MongoId.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; /** @@ -11,7 +11,7 @@ export class MongoId { title: '몽고 아이디', description: '몽고아이디 형식입니다.', }) - @IsObjectId({ message: '몽고아이디 형식이 아닙니다.' }) + @IsMongoId({ message: '몽고아이디 형식이 아닙니다.' }) // transform 자동으로 해줌 . main.ts 참고 @Transform(({ value }) => new Types.ObjectId(value)) _id: Types.ObjectId; diff --git a/src/common/dtos/PageLastIdDto.ts b/src/common/dtos/PageLastIdDto.ts new file mode 100644 index 0000000..6b35e8c --- /dev/null +++ b/src/common/dtos/PageLastIdDto.ts @@ -0,0 +1,33 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { + IsISO8601, + IsMongoId, + IsNotEmpty, + IsOptional, + IsString, +} from 'class-validator'; + +import { Types } from 'mongoose'; +import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; +/** + * mongoId 용 DTO + */ +export class PageLastIdDto { + // constructor(lastId: string | Types.ObjectId) { + // if (lastId instanceof Types.ObjectId) { + // this.lastId = lastId; + // } else { + // this.lastId = new Types.ObjectId(lastId); + // } + // } + + @ApiProperty({ + type: String, + title: '마지막 콘텐트의 아이디 _id', + description: 'lastId (커서) 방식으로 페이지 네이션을 합니다.', + required: false, + }) + @MongoIdValidationTransfrom({ toClassOnly: true }) + lastId: Types.ObjectId; +} diff --git a/src/common/dtos/QuestionId.dto.ts b/src/common/dtos/QuestionId.dto.ts index 7347160..ac287aa 100644 --- a/src/common/dtos/QuestionId.dto.ts +++ b/src/common/dtos/QuestionId.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO */ @@ -17,8 +18,6 @@ export class QuestionIdDto { description: '몽고아이디 형식입니다 . 질문의 아이디를 받아옵니다.', example: '624c24cae25c551b68a6645c', }) - @IsNotEmpty() - @IsObjectId({ message: '질문 아이디가 몽고아이디 형식이 아닙니다.' }) - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) questionId: Types.ObjectId; } diff --git a/src/common/dtos/ReportId.dto.ts b/src/common/dtos/ReportId.dto.ts index e1a708e..d641338 100644 --- a/src/common/dtos/ReportId.dto.ts +++ b/src/common/dtos/ReportId.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; /** @@ -22,7 +22,7 @@ export class ReportIdDto { example: '626cf238b51596721c21289b', }) @IsNotEmpty() - @IsObjectId({ message: '유저 아이디가 몽고아이디 형식이 아닙니다.' }) + @IsMongoId({ message: '유저 아이디가 몽고아이디 형식이 아닙니다.' }) @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) reportId: Types.ObjectId; } diff --git a/src/common/dtos/RoomId.dto.ts b/src/common/dtos/RoomId.dto.ts index 1c805a8..17790d4 100644 --- a/src/common/dtos/RoomId.dto.ts +++ b/src/common/dtos/RoomId.dto.ts @@ -1,7 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Expose, Transform } from 'class-transformer'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO @@ -20,8 +21,6 @@ export class RoomIdDto { description: '몽고아이디 형식입니다. (홍익대학교 룸 예시 )', example: '62596e8c4e22b2180fe2a902', }) - @IsObjectId({ message: '룸 아이디 값이 몽고아이디 형식이 아닙니다.' }) - // transform 자동으로 해줌 . main.ts 참고 - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) roomId: Types.ObjectId; } diff --git a/src/common/dtos/UserId.dto.ts b/src/common/dtos/UserId.dto.ts index 01181bc..bcdaf6a 100644 --- a/src/common/dtos/UserId.dto.ts +++ b/src/common/dtos/UserId.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty } from 'class-validator'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsNotEmpty, IsString } from 'class-validator'; +import { IsMongoId } from 'class-validator'; import { Types } from 'mongoose'; import { Transform } from 'class-transformer'; +import { MongoIdValidationTransfrom } from '../decorators/MongoIdValidationTransfrom.decorator'; /** * mongoId 용 DTO */ @@ -21,8 +22,6 @@ export class UserIdDto { description: '몽고아이디 형식입니다. (개발자) ', example: '626cf238b51596721c21289b', }) - @IsNotEmpty() - @IsObjectId({ message: '유저 아이디가 몽고아이디 형식이 아닙니다.' }) - @Transform(({ value }) => new Types.ObjectId(value), { toClassOnly: true }) + @MongoIdValidationTransfrom({ toClassOnly: true }) userId: Types.ObjectId; } diff --git a/src/fcm/fcm.module.ts b/src/fcm/fcm.module.ts new file mode 100644 index 0000000..fc9f3c2 --- /dev/null +++ b/src/fcm/fcm.module.ts @@ -0,0 +1,38 @@ +import { Global, Module, DynamicModule, Logger } from '@nestjs/common'; + +import { ValueProvider } from '@nestjs/common/interfaces/modules/provider.interface'; +import * as firebaseAdmin from 'firebase-admin'; +import { FcmService } from './fcm.service'; +import { FcmOptions } from './fcmOptions.interface'; +import { FCM_ADMIN, FCM_OPTIONS } from './fcmAdminProvider'; + +@Module({}) +export class FcmModule { + static forRoot(options: FcmOptions): DynamicModule { + // const optionsProvider: ValueProvider = { + // provide: FCM_OPTIONS, + // useValue: options, + // }; + + const credentialFactory = { + provide: FCM_ADMIN, + useFactory: () => { + //error can be occur in this section + return firebaseAdmin.initializeApp({ + credential: firebaseAdmin.credential.cert(options.credentialPath), + }); + }, + }; + const logger = options.logger ? options.logger : new Logger('FcmService'); + + return { + module: FcmModule, + providers: [ + { provide: Logger, useValue: logger }, + FcmService, + credentialFactory, + ], + exports: [FcmService], + }; + } +} diff --git a/src/fcm/fcm.service.spec.ts b/src/fcm/fcm.service.spec.ts new file mode 100644 index 0000000..5d88d46 --- /dev/null +++ b/src/fcm/fcm.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { FcmService } from './fcm.service'; + +describe('FcmService', () => { + let service: FcmService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [FcmService], + }).compile(); + + service = module.get(FcmService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/fcm/fcm.service.ts b/src/fcm/fcm.service.ts new file mode 100644 index 0000000..5ff604b --- /dev/null +++ b/src/fcm/fcm.service.ts @@ -0,0 +1,65 @@ +import { Inject, Injectable, Logger } from '@nestjs/common'; +import * as firebaseAdmin from 'firebase-admin'; +import { SendPushAlarmSubDto } from 'src/apis/alarm/dto/sendPushAlarm.sub.dto'; +import { FCM_ADMIN } from './fcmAdminProvider'; +// firebaseAdmin.app.App; + +@Injectable() +export class FcmService { + constructor( + @Inject(FCM_ADMIN) private fcmAdmin: firebaseAdmin.app.App, + private readonly logger: Logger, + ) {} + + async sendNotification( + deviceIds: Array, + sendPushAlarmDto: SendPushAlarmSubDto, + ) { + if (deviceIds.length == 0) { + throw new Error('You provide an empty device ids list!'); + } + + // const options = { + // priority: 'high', + // timeToLive: 60 * 60 * 24, + // }; + + // const optionsSilent = { + // priority: 'high', + // timeToLive: 60 * 60 * 24, + // content_available: true, + // }; + console.log(sendPushAlarmDto.deepLink); + const fcmPushMessage = { + notification: { + title: sendPushAlarmDto.title, + body: sendPushAlarmDto.body, + }, + data: { + deepLink: sendPushAlarmDto.deepLink, + }, + tokens: deviceIds, + apns: { + headers: { + 'apns-priority': '5', + }, + payload: { + aps: { + 'mutable-content': 1, + sound: 'default', + }, + }, + }, + }; + + let result = null; + try { + result = await this.fcmAdmin.messaging().sendMulticast(fcmPushMessage); + // console.log(result); + } catch (error) { + this.logger.error(error.message, error.stackTrace, 'nestjs-fcm'); + throw error; + } + return result; + } +} diff --git a/src/fcm/fcmAdminProvider.ts b/src/fcm/fcmAdminProvider.ts new file mode 100644 index 0000000..0155a86 --- /dev/null +++ b/src/fcm/fcmAdminProvider.ts @@ -0,0 +1,2 @@ +export const FCM_ADMIN = 'FCM_ADMIN'; +export const FCM_OPTIONS = 'FCM_OPTIONS'; diff --git a/src/fcm/fcmOptions.interface.ts b/src/fcm/fcmOptions.interface.ts new file mode 100644 index 0000000..5e52569 --- /dev/null +++ b/src/fcm/fcmOptions.interface.ts @@ -0,0 +1,9 @@ +import { Logger } from '@nestjs/common'; + +export interface FcmOptions { + /** + * 파이어베이스 인증 주소 + */ + credentialPath: string; + logger?: any; +} diff --git a/src/main.ts b/src/main.ts index b720c34..be84450 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,22 +11,22 @@ async function bootstrap() { app.setViewEngine('hbs'); + setupSwagger(app); + //앱서버용 + app.getHttpAdapter().getInstance().set('etag', false); + app.enableCors({ origin: true, credentials: true }); + app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); + app.useGlobalInterceptors(new SuccessInterceptor()); app.useGlobalPipes( new ValidationPipe({ // transform으로 형식변환가능한지 체크 dto에 transfrom 없어도 typescript type 보고 형변환 해줌 // enableImplicitConversion 옵션은 타입스크립트의 타입으로 추론가능하게 설정함 transform: true, transformOptions: { enableImplicitConversion: true }, + // forbidNonWhitelisted: true, }), ); - setupSwagger(app); - //앱서버용 - app.getHttpAdapter().getInstance().set('etag', false); - app.enableCors({ origin: true, credentials: true }); - app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); - app.useGlobalInterceptors(new SuccessInterceptor()); - const PORT = process.env.PORT; await app.listen(PORT); diff --git a/src/models/alarm.model.ts b/src/models/alarm.model.ts index c3d119a..aaed82d 100644 --- a/src/models/alarm.model.ts +++ b/src/models/alarm.model.ts @@ -57,7 +57,6 @@ export class Alarm { roomName: string; @Prop({ - required: true, default: '', type: String, }) @@ -95,6 +94,11 @@ export class Alarm { enum: ALARM_STORE_TYPE, }) alarmType: string; + + @Prop({ + type: String, + }) + questionId: string; } export const AlarmSchema = SchemaFactory.createForClass(Alarm); diff --git a/src/models/chat.model.ts b/src/models/chat.model.ts index 5c81eed..62558c4 100644 --- a/src/models/chat.model.ts +++ b/src/models/chat.model.ts @@ -2,7 +2,7 @@ import { Socket } from 'socket.io'; import { IsBoolean, IsNotEmpty, IsString, IsEnum } from 'class-validator'; import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { Document, ObjectId, Types } from 'mongoose'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import * as mongoose from 'mongoose'; import { CHAT_TYPE } from 'src/common/consts/enum'; import { Room } from './room.model'; @@ -25,7 +25,7 @@ export class Chat extends Document { sender: Socket; @Prop({ required: true, type: mongoose.Schema.Types.ObjectId, ref: 'room' }) - @IsObjectId() + @IsMongoId() room: Room; @Prop({ diff --git a/src/models/forbidden.model.ts b/src/models/forbidden.model.ts index 2fa0f14..0dc5834 100644 --- a/src/models/forbidden.model.ts +++ b/src/models/forbidden.model.ts @@ -1,7 +1,7 @@ import { IsBoolean, IsNotEmpty, IsString, IsEnum } from 'class-validator'; import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { Document, Types } from 'mongoose'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { User } from './user.model'; const options: SchemaOptions = { diff --git a/src/models/letter.model.ts b/src/models/letter.model.ts index 7ff3492..67a76fe 100644 --- a/src/models/letter.model.ts +++ b/src/models/letter.model.ts @@ -1,7 +1,7 @@ import { IsArray, IsBoolean, IsNotEmpty, IsString } from 'class-validator'; import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { User } from './user.model'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Document, Types, Schema as MongooseSchema } from 'mongoose'; import { ApiProperty } from '@nestjs/swagger'; @@ -17,12 +17,12 @@ export class Letter extends Document { type: MongooseSchema.Types.ObjectId, ref: 'LetterRoom', }) - @IsObjectId() + @IsMongoId() letterRoom: Types.ObjectId; //보낸 사람 @Prop({ required: true, type: MongooseSchema.Types.ObjectId, ref: 'User' }) - @IsObjectId() + @IsMongoId() sender: User; // 보일 수 있는 유저.. 채팅방 나가면 없애버리는거임 diff --git a/src/models/letterRoom.model.ts b/src/models/letterRoom.model.ts index c655ef5..b767ee9 100644 --- a/src/models/letterRoom.model.ts +++ b/src/models/letterRoom.model.ts @@ -1,6 +1,6 @@ import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { User } from './user.model'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { Document, Schema as MongooseSchema } from 'mongoose'; import { IsArray } from 'class-validator'; import { Letter } from './letter.model'; diff --git a/src/models/question.model.ts b/src/models/question.model.ts index ada2960..2ddcab6 100644 --- a/src/models/question.model.ts +++ b/src/models/question.model.ts @@ -2,7 +2,7 @@ import { Chat } from './chat.model'; import { Room } from './room.model'; import { IsNotEmpty, IsObject, IsString, IsArray } from 'class-validator'; import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { User } from './user.model'; import { ApiProperty } from '@nestjs/swagger'; import { TransformObjectIdToString } from 'src/common/decorators/Expose.decorator'; @@ -48,7 +48,7 @@ export class Comment { type: Types.ObjectId, ref: User.name, }) - @IsObjectId() + @IsMongoId() @Type(() => UserProfileDto) @Expose() user: User; @@ -77,7 +77,7 @@ export class Question { _id: Types.ObjectId; @Prop({ required: true, type: Types.ObjectId }) - @IsObjectId() + @IsMongoId() @Exclude() room: Room; @@ -90,7 +90,7 @@ export class Question { type: Types.ObjectId, ref: User.name, }) - @IsObjectId() + @IsMongoId() @Type(() => UserProfileDto) @Expose() user: User; @@ -108,7 +108,7 @@ export class Question { required: true, type: Types.ObjectId, }) - @IsObjectId() + @IsMongoId() @Exclude() chat: Chat; diff --git a/src/models/report.model.ts b/src/models/report.model.ts index 12ed7f9..4325ee5 100644 --- a/src/models/report.model.ts +++ b/src/models/report.model.ts @@ -1,7 +1,7 @@ import { IsBoolean, IsNotEmpty, IsString, IsEnum } from 'class-validator'; import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { Document, Types } from 'mongoose'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { User } from './user.model'; const options: SchemaOptions = { @@ -12,11 +12,11 @@ const options: SchemaOptions = { @Schema(options) export class Report extends Document { @Prop({ required: true, type: Types.ObjectId, ref: 'user' }) - @IsObjectId() + @IsMongoId() reporter: User; @Prop({ required: true, type: Types.ObjectId, ref: 'user' }) - @IsObjectId() + @IsMongoId() reportedUser: User; } diff --git a/src/models/user.model.ts b/src/models/user.model.ts index ba34674..5c3b670 100644 --- a/src/models/user.model.ts +++ b/src/models/user.model.ts @@ -12,7 +12,7 @@ import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose'; import { Document } from 'mongoose'; import { STATUS_TYPE } from 'src/common/consts/enum'; import { Room } from './room.model'; -import { IsObjectId } from 'class-validator-mongo-object-id'; +import { IsMongoId } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { Exclude, Expose, Transform, Type } from 'class-transformer'; import { Types } from 'mongoose'; @@ -116,7 +116,7 @@ export class User { }) @Type(() => ResShortCutRoomDto) @Prop({ type: Types.ObjectId, ref: 'Room' }) - @IsObjectId() + @IsMongoId() @Expose() myRoom: Room; @@ -143,7 +143,7 @@ export class User { chatAlarm: boolean; @Prop({ type: [{ type: Types.ObjectId, ref: User.name }] }) - @IsObjectId() + @IsMongoId() @Exclude() blockedUsers: Types.ObjectId[]; @@ -154,7 +154,7 @@ export class User { @Prop({ type: [{ type: Types.ObjectId, ref: User.name }], }) - @IsObjectId() + @IsMongoId() @Type(() => UserProfileDto) @Expose() iBlockUsers: UserProfileDto[]; diff --git a/src/repositories/alarm.repository.ts b/src/repositories/alarm.repository.ts index db92e18..9c08341 100644 --- a/src/repositories/alarm.repository.ts +++ b/src/repositories/alarm.repository.ts @@ -7,6 +7,7 @@ import { Alarm } from 'src/models/alarm.model'; import { SaveAlarmDto } from 'src/apis/alarm/dto/saveAlarm.dto'; import { instanceToPlain } from 'class-transformer'; import { AlarmIdDto } from 'src/common/dtos/AlarmId.dto'; +import { PageLastIdDto } from 'src/common/dtos/PageLastIdDto'; @Injectable() export class AlarmRepository { @@ -20,8 +21,30 @@ export class AlarmRepository { return await alarm.save(); } - async findAlarmByUserId(userIdDto: UserIdDto): Promise { - return await this.AlarmModel.find({ user: userIdDto.userId }); + async findAlarmByUserIdFirst( + userIdDto: UserIdDto, + limitCount: number, + ): Promise { + console.log(userIdDto); + return await this.AlarmModel.find({ user: userIdDto.userId }) + .sort({ createdAt: -1 }) + .limit(limitCount) + .lean(); + } + + async findAlarmByUserIdAndLastId( + userIdDto: UserIdDto, + lastIdDto: PageLastIdDto, + limitCount: number, + ): Promise { + console.log(userIdDto); + return await this.AlarmModel.find({ + user: userIdDto.userId, + _id: { $lt: lastIdDto.lastId }, + }) + .sort({ createdAt: -1 }) + .limit(limitCount) + .lean(); } async watchOneAlarm( @@ -30,14 +53,14 @@ export class AlarmRepository { ): Promise { return await this.AlarmModel.findOneAndUpdate( { _id: alarmIdDto.alarmId, user: userIdDto.userId }, - { watch: true }, + { iWatch: true }, ); } async watchAllAlarm(userIdDto: UserIdDto) { await this.AlarmModel.updateMany( { user: userIdDto.userId }, - { watch: true }, + { iWatch: true }, ); } } diff --git a/src/repositories/room.repository.ts b/src/repositories/room.repository.ts index 76f8ed4..8e02d06 100644 --- a/src/repositories/room.repository.ts +++ b/src/repositories/room.repository.ts @@ -8,6 +8,10 @@ import { RoomIdDto } from 'src/common/dtos/RoomId.dto'; import { CoordinatesDto } from 'src/apis/rooms/dto/coordinates.dto'; import { FindRoomDto } from 'src/apis/rooms/dto/find-room.dto'; import { UserProfileSelect } from 'src/common/dtos/UserProfile.dto'; +import { + UserFcmInfoDto, + userFcmInfoSelect, +} from 'src/apis/alarm/dto/userFcmInfo.dto'; @Injectable() export class RoomRepository { @@ -244,4 +248,20 @@ export class RoomRepository { return rooms; } + + async getUserAlarmInfoInRoom(roomIdDto: RoomIdDto) { + const room = await this.roomModel + .findOne({ + _id: roomIdDto.roomId, + }) + .populate({ + path: 'userList', + select: userFcmInfoSelect, + }) + .lean({ defaults: true }); + const userFcmInfoList = room.userList + ? (room.userList as unknown as UserFcmInfoDto[]) + : []; + return { userFcmInfoList: userFcmInfoList, roomName: room.name }; + } } diff --git a/src/repositories/user.repository.ts b/src/repositories/user.repository.ts index e7b4cb9..b519a60 100644 --- a/src/repositories/user.repository.ts +++ b/src/repositories/user.repository.ts @@ -16,6 +16,11 @@ import { UpdateProfileReqDto } from 'src/apis/users/dto/updateUserDto.req.dto'; import { UserProfileSelect } from 'src/common/dtos/UserProfile.dto'; import { ResShortCutRoomDto } from 'src/common/dtos/shortCutRoomInfo.res.dto'; import { STATUS_TYPE, USER_LEVEL_TYPE } from 'src/common/consts/enum'; +import { + UserFcmInfoDto, + userFcmInfoSelect, +} from 'src/apis/alarm/dto/userFcmInfo.dto'; +import { Types } from 'mongoose'; @Injectable() export class UserRepository { @@ -399,4 +404,13 @@ export class UserRepository { { new: true }, ); } + + async findUserFcmToken( + userIdArray: Types.ObjectId[], + ): Promise { + return await this.userModel + .find({ _id: { $in: userIdArray } }) + .select(userFcmInfoSelect) + .lean({ defaults: true }); + } }