From 4ab9ccdd654d3fb846e31d59c9937573249bf458 Mon Sep 17 00:00:00 2001 From: Will Roberts Date: Tue, 16 Aug 2022 21:07:45 -0400 Subject: [PATCH 1/4] Updates Firebase on servers and workers --- .gitignore | 7 +- README.md | 24 +- config/config.js | 61 +- config/development.json | 2 - config/production.json | 2 - docker-compose.yaml | 67 +- docker/start | 8 +- gulp/bundler.js | 2 +- gulp/bundler.register.js | 2 +- package.json | 17 +- server/game.coffee | 5 +- server/lib/duelyst_firebase_module.coffee | 81 +- server/lib/firebase_promises.coffee | 4 +- server/middleware/signed_in.coffee | 3 +- server/routes/api/me/spectate.coffee | 4 +- server/routes/session.coffee | 9 +- server/routes/utility.coffee | 1 - server/single_player.coffee | 16 +- test/integration/firebase/server_client.js | 73 ++ test/unit/firebase/server_client.js | 27 + test/unit/misc/duelyst_firebase.js | 97 --- yarn.lock | 842 +++++++++++++++++++-- 22 files changed, 1074 insertions(+), 280 deletions(-) create mode 100644 test/integration/firebase/server_client.js create mode 100644 test/unit/firebase/server_client.js delete mode 100644 test/unit/misc/duelyst_firebase.js diff --git a/.gitignore b/.gitignore index 2b939b13b..187adbf9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +# Secrets +.env +.env_for_alpha +serviceAccountKey.json + # Build artifacts /app/data/packages.js /app/localization/locales/en/index.json @@ -8,8 +13,6 @@ node_modules *.log *.log.txt dump.rdb -.env -.env_for_alpha .foreman .idea/ .node-version diff --git a/README.md b/README.md index 2c0b3db5b..340eaa5b3 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,10 @@ Worker: #### Other Dependencies +Firebase: + +- Client code can be found in `app` (see `new Firebase()` calls) and `server/lib/duelyst_firebase_module.coffee`, and configuration can be found in `config/` + Postgres: - Client code can be found in `server/lib/data_access/knex.coffee` and `server/knexfile.js`, and configuration can be found in `config/` @@ -64,9 +68,9 @@ Consul: #### Building the code -Install NPM tools: +Install some NPM tools (can use `sudo` on Mac/Linux): ``` -npm install -g typescript yarn gulpjs/gulp-cli +npm install -g typescript yarn ``` Compile TypeScript dependencies: @@ -97,11 +101,13 @@ When working in the `server` or `worker` directories, no rebuilds are needed. Se #### Starting a test environment in Docker -- Modify `development.json` with: - - Firebase Realtime endpoint and secret - - Redis connection string - - Postgres connection string -- Optionally enable debug logging for sockets by prepending `yarn $1` with `DEBUG=*` in `docker/start` +- Create a Firebase Realtime Database + - This is a Google Cloud product, and they offer a no-cost "Spark" plan + - Set the `FIREBASE_URL` environment variable in an `.env` file in the repo root + - For example, `FIREBASE_URL=https://my-example-project.firebaseio.com/` + - Create a new service account with r/w access to your realtime DB + - Create a new JSON key for the service account, and store it in a `serviceAccountKey.json` file in the repo root +- Optionally enable debug logging for WebSockets by prepending `yarn $1` with `DEBUG=*` in `docker/start` - Use `docker compose up` to start required services locally, or start individual services: - `redis` - `db` (Postgres) @@ -117,11 +123,11 @@ When working in the `server` or `worker` directories, no rebuilds are needed. Se - In another terminal window, use `NODE_ENV=development yarn migrate:latest` to run database migrations - On Windows: `$env:NODE_ENV = 'development'; yarn migrate:latest` - Only need to run this once (unless you change Postgres schema) -- Open http://localhost:3000 in a browser to load the game client +- Once you see `Duelyst 'development' started on port 3000` in the logs, open http://localhost:3000 in a browser to load the game client #### Starting individual components - `yarn api` to start api server - `yarn game` to start game server - `yarn sp` to start single player game server -- `yarn worker` to start worker \ No newline at end of file +- `yarn worker` to start worker diff --git a/config/config.js b/config/config.js index 04fc6aac8..bb9b50fa3 100644 --- a/config/config.js +++ b/config/config.js @@ -35,37 +35,36 @@ var config = convict({ env: "API_URL" }, firebase: { - doc: "Firebase URL.", - // format: "url", - default: "https://duelyst-local.firebaseio.com/", - env: "FIREBASE_URL" - }, - firebaseToken: { - doc: "Firebase security token.", - default: "", - env: "FIREBASE_TOKEN" - }, - firebaseLoggingEnabled: { - doc: "Firebase logging enabled flag.", - default: false, - env: "FIREBASE_LOGGING" - }, - auth: { - doc: "Firebase URL for auth service", - // format: "url", - default: "", // "https://duelyst-dev-auth.firebaseio.com/" - env: "AUTH_URL" - }, - authToken: { - doc: "Firebase auth token.", - default: "", // "" - env: "AUTH_TOKEN" + url: { + doc: "Firebase URL, e.g. https://my-duelyst-project-12345.firebaseio.com/", + // format: "url", + default: "", + env: "FIREBASE_URL" + }, + authServiceUrl: { + doc: "Firebase URL for auth service", + // format: "url", + default: "", + env: "FIREBASE_AUTH_URL" + }, + loggingEnabled: { + doc: "Enable logging in the Firebase Admin SDK.", + default: false, + env: "FIREBASE_LOGGING_ENABLED" + } }, - tokenExpiration: { - doc: "Time (in minutes) before tokens expire.", - format: "int", - default: 60 * 24 * 14, // 14 days in minutes - env: "TOKEN_EXPIRES" + jwt: { + signingSecret: { + doc: "The secret used when signing JSON Web Tokens", + default: "duelyst", // Set in .env + env: "JWT_SECRET" + }, + tokenExpiration: { + doc: "Time (in minutes) before tokens expire.", + format: "int", + default: 60 * 24 * 14, // 14 days in minutes + env: "TOKEN_EXPIRES" + }, }, cdn: { doc: "CDN / S3 url. Default is blank.", @@ -431,7 +430,7 @@ config.version = require('../version').version var pgUrl = url.parse(config.get('postgres_connection_string')); console.log("CONFIG: version:"+config.version) console.log("CONFIG: env:"+config.get('env')) -console.log("CONFIG: firebase:"+url.parse(config.get('firebase')).host) +console.log("CONFIG: firebase:"+url.parse(config.get('firebase.url')).host) console.log("CONFIG: postgres:"+pgUrl.host+pgUrl.pathname) console.log("CONFIG: redis:"+config.get('redis.ip')) // console.log("CONFIG: paypal_buttons:",config.get('paypalButtons')) diff --git a/config/development.json b/config/development.json index 5f4ccf0e4..3adea2aae 100644 --- a/config/development.json +++ b/config/development.json @@ -2,8 +2,6 @@ "env": "development", "api": "http://localhost:3000", "postgres_connection_string": "postgres://duelyst:duelyst@0.0.0.0:5431/duelyst", - "firebase": "https://duelyst-development.firebaseio.com/", - "firebaseToken": "K4EkQWIT9UrTATVW9h0dHhf8t1nvGVjWMi8rPHb2", "redis": { "ip": "localhost", "port": 6379, diff --git a/config/production.json b/config/production.json index 4c2803bed..b368ea166 100644 --- a/config/production.json +++ b/config/production.json @@ -1,8 +1,6 @@ { "env": "production", "api": "", - "firebase": "", - "firebaseToken": "", "cdn": "", "s3_url":"", "consul": { diff --git a/docker-compose.yaml b/docker-compose.yaml index cc10e4af2..ee64daade 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,12 +2,6 @@ version: "3.9" x-base-service: &base image: node:lts - environment: - REDIS_IP: redis - POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" - depends_on: - - db - - redis entrypoint: bash working_dir: /app volumes: @@ -19,6 +13,7 @@ services: image: "redis" ports: - "6379:6379" + db: image: postgres restart: always @@ -30,6 +25,7 @@ services: - 5431:5432 volumes: - ./.pgdata:/var/lib/postgresql/data + adminer: image: adminer profiles: @@ -37,12 +33,23 @@ services: restart: always ports: - 8080:8080 + environment: + POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + depends_on: + - db api: <<: *base ports: - 3000:3000 + environment: + REDIS_IP: redis + POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + FIREBASE_URL: ${FIREBASE_URL} command: docker/start api + depends_on: + - db + - redis game: <<: *base @@ -50,19 +57,36 @@ services: - donotstart ports: - 8000:8000 + environment: + REDIS_IP: redis + FIREBASE_URL: ${FIREBASE_URL} command: docker/start game + depends_on: + - redis sp: <<: *base ports: - 8000:8000 + environment: + REDIS_IP: redis + FIREBASE_URL: ${FIREBASE_URL} command: docker/start sp + depends_on: + - redis worker: <<: *base ports: - 3002:8080 + environment: + REDIS_IP: redis + POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + FIREBASE_URL: ${FIREBASE_URL} command: docker/start worker + depends_on: + - db + - redis worker-ui: <<: *base @@ -71,6 +95,8 @@ services: ports: - 3001:3000 command: docker/start worker-ui + depends_on: + - worker migrate: image: node:lts @@ -85,5 +111,30 @@ services: working_dir: /app volumes: - .:/app - entrypoint: "bash -c" - command: "yarn install --dev && yarn migrate:latest" + command: docker/start migrate:latest + + test-unit: + <<: *base + profiles: + - donotstart + environment: + REDIS_IP: redis + POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + FIREBASE_URL: ${FIREBASE_URL} + command: docker/start test:unit + depends_on: + - db + - redis + + test-integration: + <<: *base + profiles: + - donotstart + environment: + REDIS_IP: redis + POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + FIREBASE_URL: ${FIREBASE_URL} + command: docker/start test:integration + depends_on: + - db + - redis diff --git a/docker/start b/docker/start index e15b8ba01..4241e6f74 100644 --- a/docker/start +++ b/docker/start @@ -1,5 +1,11 @@ #!/usr/bin/env bash + +# Work around git vs https issue for old packages. +git config --global url."https://github.com/".insteadOf git@github.com: +git config --global url."https://".insteadOf git:// + +# Install dependencies yarn install --dev # To enable socket debug logs, prepend this command with DEBUG=* -yarn $1 \ No newline at end of file +yarn $1 diff --git a/gulp/bundler.js b/gulp/bundler.js index 63a6ca943..5304f08e1 100644 --- a/gulp/bundler.js +++ b/gulp/bundler.js @@ -63,7 +63,7 @@ bundler.transform(envify({ NODE_ENV: env, VERSION: version, API_URL: config.get('api'), - FIREBASE_URL: config.get('firebase'), + FIREBASE_URL: config.get('firebase.url'), AMI_ID: config.get('amaId'), MARKETING_AMA_ID: config.get('marketingAmaId'), STRIPE_CLIENT_KEY: config.get('stripeClientKey'), diff --git a/gulp/bundler.register.js b/gulp/bundler.register.js index 9756ced39..50d0c18d4 100644 --- a/gulp/bundler.register.js +++ b/gulp/bundler.register.js @@ -55,7 +55,7 @@ bundler.transform(envify({ NODE_ENV: env, VERSION: version, API_URL: config.get('api'), - FIREBASE_URL: config.get('firebase'), + FIREBASE_URL: config.get('firebase.url'), AMI_ID: config.get('amaId'), MARKETING_AMA_ID: config.get('marketingAmaId'), STRIPE_CLIENT_KEY: config.get('stripeClientKey'), diff --git a/package.json b/package.json index 728de3740..aee530000 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "@counterplay/chromajs": "./packages/chroma-js", "@counterplay/exception-reporter": "./packages/exception-reporter", "@counterplay/warlock": "./packages/warlock", + "@firebase/app-types": "^0.7.0", "@thream/socketio-jwt": "^3.0.0", "analytics-node": "*", "app-module-path": "^1.0.6", @@ -28,6 +29,7 @@ "express-real-ip": "^1.0.0", "fb": "^2.0.0-alpha1", "firebase": "2.0.3", + "firebase-admin": "^11.0.1", "form-urlencoded": "^1.2.1", "gamecenter-identity-verifier": "^0.1.1", "glicko2": "^0.8.4", @@ -159,7 +161,6 @@ "mailchimp": "1.1.0", "minimist": "^1.2.0", "mocha": "^2.4.5", - "mockfirebase": "^0.3.0", "ncp": "^2.0.0", "power-assert": "^1.4.1", "progress": "1.1.8", @@ -183,7 +184,6 @@ "sp": "node ./bin/single_player", "worker": "node ./bin/worker", "worker-ui": "node ./bin/workerui", - "build:app": "node --max_old_space_size=2048 --stack-size=100000 node_modules/gulp/bin/gulp.js build:app --watch=false", "build:desktop": "node --max_old_space_size=2048 --stack-size=100000 node_modules/gulp/bin/gulp.js desktop:build", "build:release": "node --max_old_space_size=2048 --stack-size=100000 node_modules/gulp/bin/gulp.js build:release", @@ -199,11 +199,14 @@ "push:master": "gulp git:master:patch", "push:staging": "gulp git:staging", "rsx:copy": "gulp rsx:copy", - "test:all": "mocha -t 10000", - "test:data": "mocha test/unit/data_access --recursive -t 15000", - "test:misc": "mocha test/unit/misc --recursive -t 5000", - "test:sdk": "mocha test/unit/sdk --recursive -t 5000", - "test": "mocha", + "test:achievements": "mocha -t 100000 --recursive test/unit/achievements", + "test:data": "mocha -t 15000 --recursive test/unit/data_access", + "test:firebase": "mocha -t 1000 test/unit/firebase test/integration/firebase", + "test:misc": "mocha -t 5000 --recursive test/unit/misc", + "test:sdk": "mocha -t 5000 --recursive test/unit/sdk", + "test:unit": "mocha -t 10000 --recursive test/unit", + "test:integration": "mocha -t 10000 --recursive test/integration", + "test": "mocha -t 10000", "watch": "node --max_old_space_size=2048 --stack-size=100000 node_modules/gulp/bin/gulp.js build" }, "xo": { diff --git a/server/game.coffee b/server/game.coffee index 3dc4d411c..e6dac3356 100644 --- a/server/game.coffee +++ b/server/game.coffee @@ -27,7 +27,6 @@ Consul = require './lib/consul' # Configuration object config = require '../config/config.js' env = config.get('env') -firebaseToken = config.get('firebaseToken') # Boots up a basic HTTP server on port 8080 # Responds to /health endpoint with status 200 @@ -77,7 +76,7 @@ io = require('socket.io')().listen(server, { }) io.use( ioJwt.authorize( - secret:firebaseToken + secret: config.get('jwt.signingSecret'), timeout: 15000 ) ) @@ -309,7 +308,7 @@ onGameSpectatorJoin = (requestData) -> # verify - synchronous try - spectateToken = jwt.verify(requestData.spectateToken, firebaseToken) + spectateToken = jwt.verify(requestData.spectateToken, config.get('jwt.signingSecret')) catch error Logger.module("IO").error "[G:#{gameId}]", "spectate_game -> ERROR decoding spectate token: #{error?.message}".red diff --git a/server/lib/duelyst_firebase_module.coffee b/server/lib/duelyst_firebase_module.coffee index 4924c16e1..eb62be5c3 100644 --- a/server/lib/duelyst_firebase_module.coffee +++ b/server/lib/duelyst_firebase_module.coffee @@ -1,65 +1,70 @@ Promise = require 'bluebird' -Firebase = require 'firebase' -Logger = require '../../app/common/logger.coffee' +firebaseAdmin = require 'firebase-admin' colors = require 'colors' moment = require 'moment' util = require 'util' _ = require 'underscore' url = require 'url' -# Configuration object +Logger = require '../../app/common/logger.coffee' config = require '../../config/config.js' - -if config.get('firebaseLoggingEnabled') - Firebase.enableLogging(true) +defaultFirebaseUrl = config.get('firebase.url') +firebaseLoggingEnabled = config.get('firebase.loggingEnabled') +firebaseServiceAccount = require('../../serviceAccountKey.json') class DuelystFirebaseModule - - # Connection objects keyed by URL - @connections: {} + # App objects keyed by URL + @apps: {} # Connect to a Firebase URL, returns connection if already exists - @connect: (firebaseUrl = config.get('firebase'), firebaseToken = config.get('firebaseToken')) -> - parsed = url.parse(firebaseUrl) - key = url.format(parsed) - - # Logger.module("DuelystFirebaseModule").debug "connect() -> connecting to #{key}".magenta + @connect: (firebaseUrl = defaultFirebaseUrl) -> + # Check for an existing connection on this URL. + # TODO: check token expiration, new tokens from callers, etc. + key = url.format(url.parse(firebaseUrl)) + if @apps[key]? + return @apps[key] - # TODO: check token expiration! - # TODO: check for a new token being passed in for same key - if @connections[key]? - # Logger.module("DuelystFirebaseModule").debug "connect() -> existing connection for #{key}".green - return @connections[key] - - @connections[key] = new DuelystFirebaseModule( - key: key - firebaseUrl: firebaseUrl - firebaseToken: firebaseToken + # Create a new connection. + @apps[key] = new DuelystFirebaseModule( + key: key, + firebaseUrl: firebaseUrl, ) # Count current number of connections @getNumConnections: -> - _.size(@connections) + _.size(@apps) # Opens new connections - constructor: ({@key, @firebaseUrl, @firebaseToken}) -> - Logger.module("DuelystFirebaseModule").debug "connect() -> new connection to #{@key}".magenta + constructor: ({@key, @firebaseUrl}) -> + Logger.module('Firebase').log "connect() -> new app connection with db #{@key}" @promise = new Promise (resolve, reject) => - connection = new Firebase(@firebaseUrl) - connection.authWithCustomToken @firebaseToken, (error, result) => - if error? - Logger.module("DuelystFirebaseModule").debug "auth() -> authentication FAILED.".red - return reject(error) - else - Logger.module("DuelystFirebaseModule").debug "auth() -> authentication SUCCESS.".green - @authData = result - @tokenExpires = result.expires - return resolve(connection) + # Validate configuration before attempting to connect. + if @firebaseUrl == '' + return reject(new Error('firebase.url must be set')) + + if firebaseLoggingEnabled + firebaseAdmin.database.enableLogging(true) + + try + app = firebaseAdmin.initializeApp({ + credential: firebaseAdmin.credential.cert(firebaseServiceAccount), + databaseURL: @firebaseUrl + }, @firebaseUrl) + resolve(app) + catch e + return reject(new Error('failed to initialize firebase app: ' + e)) + @promise.catch (error) => - delete DuelystFirebaseModule.connections[@key] + delete DuelystFirebaseModule.apps[@key] # Returns a Promise with the Firebase root reference getRootRef: -> @promise + .then (app) -> + try + db = app.database() + return db.ref() + catch e + Logger.module('Firebase').error "getRootRef: #{e.toString()}" module.exports = DuelystFirebaseModule diff --git a/server/lib/firebase_promises.coffee b/server/lib/firebase_promises.coffee index 28fe51d14..3036eed97 100644 --- a/server/lib/firebase_promises.coffee +++ b/server/lib/firebase_promises.coffee @@ -135,7 +135,7 @@ module.exports.safeTransaction = (ref,updateFn) -> # generate a lexically increasing transaction id tx_id = generatePushId() innerError = null - Logger.module("FB").time("Firebase transaction for /#{ref.key()} (#{tx_id})") + Logger.module("FB").time("Firebase transaction for /#{ref} (#{tx_id})") txUpdateData = (data)-> @@ -161,7 +161,7 @@ module.exports.safeTransaction = (ref,updateFn) -> return data onTxUpdateComplete = (error,committed,snapshot)-> - Logger.module("FB").timeEnd("Firebase transaction for /#{ref.key()} (#{tx_id})") + Logger.module("FB").timeEnd("Firebase transaction for /#{ref} (#{tx_id})") if error reject(error) else if committed and snapshot.val()?.tx_id == tx_id diff --git a/server/middleware/signed_in.coffee b/server/middleware/signed_in.coffee index 60d1a2eb1..d46136514 100644 --- a/server/middleware/signed_in.coffee +++ b/server/middleware/signed_in.coffee @@ -4,7 +4,6 @@ compose = require('compose-middleware').compose t = require 'tcomb-validation' validators = require '../validators' config = require '../../config/config' -firebaseToken = config.get('firebaseToken') ### Any route that requires authentication can use this middleware @@ -13,7 +12,7 @@ Then ensure both an ID and maybe(EMAIL) are present in the JWT payload We can add additional checks to the JWT payload here ### module.exports = compose([ - expressJwt({secret: firebaseToken}), + expressJwt({secret: config.get('jwt.signingSecret')}), (req, res, next) -> result = t.validate(req.user.d, validators.token) if not result.isValid() diff --git a/server/routes/api/me/spectate.coffee b/server/routes/api/me/spectate.coffee index d0f537e29..e6b62a5f2 100644 --- a/server/routes/api/me/spectate.coffee +++ b/server/routes/api/me/spectate.coffee @@ -38,7 +38,7 @@ router = express.Router() # algorithm: 'HS256' # # # We are encoding the payload inside the token -# token = jwt.sign(payload, config.get('firebaseToken'), options) +# token = jwt.sign(payload, config.get('jwt.signingSecret'), options) # res.status(200).json(token) # # .catch (error) -> next(error) @@ -104,7 +104,7 @@ router.get "/:player_id", (req, res, next) -> algorithm: 'HS256' # We are encoding the payload inside the token - @.token = jwt.sign(payload, config.get('firebaseToken'), options) + @.token = jwt.sign(payload, config.get('jwt.signingSecret'), options) .then ()-> responseData = gameData: DataAccessHelpers.restifyData(@.gameRow) diff --git a/server/routes/session.coffee b/server/routes/session.coffee index cab16819f..e82926a36 100644 --- a/server/routes/session.coffee +++ b/server/routes/session.coffee @@ -34,7 +34,6 @@ AnalyticsUtil = require '../../app/common/analyticsUtil' # Configuration object config = require '../../config/config' -firebaseToken = config.get('firebaseToken') {version} = require '../../version' ### @@ -83,10 +82,10 @@ logUserIn = (id) -> v: 0 iat: Math.floor(new Date().getTime() / 1000) options = - expiresIn: config.get('tokenExpiration') + expiresIn: config.get('jwt.tokenExpiration') algorithm: 'HS256' - @token = jwt.sign(payload, firebaseToken, options) + @token = jwt.sign(payload, config.get('jwt.signingSecret'), options) @analyticsData = analyticsDataFromUserData(data) return UsersModule.bumpSessionCountAndSyncDataIfNeeded(id, data) .then (synced) -> @@ -169,11 +168,11 @@ router.post "/session/", (req, res, next) -> # subject # issuer options = - expiresIn: config.get('tokenExpiration') + expiresIn: config.get('jwt.tokenExpiration') algorithm: 'HS256' # We are encoding the payload inside the token - @.token = jwt.sign(payload, firebaseToken, options) + @.token = jwt.sign(payload, config.get('jwt.signingSecret'), options) # make a db transaction/ledger event for the login # UsersModule.logEvent(@id,"session","login") diff --git a/server/routes/utility.coffee b/server/routes/utility.coffee index 15bb7910f..747695d1b 100644 --- a/server/routes/utility.coffee +++ b/server/routes/utility.coffee @@ -20,7 +20,6 @@ Errors = require '../lib/custom_errors' # Configuration object config = require '../../config/config.js' -firebaseToken = config.get('firebaseToken') # set up AWS AWS.config.update diff --git a/server/single_player.coffee b/server/single_player.coffee index 8bbfc71ac..20efebba8 100644 --- a/server/single_player.coffee +++ b/server/single_player.coffee @@ -8,6 +8,7 @@ _ = require 'underscore' colors = require 'colors' # used for console message coloring jwt = require 'jsonwebtoken' io = require 'socket.io' +ioJwt = require 'socketio-jwt' Promise = require 'bluebird' kue = require 'kue' moment = require 'moment' @@ -27,7 +28,6 @@ Consul = require './lib/consul' # Configuration object config = require '../config/config.js' env = config.get('env') -firebaseToken = config.get('firebaseToken') # Boots up a basic HTTP server on port 8080 # Responds to /health endpoint with status 200 @@ -75,12 +75,12 @@ io = require('socket.io')().listen(server, { origin: "*" } }) -# io.use( -# ioJwt.authorize( -# secret:firebaseToken -# timeout: 15000 -# ) -# ) +io.use( + ioJwt.authorize( + secret: config.get('jwt.signingSecret') + timeout: 15000 + ) +) module.exports = io server.listen config.get('game_port'), () -> Logger.module("AI SERVER").log "AI Server #{os.hostname()} started." @@ -303,7 +303,7 @@ onGameSpectatorJoin = (requestData) -> # verify - synchronous try - spectateToken = jwt.verify(requestData.spectateToken, firebaseToken) + spectateToken = jwt.verify(requestData.spectateToken, config.get('jwt.signingSecret')) catch error Logger.module("IO").error "[G:#{gameId}]", "spectate_game -> ERROR decoding spectate token: #{error?.message}".red diff --git a/test/integration/firebase/server_client.js b/test/integration/firebase/server_client.js new file mode 100644 index 000000000..4ac96517a --- /dev/null +++ b/test/integration/firebase/server_client.js @@ -0,0 +1,73 @@ +var path = require('path') +require('app-module-path').addPath(path.join(__dirname, '../../../')) +require('coffee-script/register') +var expect = require('chai').expect +var _ = require('underscore') + +var config = require('../../../config/config.js') +var DuelystFirebase = require('../../../server/lib/duelyst_firebase_module.coffee') + +describe('Firebase.ServerClient.IntegrationTests', function() { + const firebaseUrl = config.get('firebase.url'); + const testRef = '/test-ref-server'; + const testObject = {message: 'hello from firebase unit tests', timestamp: Date.now()}; + + it('should reject on invalid firebase.url', function() { + return DuelystFirebase.connect('invalidurl').getRootRef() + .then(function(rootRef) { + expect(rootRef).to.not.exist; + }) + .catch(function(e) { + expect(e).to.exist; + expect(e).to.be.instanceOf(Error); + expect(DuelystFirebase.getNumConnections()).to.be.equal(0); + }); + }); + + it('should resolve on success', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(rootRef.toString()).to.be.equal(firebaseUrl); + expect(DuelystFirebase.getNumConnections()).to.be.equal(1); + }); + }); + + it('should avoid recreating existing connections', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(rootRef.toString()).to.be.equal(firebaseUrl); + expect(DuelystFirebase.getNumConnections()).to.be.equal(1); + }); + }); + + it('should create new connections for new URLs', function() { + return DuelystFirebase.connect('https://another-duelyst-project.firebaseio.local/').getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(DuelystFirebase.getNumConnections()).to.be.equal(2); + }); + }); + + it('should write test data', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + rootRef.child(testRef) + .set(testObject, function(error) { + expect(error).to.not.exist; + }); + }); + }); + + it('should read back test data', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + rootRef.child(testRef) + .once('value') + .then(function(snapshot) { + expect(snapshot.val().to.be.equal(testObject)) + }); + }); + }); +}); diff --git a/test/unit/firebase/server_client.js b/test/unit/firebase/server_client.js new file mode 100644 index 000000000..ce92c305f --- /dev/null +++ b/test/unit/firebase/server_client.js @@ -0,0 +1,27 @@ +var path = require('path') +require('app-module-path').addPath(path.join(__dirname, '../../../')) +require('coffee-script/register') +var expect = require('chai').expect +var _ = require('underscore') + +var config = require('../../../config/config.js') +var DuelystFirebase = require('../../../server/lib/duelyst_firebase_module.coffee') + +describe('Firebase.ServerClient.UnitTests', function() { + const firebaseUrl = 'https://duelyst-unit-tests.firebaseio.local/' + + describe('#connect()', function() { + it('should reject on empty firebase.url', function() { + return DuelystFirebase.connect('').getRootRef() + .then(function(rootRef) { + expect(rootRef).to.not.exist; + }) + .error(function(e) { + expect(e).to.exist; + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('firebase.url must be set'); + expect(DuelystFirebase.getNumConnections()).to.be.equal(0); + }); + }); + }); +}); diff --git a/test/unit/misc/duelyst_firebase.js b/test/unit/misc/duelyst_firebase.js deleted file mode 100644 index 380120984..000000000 --- a/test/unit/misc/duelyst_firebase.js +++ /dev/null @@ -1,97 +0,0 @@ -var path = require('path') -require('app-module-path').addPath(path.join(__dirname, '../../../')) -require('coffee-script/register') -var expect = require('chai').expect -var DuelystFirebase = require('../../../server/lib/duelyst_firebase_module.coffee') -var Firebase = require('firebase') -var config = require('../../../config/config.js') -var _ = require ('underscore') - -describe("duelyst firebase module", function() { - - var firebaseUrl = config.get('firebase') - var firebaseToken = config.get('firebaseToken') - - describe("get root Firebase reference", function() { - - it('expect an explicit error (promise reject) if authentication fails', function() { - return DuelystFirebase.connect('https://duelyst-dev.firebaseio.com/foo','notarealtoken').getRootRef() - .then(function(rootRef){ - expect(rootRef).to.not.exist; - }) - .error(function(e){ - expect(e).to.exist; - expect(e).to.be.instanceOf(Error); - }) - }) - - it('expect an implicity error (throw) if given invalid URL', function() { - return DuelystFirebase.connect('notarealurl', firebaseToken).getRootRef() - .then(function(rootRef){ - expect(rootRef).to.not.exist; - }) - .catch(function(e){ - expect(e).to.exist; - expect(e).to.be.instanceOf(Error); - }) - }) - - it('expect a valid Firebase reference', function() { - return DuelystFirebase.connect(firebaseUrl, firebaseToken).getRootRef() - .then(function(rootRef){ - expect(rootRef).to.exist; - expect(rootRef.root().toString()).to.be.equal(config.get('firebase').replace(/\/$/, '')) - expect(DuelystFirebase.getNumConnections()).to.be.equal(1) - }) - }) - it('expect no new connections if given a previously used URL', function() { - return DuelystFirebase.connect(firebaseUrl, firebaseToken).getRootRef() - .then(function(rootRef){ - expect(rootRef).to.exist; - expect(rootRef.root().toString()).to.be.equal(config.get('firebase').replace(/\/$/, '')) - expect(DuelystFirebase.getNumConnections()).to.be.equal(1) - }) - }) - it('expect a different root reference is given a sub-URL (ie. /users)', function() { - return DuelystFirebase.connect(firebaseUrl + 'users', firebaseToken).getRootRef() - .then(function(rootRef){ - expect(rootRef).to.exist; - expect(DuelystFirebase.getNumConnections()).to.be.equal(2) - }) - }) - }) - - describe("get root Firebase reference, second try", function() { - it('expect the same Firebase reference as previous call', function() { - return DuelystFirebase.connect(firebaseUrl, firebaseToken).getRootRef() - .then(function(rootRef){ - expect(rootRef).to.exist; - expect(rootRef.root().toString()).to.be.equal(config.get('firebase').replace(/\/$/, '')) - expect(DuelystFirebase.getNumConnections()).to.be.equal(2) - }) - }) - }) - - describe("get root Firebase reference, no params specified", function() { - it('expect a valid Firebase reference', function() { - return DuelystFirebase.connect().getRootRef() - .then(function(rootRef){ - expect(rootRef).to.exist; - expect(rootRef.root().toString()).to.be.equal(config.get('firebase').replace(/\/$/, '')) - expect(DuelystFirebase.getNumConnections()).to.be.equal(2) - }) - }) - }) - - // describe("get new root Firebase reference", function() { - // it('expect a different root reference if given a different URL', function() { - // return DuelystFirebase.connect(config.get('auth'),config.get('authToken')).getRootRef() - // .then(function(rootRef){ - // expect(rootRef).to.exist; - // expect(rootRef.root().toString()).to.be.equal(config.get('auth').replace(/\/$/, '')) - // expect(DuelystFirebase.getNumConnections()).to.be.equal(2) - // }) - // }) - // }) - -}) diff --git a/yarn.lock b/yarn.lock index cfb26030d..25d9dc04a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,6 +54,159 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@fastify/busboy@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-1.1.0.tgz#4472f856e2bb5a9ee34ad64b93891b73b73537ca" + integrity sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA== + dependencies: + text-decoding "^1.0.0" + +"@firebase/app-types@0.7.0", "@firebase/app-types@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.7.0.tgz#c9e16d1b8bed1a991840b8d2a725fb58d0b5899f" + integrity sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg== + +"@firebase/auth-interop-types@0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz#5ce13fc1c527ad36f1bb1322c4492680a6cf4964" + integrity sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g== + +"@firebase/component@0.5.17": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.5.17.tgz#89291f378714df05d44430c524708669380d8ea6" + integrity sha512-mTM5CBSIlmI+i76qU4+DhuExnWtzcPS3cVgObA3VAjliPPr3GrUlTaaa8KBGfxsD27juQxMsYA0TvCR5X+GQ3Q== + dependencies: + "@firebase/util" "1.6.3" + tslib "^2.1.0" + +"@firebase/database-compat@^0.2.3": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.2.5.tgz#5bed7e2a2f671391bd2b23e9dca09400214a15dd" + integrity sha512-fj88gwtNJMcJBDjcTMbCuYEiVzuGb76rTOaaiAOqxR+unzvvbs2KU5KbFyl83jcpIjY6NIt+xXNrCXpzo7Zp3g== + dependencies: + "@firebase/component" "0.5.17" + "@firebase/database" "0.13.5" + "@firebase/database-types" "0.9.13" + "@firebase/logger" "0.3.3" + "@firebase/util" "1.6.3" + tslib "^2.1.0" + +"@firebase/database-types@0.9.13", "@firebase/database-types@^0.9.7": + version "0.9.13" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.9.13.tgz#47c12593ed27a9562f0919b7d3a1f1e00888abc2" + integrity sha512-dIJ1zGe3EHMhwcvukTOPzYlFYFIG1Et5Znl7s7y/ZTN2/toARRNnsv1qCKvqevIMYKvIrRsYOYfOXDS8l1YIJA== + dependencies: + "@firebase/app-types" "0.7.0" + "@firebase/util" "1.6.3" + +"@firebase/database@0.13.5": + version "0.13.5" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.13.5.tgz#c66888147d4d707237285547f8405dfa739f47a2" + integrity sha512-QmX73yi8URk36NAbykXeuAcJCjDtx3BzuxKJO3sL9B4CtjNFAfpWawVxoaaThocDWNAyMJxFhiL1kkaVraH7Lg== + dependencies: + "@firebase/auth-interop-types" "0.1.6" + "@firebase/component" "0.5.17" + "@firebase/logger" "0.3.3" + "@firebase/util" "1.6.3" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/logger@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.3.3.tgz#0f724b1e0b166d17ac285aac5c8ec14d136beed4" + integrity sha512-POTJl07jOKTOevLXrTvJD/VZ0M6PnJXflbAh5J9VGkmtXPXNG6MdZ9fmRgqYhXKTaDId6AQenQ262uwgpdtO0Q== + dependencies: + tslib "^2.1.0" + +"@firebase/util@1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.6.3.tgz#76128c1b5684c031823e95f6c08a7fb8560655c6" + integrity sha512-FujteO6Zjv6v8A4HS+t7c+PjU0Kaxj+rOnka0BsI/twUaCC9t8EQPmXpWZdk7XfszfahJn2pqsflUWUhtUkRlg== + dependencies: + tslib "^2.1.0" + +"@google-cloud/firestore@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-5.0.2.tgz#36923fde45987f928a220d347f341c5602f9e340" + integrity sha512-xlGcNYaW0nvUMzNn2+pLfbEBVt6oysVqtM89faMgZWkWfEtvIQGS0h5PRdLlcqufNzRCX3yIGv29Pb+03ys+VA== + dependencies: + 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@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" + integrity sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== + +"@google-cloud/promisify@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-3.0.0.tgz#5cd6941fc30c4acac18051706aa5af96069bd3e3" + integrity sha512-91ArYvRgXWb73YvEOBMmOcJc0bDRs5yiVHnqkwoG0f3nm7nZuipllz6e7BvFESBvjkDTBC0zMD8QxedUwNLc1A== + +"@google-cloud/storage@^6.1.0": + version "6.4.1" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-6.4.1.tgz#83334150d4e224cb48691de4d7f9c38e143a0970" + integrity sha512-lAddmRJ8tvxPykUqJfONBQA5XGwGk0vut1POXublc64+nCdB5aQMxwuBMf7J1zubx19QGpYPQwW6wR7YTWrvLw== + dependencies: + "@google-cloud/paginator" "^3.0.7" + "@google-cloud/projectify" "^3.0.0" + "@google-cloud/promisify" "^3.0.0" + abort-controller "^3.0.0" + arrify "^2.0.0" + async-retry "^1.3.3" + compressible "^2.0.12" + duplexify "^4.0.0" + ent "^2.2.0" + extend "^3.0.2" + gaxios "^5.0.0" + google-auth-library "^8.0.1" + mime "^3.0.0" + mime-types "^2.0.8" + p-limit "^3.0.1" + retry-request "^5.0.0" + teeny-request "^8.0.0" + uuid "^8.0.0" + +"@grpc/grpc-js@~1.6.0": + version "1.6.10" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.10.tgz#b6584c59ef90aa76d878ac92c21785e602f247ff" + integrity sha512-XTX5z/P5kH802MDoVm/rqOil0UwYEOEjf9+NPgfmm5UINIxDzwYaXfVR6z8svCBG8Hlbu/FzkXqhP8J5xaWzSQ== + dependencies: + "@grpc/proto-loader" "^0.7.0" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.6.12": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.13.tgz#008f989b72a40c60c96cd4088522f09b05ac66bc" + integrity sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g== + dependencies: + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^6.11.3" + yargs "^16.2.0" + +"@grpc/proto-loader@^0.7.0": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.2.tgz#fa63178853afe1473c50cff89fe572f7c8b20154" + integrity sha512-jCdyLIT/tdQ1zhrbTQnJNK5nbDf0GoBpy5jVNywBzzMDF+Vs6uEaHnfz46dMtDxkvwrF2hzk5Z67goliceH0sA== + dependencies: + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^7.0.0" + yargs "^16.2.0" + "@gulp-sourcemaps/map-sources@1.X": version "1.0.0" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" @@ -91,6 +244,64 @@ semver "^7.3.5" tar "^6.1.11" +"@panva/asn1.js@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6" + integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw== + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@segment/loosely-validate-event@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681" @@ -116,11 +327,31 @@ dependencies: jsonwebtoken "8.5.1" +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/component-emitter@^1.2.10": version "1.2.11" resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + "@types/cookie@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" @@ -131,11 +362,70 @@ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== +"@types/express-serve-static-core@^4.17.18": + version "4.17.30" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz#0f2f99617fa8f9696170c46152ccf7500b34ac04" + integrity sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.13": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/jsonwebtoken@^8.5.8": + version "8.5.9" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz#2c064ecb0b3128d837d2764aa0b117b0ff6e4586" + integrity sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg== + dependencies: + "@types/node" "*" + +"@types/long@^4.0.0", "@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "18.7.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.13.tgz#23e6c5168333480d454243378b69e861ab5c011a" + integrity sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw== + "@types/node@>=10.0.0": version "17.0.23" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/serve-static@*": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + dependencies: + "@types/mime" "*" + "@types/node" "*" + JSONStream@^1.0.3, JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -149,14 +439,6 @@ JSONStream@^1.0.3, JSONStream@^1.0.4: resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57" integrity sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c= -MD5@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/MD5/-/MD5-1.2.2.tgz#d903c8ec5ba223cd2b80432824881d04bb9841c0" - integrity sha1-2QPI7FuiI80rgEMoJIgdBLuYQcA= - dependencies: - charenc ">= 0.0.1" - crypt ">= 0.0.1" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -167,6 +449,13 @@ abbrev@1.0.x: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -361,7 +650,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -628,6 +917,11 @@ arrify@^1.0.0, arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -727,6 +1021,13 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + async-settle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" @@ -1492,7 +1793,7 @@ base64-js@1.2.0: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1" integrity sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE= -base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -1550,6 +1851,11 @@ benchmark@^2.1.0: lodash "^4.17.4" platform "^1.3.3" +bignumber.js@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62" + integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A== + bin-build@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-2.2.0.tgz#11f8dd61f70ffcfa2bdcaa5b46f5e8fedd4221cc" @@ -2422,7 +2728,7 @@ character-parser@1.2.0: resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-1.2.0.tgz#94134d6e5d870a39be359f7d22460935184ddef6" integrity sha1-lBNNbl2HCjm+NZ99IkYJNRhN3vY= -charenc@0.0.2, "charenc@>= 0.0.1": +charenc@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= @@ -2600,6 +2906,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -2887,6 +3202,13 @@ compose-middleware@^2.0.1: dependencies: array-flatten "^2.1.0" +compressible@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3306,7 +3628,7 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -crypt@0.0.2, "crypt@>= 0.0.1": +crypt@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= @@ -3483,7 +3805,7 @@ debug-fabulous@0.0.X: lazy-debug-legacy "0.0.X" object-assign "4.1.0" -debug@*, debug@4, debug@^4.1.1, debug@^4.3.2, debug@~4.3.1, debug@~4.3.2: +debug@*, debug@4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -4150,6 +4472,16 @@ duplexify@^3.2.0, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +duplexify@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + each-async@^1.0.0, each-async@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/each-async/-/each-async-1.1.1.tgz#dee5229bdf0ab6ba2012a395e1b869abf8813473" @@ -4179,7 +4511,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -4340,7 +4672,7 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -4385,6 +4717,11 @@ engine.io@~6.1.0: engine.io-parser "~5.0.3" ws "~8.2.3" +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -4566,6 +4903,11 @@ es6-weak-map@~0.1.4: es6-iterator "~0.1.3" es6-symbol "~2.0.1" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-goat@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-1.3.0.tgz#bf3ee8ad1e488fbba404b084b2e4a55e09231c64" @@ -4959,6 +5301,11 @@ event-stream@~3.1.0: stream-combiner "~0.0.4" through "~2.3.1" +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + events@1.1.1, events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -5193,7 +5540,7 @@ extend@^1.2.1: resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8" integrity sha1-0VFvsP9WJNLr+RI+odrFoZlABPg= -extend@^3.0.0, extend@~3.0.2: +extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -5304,6 +5651,11 @@ fast-stats@0.0.3: resolved "https://registry.yarnpkg.com/fast-stats/-/fast-stats-0.0.3.tgz#650af963c3ff85c496a3610f20d40cd4c164594d" integrity sha1-ZQr5Y8P/hcSWo2EPINQM1MFkWU0= +fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz#bf1898ad800282a4e53c0ea9690704dd26e4298e" + integrity sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ== + fastly-promises@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/fastly-promises/-/fastly-promises-0.4.0.tgz#84b0290e61665e867018715c9952f09709fc2794" @@ -5324,7 +5676,7 @@ faucet@0.0.1: tape "~2.3.2" through2 "~0.2.3" -faye-websocket@>=0.6.0: +faye-websocket@0.11.4, faye-websocket@>=0.6.0: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== @@ -5566,6 +5918,23 @@ fined@^1.0.1: object.pick "^1.2.0" parse-filepath "^1.0.1" +firebase-admin@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-11.0.1.tgz#68b11b55af70eb9b9a4c8b2cdfa86c892e9ba91b" + integrity sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q== + dependencies: + "@fastify/busboy" "^1.1.0" + "@firebase/database-compat" "^0.2.3" + "@firebase/database-types" "^0.9.7" + "@types/node" ">=12.12.47" + jsonwebtoken "^8.5.1" + jwks-rsa "^2.0.2" + node-forge "^1.3.1" + uuid "^8.3.2" + optionalDependencies: + "@google-cloud/firestore" "^5.0.2" + "@google-cloud/storage" "^6.1.0" + firebase@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/firebase/-/firebase-2.0.3.tgz#9049b822b8d4911fdf1ba4afcbf527def7c63f91" @@ -5711,13 +6080,6 @@ formatio@1.1.1: dependencies: samsam "~1.1" -formatio@~1.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.0.2.tgz#e7991ca144ff7d8cff07bb9ac86a9b79c6ba47ef" - integrity sha1-55kcoUT/fYz/B7uayGqbeca6R+8= - dependencies: - samsam "~1.1" - formidable@1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.14.tgz#2b3f4c411cbb5fdd695c44843e2a23514a43231a" @@ -5899,6 +6261,43 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^4.0.0: + version "4.3.3" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.3.3.tgz#d44bdefe52d34b6435cc41214fdb160b64abfc22" + integrity sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA== + 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" + +gaxios@^5.0.0, gaxios@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-5.0.1.tgz#50fc76a2d04bc1700ed8c3ff1561e52255dfc6e0" + integrity sha512-keK47BGKHyyOVQxgcUaSaFvr3ehZYAlvhvpHXy0YB2itzZef+GqZR8TBsfVRWghdwlKrYsn+8L8i3eblF7Oviw== + dependencies: + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.6.7" + +gcp-metadata@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9" + integrity sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A== + dependencies: + gaxios "^4.0.0" + json-bigint "^1.0.0" + +gcp-metadata@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.0.0.tgz#a00f999f60a4461401e7c515f8a3267cfb401ee7" + integrity sha512-gfwuX3yA3nNsHSWUL4KG90UulNiq922Ukj3wLTrcnX33BB7PwB1o0ubR8KVvXu9nJH+P5w1j2SQSNNqto+H0DA== + dependencies: + gaxios "^5.0.0" + json-bigint "^1.0.0" + generate-function@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" @@ -5928,7 +6327,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -6482,6 +6881,36 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" +google-auth-library@^7.14.0: + version "7.14.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" + integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA== + 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" + +google-auth-library@^8.0.1: + version "8.4.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.4.0.tgz#3a5414344bb313ee64ceeef1f7e5162cc1fdf04b" + integrity sha512-cg/usxyQEmq4PPDBQRt+kGIrfL3k+mOrAoS9Xv1hitQL66AoY7iWvRBcYo3Rb0w4V1t9e/GqW2/D4honlAtMDg== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^5.0.0" + gcp-metadata "^5.0.0" + gtoken "^6.1.0" + jws "^4.0.0" + lru-cache "^6.0.0" + google-auth-library@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-0.10.0.tgz#6e15babee85fd1dd14d8d128a295b6838d52136e" @@ -6492,6 +6921,25 @@ google-auth-library@~0.10.0: lodash.noop "^3.0.1" request "^2.74.0" +google-gax@^2.24.1: + version "2.30.5" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.30.5.tgz#e836f984f3228900a8336f608c83d75f9cb73eff" + integrity sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ== + 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.3" + retry-request "^4.0.0" + google-p12-pem@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-0.1.2.tgz#33c46ab021aa734fa0332b3960a9a3ffcb2f3177" @@ -6499,6 +6947,20 @@ google-p12-pem@^0.1.0: dependencies: node-forge "^0.7.1" +google-p12-pem@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" + integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== + dependencies: + node-forge "^1.3.1" + +google-p12-pem@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-4.0.0.tgz#f46581add1dc6ea0b96160cda6ce37ee35ab8ca3" + integrity sha512-lRTMn5ElBdDixv4a86bixejPSRk1boRtUowNepeKEVvYiFlkLuAJUVpEz6PfObDHYEKnZWq/9a2zC98xu62A9w== + dependencies: + node-forge "^1.3.1" + googleapis@^16.1.0: version "16.1.0" resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-16.1.0.tgz#0f19f2d70572d918881a0f626e3b1a2fa8629576" @@ -6591,6 +7053,24 @@ gtoken@^1.2.1: mime "^1.4.1" request "^2.72.0" +gtoken@^5.0.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.3.2.tgz#deb7dc876abe002178e0515e383382ea9446d58f" + integrity sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ== + dependencies: + gaxios "^4.0.0" + google-p12-pem "^3.1.3" + jws "^4.0.0" + +gtoken@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.1.tgz#29ebf3e6893719176d180f5694f1cad525ce3c04" + integrity sha512-HPM4VzzPEGxjQ7T2xLrdSYBs+h1c0yHAUiN+8RHPDoiZbndlpg9Sx3SjWcrTt9+N3FHsSABEpjvdQVan5AAuZQ== + dependencies: + gaxios "^5.0.1" + google-p12-pem "^4.0.0" + jws "^4.0.0" + gulp-autoprefixer@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/gulp-autoprefixer/-/gulp-autoprefixer-2.3.1.tgz#f675d3b1bd76f088df2f24ab7ad3e4a059e07e67" @@ -7387,6 +7867,15 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.6.tgz#2e02406ab2df8af8a7abfba62e0da01c62b95afd" integrity sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA== +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -8224,11 +8713,21 @@ is-shared-array-buffer@^1.0.1: dependencies: call-bind "^1.0.2" +is-stream-ended@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" + integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== + is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -8448,7 +8947,7 @@ j2j@0.1.2: graceful-fs "^3.0.2" q "^1.0.1" sandbox "^0.8.6" - yargs "https://github.com/boneskull/yargs#nylen" + yargs "git://github.com/boneskull/yargs#nylen" jade@0.26.3: version "0.26.3" @@ -8481,6 +8980,13 @@ join-component@^1.1.0: resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5" integrity sha1-uEF7dQZho5K+4sJTfGiyqdSXfNU= +jose@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/jose/-/jose-2.0.5.tgz#29746a18d9fff7dcf9d5d2a6f62cb0c7cd27abd3" + integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA== + dependencies: + "@panva/asn1.js" "^1.0.0" + jpeg-js@^0.4.1: version "0.4.3" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" @@ -8586,6 +9092,13 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -8680,7 +9193,7 @@ jsonwebtoken@5.4.1: jws "^3.0.0" ms "^0.7.1" -jsonwebtoken@8.5.1, jsonwebtoken@^8.3.0: +jsonwebtoken@8.5.1, jsonwebtoken@^8.3.0, jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== @@ -8740,6 +9253,27 @@ jwa@^1.4.1: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwks-rsa@^2.0.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-2.1.4.tgz#38ebfbe9cb4cdce3be070e6575796304917bae97" + integrity sha512-mpArfgPkUpX11lNtGxsF/szkasUcbWHGplZl/uFvFO2NuMHmt0dQXIihh0rkPU2yQd5niQtuUHbXnG/WKiXF6Q== + dependencies: + "@types/express" "^4.17.13" + "@types/jsonwebtoken" "^8.5.8" + debug "^4.3.4" + jose "^2.0.5" + limiter "^1.1.5" + lru-memoizer "^2.1.4" + jws@^3.0.0, jws@^3.1.4, jws@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" @@ -8748,6 +9282,14 @@ jws@^3.0.0, jws@^3.1.4, jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + jwt-decode@^2.0.1: version "2.2.0" resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79" @@ -8967,6 +9509,11 @@ liftoff@~2.2.0: rechoir "^0.6.2" resolve "^1.1.7" +limiter@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" + integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== + load-json-file@^1.0.0, load-json-file@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -9228,6 +9775,11 @@ lodash.assign@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.clonedeep@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz#a0a1e40d82a5ea89ff5b147b8444ed63d92827db" @@ -9518,7 +10070,7 @@ lodash@>=2.4.1, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.5.1, lo resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -lodash@^2.4.1, lodash@~2.4.1: +lodash@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" integrity sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4= @@ -9556,6 +10108,16 @@ lolex@1.3.2: resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" integrity sha1-fD2mL/yzDw9agKJWbKJORdigHzE= +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +long@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61" + integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w== + longest@^1.0.0, longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -9616,11 +10178,34 @@ lru-cache@^4.0.1, lru-cache@^4.1.5: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru-cache@^7.4.0: version "7.8.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.8.1.tgz#68ee3f4807a57d2ba185b7fd90827d5c21ce82bb" integrity sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg== +lru-cache@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + integrity sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw== + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +lru-memoizer@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.1.4.tgz#b864d92b557f00b1eeb322156a0409cb06dafac6" + integrity sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ== + dependencies: + lodash.clonedeep "^4.5.0" + lru-cache "~4.0.0" + lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -9899,12 +10484,12 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.52.0, mime-db@^1.28.0: +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.0.1, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.0.1, mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -9921,6 +10506,11 @@ mime@1.6.0, mime@^1.3.4, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -10131,15 +10721,6 @@ mocha@^2.4.5: supports-color "1.2.0" to-iso-string "0.0.2" -mockfirebase@^0.3.0: - version "0.3.2" - resolved "https://registry.yarnpkg.com/mockfirebase/-/mockfirebase-0.3.2.tgz#6d30b1115bbd3c20bb08b95689527af2a6344ef7" - integrity sha1-bTCxEVu9PCC7CLlWiVJ68qY0Tvc= - dependencies: - MD5 "~1.2.1" - lodash "~2.4.1" - sinon "~1.10.3" - modify-filename@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/modify-filename/-/modify-filename-1.1.0.tgz#9a2dec83806fbb2d975f22beec859ca26b393aa1" @@ -10466,7 +11047,7 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.7: +node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -10478,6 +11059,11 @@ node-forge@^0.7.1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f" @@ -10754,6 +11340,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-inspect@^1.12.0, object-inspect@^1.9.0: version "1.12.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" @@ -11080,6 +11671,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -11905,6 +12503,51 @@ proto-props@^1.1.0: resolved "https://registry.yarnpkg.com/proto-props/-/proto-props-1.1.0.tgz#e2606581dd24aa22398aeeeb628fc08e2ec89c91" integrity sha512-A377CdhQBRjYVsSWrm2jo0KJa+N/IBew6lGLm0pdzZjtVqlUT23wEqg7q1/bk5gBEgVoBBbaErZY+UUNrcKOug== +proto3-json-serializer@^0.1.8: + version "0.1.9" + resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz#705ddb41b009dd3e6fcd8123edd72926abf65a34" + integrity sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ== + dependencies: + protobufjs "^6.11.2" + +protobufjs@6.11.3, protobufjs@^6.11.2, protobufjs@^6.11.3, protobufjs@^6.8.6: + version "6.11.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" + integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + 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" + +protobufjs@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.0.0.tgz#8c678e1351fd926178fce5a4213913e8d990974f" + integrity sha512-ffNIEm+quOcYtQvHdW406v1NQmZSuqVklxsXk076BtuFnlYZfigLU+JOMrTD8TUOyqHYbRI/fSVNvgd25YeN3w== + 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 "^5.0.0" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -11920,10 +12563,10 @@ pruner@^0.0.7: dependencies: fs-extra "^4.0.0" -pseudomap@^1.0.2: +pseudomap@^1.0.1, pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== psl@^1.1.28: version "1.8.0" @@ -12222,7 +12865,7 @@ readable-stream@1.0.27-1: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@3, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -12745,6 +13388,27 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry-request@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903" + integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg== + dependencies: + debug "^4.1.1" + extend "^3.0.2" + +retry-request@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.1.tgz#c6be2a4a36f1554ba3251fa8fd945af26ee0e9ec" + integrity sha512-lxFKrlBt0OZzCWh/V0uPEN0vlr3OhdeXnpeY5OES+ckslm791Cb1D5P7lJUSnY7J5hiCjcyaUGmzCnIGDCUBig== + dependencies: + debug "^4.1.1" + extend "^3.0.2" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + rev-hash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rev-hash/-/rev-hash-1.0.0.tgz#96993959ea9bfb1c59b13adf02ac2e34bb373603" @@ -13187,14 +13851,6 @@ sinon@^1.10.3: samsam "1.1.2" util ">=0.10.3 <1" -sinon@~1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.10.3.tgz#c063e0e99d8327dc199113aab52eb83a2e9e3c2c" - integrity sha1-wGPg6Z2DJ9wZkROqtS64Oi6ePCw= - dependencies: - formatio "~1.0" - util ">=0.10.3 <1" - slash@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/slash/-/slash-0.1.3.tgz#aa710c8ef50b8e1d187ad6cff46f38c656ba0e57" @@ -13629,6 +14285,13 @@ stream-combiner@~0.0.3, stream-combiner@~0.0.4: dependencies: duplexer "~0.1.1" +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + stream-exhaust@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" @@ -13701,7 +14364,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13809,7 +14472,7 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -13914,6 +14577,11 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== + stylus@0.42.2: version "0.42.2" resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.42.2.tgz#bed29107803129bed1983efc4c7e33f4fd34fee7" @@ -14144,6 +14812,17 @@ tcomb@^2.2.0, tcomb@^2.6.0: resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-2.7.0.tgz#10d62958041669a5d53567b9a4ee8cde22b1c2b0" integrity sha1-ENYpWAQWaaXVNWe5pO6M3iKxwrA= +teeny-request@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-8.0.0.tgz#9614410ba70114fd28ba7bf5077dce3e2f02adf7" + integrity sha512-6KEYxXI4lQPSDkXzXpPmJPNmo7oqduFFbhOEHf8sfsLbXyCsb+umUjBtMGAKhaSToD8JNCtQutTRefu29K64JA== + 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" + temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -14175,6 +14854,11 @@ ternary-stream@^1.2.0: merge-stream "~0.1.6" through2 "~0.6.3" +text-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -14511,6 +15195,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tty-browserify@0.0.1, tty-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" @@ -14955,7 +15644,7 @@ uuid@^3.0.1, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.2: +uuid@^8.0.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -15424,6 +16113,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-fn@^0.1.0: version "0.1.5" resolved "https://registry.yarnpkg.com/wrap-fn/-/wrap-fn-0.1.5.tgz#f21b6e41016ff4a7e31720dbc63a09016bdf9845" @@ -15619,10 +16317,15 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== -yallist@^2.1.2: +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^2.0.0, yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== yallist@^3.0.0, yallist@^3.1.1: version "3.1.1" @@ -15642,6 +16345,11 @@ yargs-parser@^15.0.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394" @@ -15667,6 +16375,19 @@ yargs@^14.2.0: y18n "^4.0.0" yargs-parser "^15.0.1" +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^7.1.0: version "7.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db" @@ -15686,9 +16407,9 @@ yargs@^7.1.0: y18n "^3.2.1" yargs-parser "^5.0.1" -"yargs@https://github.com/boneskull/yargs#nylen": +"yargs@git://github.com/boneskull/yargs#nylen": version "1.3.1" - resolved "https://github.com/boneskull/yargs#7fbfd89cc0200a6b0b858115f6e33b3c2b7ad98a" + resolved "git://github.com/boneskull/yargs#7fbfd89cc0200a6b0b858115f6e33b3c2b7ad98a" yargs@~3.27.0: version "3.27.0" @@ -15725,6 +16446,11 @@ yeast@0.1.2: resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + zopflipng-bin@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/zopflipng-bin/-/zopflipng-bin-3.0.1.tgz#988203810fd152e4ed75f4476be0cdf2aadba758" From c19a669846979cfceb31d1c5721ec9d7a980422f Mon Sep 17 00:00:00 2001 From: Will Roberts Date: Wed, 24 Aug 2022 23:57:41 -0400 Subject: [PATCH 2/4] Fixes some DB access / concurrency issues for migrations and tests --- config/development.json | 2 +- docker-compose.yaml | 5 +++-- docker/start | 0 .../20160913190913_add_gift_code_exclusion_id.js | 9 ++------- 4 files changed, 6 insertions(+), 10 deletions(-) mode change 100644 => 100755 docker/start diff --git a/config/development.json b/config/development.json index 3adea2aae..42dbb7a85 100644 --- a/config/development.json +++ b/config/development.json @@ -1,7 +1,7 @@ { "env": "development", "api": "http://localhost:3000", - "postgres_connection_string": "postgres://duelyst:duelyst@0.0.0.0:5431/duelyst", + "postgres_connection_string": "postgres://duelyst:duelyst@0.0.0.0:5432/duelyst", "redis": { "ip": "localhost", "port": 6379, diff --git a/docker-compose.yaml b/docker-compose.yaml index ee64daade..e0a9c4c30 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -15,14 +15,14 @@ services: - "6379:6379" db: - image: postgres + image: postgres:14 restart: always environment: POSTGRES_USER: duelyst POSTGRES_PASSWORD: duelyst POSTGRES_DB: duelyst ports: - - 5431:5432 + - 5432:5432 volumes: - ./.pgdata:/var/lib/postgresql/data @@ -106,6 +106,7 @@ services: DEBUG: "*" NODE_ENV: development POSTGRES_CONNECTION: "pg://duelyst:duelyst@db/duelyst" + FIREBASE_URL: ${FIREBASE_URL} depends_on: - db working_dir: /app diff --git a/docker/start b/docker/start old mode 100644 new mode 100755 diff --git a/server/migrations/20160913190913_add_gift_code_exclusion_id.js b/server/migrations/20160913190913_add_gift_code_exclusion_id.js index ef4eaa64b..5e5db10b3 100644 --- a/server/migrations/20160913190913_add_gift_code_exclusion_id.js +++ b/server/migrations/20160913190913_add_gift_code_exclusion_id.js @@ -1,13 +1,8 @@ - -// - exports.up = function(knex, Promise) { return Promise.all([ - knex.schema.table('gift_codes', function (table) { - table.string('exclusion_id',36) - }), + knex.raw('ALTER TABLE gift_codes ADD COLUMN IF NOT EXISTS exclusion_id varchar;'), // partial index since it will only be queried when a gift_code has a user and created concurrently for performance reasons - knex.raw("CREATE INDEX CONCURRENTLY gift_codes_claimed_by_user_id_index ON gift_codes (claimed_by_user_id) WHERE claimed_by_user_id IS NOT NULL") + knex.raw("CREATE INDEX CONCURRENTLY IF NOT EXISTS gift_codes_claimed_by_user_id_index ON gift_codes (claimed_by_user_id) WHERE claimed_by_user_id IS NOT NULL") ]) } From b289ad05216232e6b0b2a5afb80864249b4bb86d Mon Sep 17 00:00:00 2001 From: Will Roberts Date: Fri, 26 Aug 2022 19:48:40 -0400 Subject: [PATCH 3/4] Adds graceful shutdown with `disconnect()` and catches errors earlier. --- server/lib/duelyst_firebase_module.coffee | 17 +++- test/integration/firebase/server_client.js | 111 +++++++++++---------- 2 files changed, 77 insertions(+), 51 deletions(-) diff --git a/server/lib/duelyst_firebase_module.coffee b/server/lib/duelyst_firebase_module.coffee index eb62be5c3..d5bc5278b 100644 --- a/server/lib/duelyst_firebase_module.coffee +++ b/server/lib/duelyst_firebase_module.coffee @@ -30,6 +30,17 @@ class DuelystFirebaseModule firebaseUrl: firebaseUrl, ) + # Gracefully disconnect from Firebase. + @disconnect: (url) -> + if @apps[url]? + Logger.module('Firebase').log "disconnecting from #{url}" + @apps[url].promise.then (deletable) -> + deletable.delete().then (error) -> + Logger.module('Firebase').error "failed to delete: #{error.toString()}" + delete DuelystFirebaseModule.apps[url] + else + Logger.module('Firebase').log "already disconnected from #{url}" + # Count current number of connections @getNumConnections: -> _.size(@apps) @@ -50,6 +61,10 @@ class DuelystFirebaseModule credential: firebaseAdmin.credential.cert(firebaseServiceAccount), databaseURL: @firebaseUrl }, @firebaseUrl) + + # Initialize the database before resolving. + db = app.database() + ref = db.ref() resolve(app) catch e return reject(new Error('failed to initialize firebase app: ' + e)) @@ -65,6 +80,6 @@ class DuelystFirebaseModule db = app.database() return db.ref() catch e - Logger.module('Firebase').error "getRootRef: #{e.toString()}" + Logger.module('Firebase').error "failed to get ref: #{e.toString()}" module.exports = DuelystFirebaseModule diff --git a/test/integration/firebase/server_client.js b/test/integration/firebase/server_client.js index 4ac96517a..a00b61400 100644 --- a/test/integration/firebase/server_client.js +++ b/test/integration/firebase/server_client.js @@ -8,66 +8,77 @@ var config = require('../../../config/config.js') var DuelystFirebase = require('../../../server/lib/duelyst_firebase_module.coffee') describe('Firebase.ServerClient.IntegrationTests', function() { - const firebaseUrl = config.get('firebase.url'); - const testRef = '/test-ref-server'; - const testObject = {message: 'hello from firebase unit tests', timestamp: Date.now()}; + const firebaseUrl = config.get('firebase.url'); + const testRef = '/test-ref-server'; + const testObject = {message: 'hello from firebase unit tests', timestamp: Date.now()}; - it('should reject on invalid firebase.url', function() { - return DuelystFirebase.connect('invalidurl').getRootRef() - .then(function(rootRef) { - expect(rootRef).to.not.exist; - }) - .catch(function(e) { - expect(e).to.exist; - expect(e).to.be.instanceOf(Error); - expect(DuelystFirebase.getNumConnections()).to.be.equal(0); - }); + it('should reject on invalid firebase.url', function() { + return DuelystFirebase.connect('invalidurl').getRootRef() + .then(function(rootRef) { + expect(rootRef).to.not.exist; + }) + .catch(function(e) { + expect(e).to.exist; + expect(e).to.be.instanceOf(Error); + expect(DuelystFirebase.getNumConnections()).to.be.equal(0); }); + }); - it('should resolve on success', function() { - return DuelystFirebase.connect(firebaseUrl).getRootRef() - .then(function(rootRef) { - expect(rootRef).to.exist; - expect(rootRef.toString()).to.be.equal(firebaseUrl); - expect(DuelystFirebase.getNumConnections()).to.be.equal(1); - }); + it('should resolve on success', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(rootRef.toString()).to.be.equal(firebaseUrl); + expect(DuelystFirebase.getNumConnections()).to.be.equal(1); + DuelystFirebase.disconnect(firebaseUrl); }); + }); - it('should avoid recreating existing connections', function() { - return DuelystFirebase.connect(firebaseUrl).getRootRef() - .then(function(rootRef) { - expect(rootRef).to.exist; - expect(rootRef.toString()).to.be.equal(firebaseUrl); - expect(DuelystFirebase.getNumConnections()).to.be.equal(1); - }); + it('should avoid recreating existing connections', function() { + let firstRef = DuelystFirebase.connect(firebaseUrl).getRootRef(); + + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(rootRef.toString()).to.be.equal(firebaseUrl); + expect(DuelystFirebase.getNumConnections()).to.be.equal(1); + DuelystFirebase.disconnect(firebaseUrl); }); + }); - it('should create new connections for new URLs', function() { - return DuelystFirebase.connect('https://another-duelyst-project.firebaseio.local/').getRootRef() - .then(function(rootRef) { - expect(rootRef).to.exist; - expect(DuelystFirebase.getNumConnections()).to.be.equal(2); - }); + it('should create new connections for new URLs', function() { + let anotherUrl = 'https://another-duelyst-project.firebaseio.local/'; + let firstRef = DuelystFirebase.connect(firebaseUrl).getRootRef(); + + return DuelystFirebase.connect(anotherUrl).getRootRef() + .then(function(rootRef) { + expect(rootRef).to.exist; + expect(DuelystFirebase.getNumConnections()).to.be.equal(2); + DuelystFirebase.disconnect(firebaseUrl); + DuelystFirebase.disconnect(anotherUrl); }); + }); - it('should write test data', function() { - return DuelystFirebase.connect(firebaseUrl).getRootRef() - .then(function(rootRef) { - rootRef.child(testRef) - .set(testObject, function(error) { - expect(error).to.not.exist; - }); - }); + it('should write test data', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + rootRef.child(testRef) + .set(testObject, function(error) { + expect(error).to.not.exist; + DuelystFirebase.disconnect(firebaseUrl); + }); }); + }); - it('should read back test data', function() { - return DuelystFirebase.connect(firebaseUrl).getRootRef() - .then(function(rootRef) { - rootRef.child(testRef) - .once('value') - .then(function(snapshot) { - expect(snapshot.val().to.be.equal(testObject)) - }); - }); + it('should read back test data', function() { + return DuelystFirebase.connect(firebaseUrl).getRootRef() + .then(function(rootRef) { + rootRef.child(testRef) + .once('value') + .then(function(snapshot) { + expect(snapshot.val().to.be.equal(testObject)) + DuelystFirebase.disconnect(firebaseUrl); + }); }); + }); }); From 60001b64ae7a607ec490f1ff94b15b895221325a Mon Sep 17 00:00:00 2001 From: Will Roberts Date: Fri, 2 Sep 2022 09:14:40 -0400 Subject: [PATCH 4/4] Firebase: handle missing service account key --- server/lib/duelyst_firebase_module.coffee | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/lib/duelyst_firebase_module.coffee b/server/lib/duelyst_firebase_module.coffee index d5bc5278b..2c630d806 100644 --- a/server/lib/duelyst_firebase_module.coffee +++ b/server/lib/duelyst_firebase_module.coffee @@ -10,7 +10,13 @@ Logger = require '../../app/common/logger.coffee' config = require '../../config/config.js' defaultFirebaseUrl = config.get('firebase.url') firebaseLoggingEnabled = config.get('firebase.loggingEnabled') -firebaseServiceAccount = require('../../serviceAccountKey.json') + +# Read service account credentials. +try + firebaseServiceAccount = require('../../serviceAccountKey.json') +catch error + Logger.module('Firebase').error 'Failed to read serviceAccountKey.json; will not authenticate to Firebase' + firebaseServiceAccount = {} class DuelystFirebaseModule # App objects keyed by URL