Browse Source

refactor: remove bluebird + native scheduler (#5702)

Nicolas Giard 2 years ago
parent
commit
f4ce5ff63e

+ 0 - 2
package.json

@@ -52,7 +52,6 @@
     "auto-load": "3.0.4",
     "auto-load": "3.0.4",
     "aws-sdk": "2.1208.0",
     "aws-sdk": "2.1208.0",
     "bcryptjs-then": "1.0.1",
     "bcryptjs-then": "1.0.1",
-    "bluebird": "3.7.2",
     "body-parser": "1.20.0",
     "body-parser": "1.20.0",
     "chalk": "4.1.2",
     "chalk": "4.1.2",
     "cheerio": "1.0.0-rc.12",
     "cheerio": "1.0.0-rc.12",
@@ -81,7 +80,6 @@
     "filesize": "6.1.0",
     "filesize": "6.1.0",
     "fs-extra": "9.0.1",
     "fs-extra": "9.0.1",
     "getos": "3.2.1",
     "getos": "3.2.1",
-    "graphile-worker": "0.13.0",
     "graphql": "16.3.0",
     "graphql": "16.3.0",
     "graphql-list-fields": "2.0.2",
     "graphql-list-fields": "2.0.2",
     "graphql-rate-limit-directive": "2.0.2",
     "graphql-rate-limit-directive": "2.0.2",

+ 0 - 19
server/app/data.yml

@@ -78,25 +78,6 @@ defaults:
     search:
     search:
       maxHits: 100
       maxHits: 100
     maintainerEmail: security@requarks.io
     maintainerEmail: security@requarks.io
-jobs:
-  - task: background
-    identifier: purge-uploads
-    pattern: '*/15 * * * *'
-    payload:
-      name: purgeUploads
-      data: {}
-  # - task: simple
-  #   identifier: letest
-  #   pattern: '* * * * *'
-  #   payload:
-  #     name: bob
-  #     data: {}
-  # - task: simple
-  #   identifier: letest2
-  #   pattern: '* * * * *'
-  #   payload:
-  #     name: bob
-  #     data: {}
 groups:
 groups:
   defaultPermissions:
   defaultPermissions:
     - 'read:pages'
     - 'read:pages'

+ 4 - 3
server/core/auth.js

@@ -4,8 +4,9 @@ const _ = require('lodash')
 const jwt = require('jsonwebtoken')
 const jwt = require('jsonwebtoken')
 const ms = require('ms')
 const ms = require('ms')
 const { DateTime } = require('luxon')
 const { DateTime } = require('luxon')
-const Promise = require('bluebird')
-const crypto = Promise.promisifyAll(require('crypto'))
+const util = require('node:util')
+const crypto = require('node:crypto')
+const randomBytes = util.promisify(crypto.randomBytes)
 const pem2jwk = require('pem-jwk').pem2jwk
 const pem2jwk = require('pem-jwk').pem2jwk
 
 
 const securityHelper = require('../helpers/security')
 const securityHelper = require('../helpers/security')
@@ -366,7 +367,7 @@ module.exports = {
   async regenerateCertificates () {
   async regenerateCertificates () {
     WIKI.logger.info('Regenerating certificates...')
     WIKI.logger.info('Regenerating certificates...')
 
 
-    _.set(WIKI.config, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex'))
+    _.set(WIKI.config, 'sessionSecret', (await randomBytes(32)).toString('hex'))
     const certs = crypto.generateKeyPairSync('rsa', {
     const certs = crypto.generateKeyPairSync('rsa', {
       modulusLength: 2048,
       modulusLength: 2048,
       publicKeyEncoding: {
       publicKeyEncoding: {

+ 2 - 2
server/core/db.js

@@ -1,13 +1,13 @@
 const _ = require('lodash')
 const _ = require('lodash')
 const autoload = require('auto-load')
 const autoload = require('auto-load')
 const path = require('path')
 const path = require('path')
-const Promise = require('bluebird')
 const Knex = require('knex')
 const Knex = require('knex')
 const fs = require('fs')
 const fs = require('fs')
 const Objection = require('objection')
 const Objection = require('objection')
 
 
 const migrationSource = require('../db/migrator-source')
 const migrationSource = require('../db/migrator-source')
 const migrateFromLegacy = require('../db/legacy')
 const migrateFromLegacy = require('../db/legacy')
+const { setTimeout } = require('timers/promises')
 
 
 /**
 /**
  * ORM DB module
  * ORM DB module
@@ -118,7 +118,7 @@ module.exports = {
               WIKI.logger.error(`Database Connection Error: ${err.message}`)
               WIKI.logger.error(`Database Connection Error: ${err.message}`)
             }
             }
             WIKI.logger.warn(`Will retry in 3 seconds... [Attempt ${++conAttempts} of 10]`)
             WIKI.logger.warn(`Will retry in 3 seconds... [Attempt ${++conAttempts} of 10]`)
-            await new Promise(resolve => setTimeout(resolve, 3000))
+            await setTimeout(3000)
             await initTasks.connect()
             await initTasks.connect()
           } else {
           } else {
             throw err
             throw err

+ 1 - 1
server/core/kernel.js

@@ -74,9 +74,9 @@ module.exports = {
     await WIKI.db.commentProviders.initProvider()
     await WIKI.db.commentProviders.initProvider()
     await WIKI.db.sites.reloadCache()
     await WIKI.db.sites.reloadCache()
     await WIKI.db.storage.initTargets()
     await WIKI.db.storage.initTargets()
-    await WIKI.scheduler.start()
 
 
     await WIKI.db.subscribeToNotifications()
     await WIKI.db.subscribeToNotifications()
+    await WIKI.scheduler.start()
   },
   },
   /**
   /**
    * Graceful shutdown
    * Graceful shutdown

+ 3 - 0
server/core/logger.js

@@ -33,6 +33,9 @@ LEVELS.forEach(lvl => {
           message: msg
           message: msg
         })
         })
       } else {
       } else {
+        if (msg instanceof Error) {
+          msg = msg.stack
+        }
         formatted = chalk`${new Date().toISOString()} {dim [${WIKI.INSTANCE_ID}]} {${LEVELCOLORS[lvl]}.bold ${lvl}}: ${msg}`
         formatted = chalk`${new Date().toISOString()} {dim [${WIKI.INSTANCE_ID}]} {${LEVELCOLORS[lvl]}.bold ${lvl}}: ${msg}`
       }
       }
 
 

+ 46 - 38
server/core/scheduler.js

@@ -1,12 +1,11 @@
 const { DynamicThreadPool } = require('poolifier')
 const { DynamicThreadPool } = require('poolifier')
-const { v4: uuid } = require('uuid')
 const os = require('node:os')
 const os = require('node:os')
-const path = require('node:path')
+const { setTimeout } = require('node:timers/promises')
 
 
 module.exports = {
 module.exports = {
   pool: null,
   pool: null,
-  runner: null,
   maxWorkers: 1,
   maxWorkers: 1,
+  activeWorkers: 0,
   async init () {
   async init () {
     this.maxWorkers = WIKI.config.scheduler.workers === 'auto' ? os.cpus().length : WIKI.config.scheduler.workers
     this.maxWorkers = WIKI.config.scheduler.workers === 'auto' ? os.cpus().length : WIKI.config.scheduler.workers
     WIKI.logger.info(`Initializing Worker Pool (Limit: ${this.maxWorkers})...`)
     WIKI.logger.info(`Initializing Worker Pool (Limit: ${this.maxWorkers})...`)
@@ -19,46 +18,55 @@ module.exports = {
   },
   },
   async start () {
   async start () {
     WIKI.logger.info('Starting Scheduler...')
     WIKI.logger.info('Starting Scheduler...')
-    // this.runner = await run({
-    //   pgPool: new Pool({
-    //     ...(typeof WIKI.db.config === 'string') ? {
-    //       connectionString: WIKI.db.config
-    //     } : WIKI.db.config,
-    //     max: this.maxWorkers + 2
-    //   }),
-    //   schema: WIKI.config.db.schemas.scheduler,
-    //   concurrency: this.maxWorkers,
-    //   noHandleSignals: true,
-    //   logger: new Logger(scope => {
-    //     return (level, message, meta) => {
-    //       const prefix = (scope?.workerId) ? `[${scope.workerId}] ` : ''
-    //       WIKI.logger[level](`${prefix}${message}`, meta)
-    //     }
-    //   }),
-    //   parsedCronItems: parseCronItems(WIKI.data.jobs),
-    //   taskList: {
-    //     simple: async (payload, helpers) => {
-    //       // TODO: Handle task
-    //     },
-    //     background: async (payload, helpers) => {
-    //       try {
-    //         await this.pool.execute({
-    //           id: helpers.job.id,
-    //           name: payload.name,
-    //           data: payload.data
-    //         })
-    //       } catch (err) {
-    //         helpers.logger.warn(`Failed job: ${err.message}`)
-    //         throw err
-    //       }
-    //     }
-    //   }
+    WIKI.db.listener.addChannel('scheduler', payload => {
+      switch (payload.event) {
+        case 'newJob': {
+          if (this.activeWorkers < this.maxWorkers) {
+            this.activeWorkers++
+            this.processJob()
+          }
+          break
+        }
+      }
+    })
+    // await WIKI.db.knex('jobs').insert({
+    //   task: 'test',
+    //   payload: { foo: 'bar' }
+    // })
+    // WIKI.db.listener.publish('scheduler', {
+    //   source: WIKI.INSTANCE_ID,
+    //   event: 'newJob'
     // })
     // })
     WIKI.logger.info('Scheduler: [ STARTED ]')
     WIKI.logger.info('Scheduler: [ STARTED ]')
   },
   },
+  async processJob () {
+    try {
+      await WIKI.db.knex.transaction(async trx => {
+        const jobs = await trx('jobs')
+          .where('id', WIKI.db.knex.raw('(SELECT id FROM jobs ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1)'))
+          .returning('*')
+          .del()
+        if (jobs && jobs.length === 1) {
+          const job = jobs[0]
+          WIKI.logger.info(`Processing new job ${job.id}: ${job.task}...`)
+          if (job.useWorker) {
+            await this.pool.execute({
+              id: job.id,
+              name: job.task,
+              data: job.payload
+            })
+          } else {
+
+          }
+        }
+      })
+    } catch (err) {
+      WIKI.logger.warn(err)
+    }
+  },
   async stop () {
   async stop () {
     WIKI.logger.info('Stopping Scheduler...')
     WIKI.logger.info('Stopping Scheduler...')
-    // await this.runner.stop()
+    await this.pool.stop()
     WIKI.logger.info('Scheduler: [ STOPPED ]')
     WIKI.logger.info('Scheduler: [ STOPPED ]')
   }
   }
 }
 }

+ 4 - 5
server/core/servers.js

@@ -2,7 +2,6 @@ const fs = require('fs-extra')
 const http = require('http')
 const http = require('http')
 const https = require('https')
 const https = require('https')
 const { ApolloServer } = require('apollo-server-express')
 const { ApolloServer } = require('apollo-server-express')
-const Promise = require('bluebird')
 const _ = require('lodash')
 const _ = require('lodash')
 const io = require('socket.io')
 const io = require('socket.io')
 const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core')
 const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core')
@@ -188,11 +187,11 @@ module.exports = {
   async stopServers () {
   async stopServers () {
     this.closeConnections()
     this.closeConnections()
     if (this.http) {
     if (this.http) {
-      await Promise.fromCallback(cb => { this.http.close(cb) })
+      await new Promise(resolve => this.http.close(resolve))
       this.http = null
       this.http = null
     }
     }
     if (this.https) {
     if (this.https) {
-      await Promise.fromCallback(cb => { this.https.close(cb) })
+      await new Promise(resolve => this.https.close(resolve))
       this.https = null
       this.https = null
     }
     }
     this.graph = null
     this.graph = null
@@ -205,7 +204,7 @@ module.exports = {
     switch (srv) {
     switch (srv) {
       case 'http':
       case 'http':
         if (this.http) {
         if (this.http) {
-          await Promise.fromCallback(cb => { this.http.close(cb) })
+          await new Promise(resolve => this.http.close(resolve))
           this.http = null
           this.http = null
         }
         }
         this.initHTTP()
         this.initHTTP()
@@ -213,7 +212,7 @@ module.exports = {
         break
         break
       case 'https':
       case 'https':
         if (this.https) {
         if (this.https) {
-          await Promise.fromCallback(cb => { this.https.close(cb) })
+          await new Promise(resolve => this.https.close(resolve))
           this.https = null
           this.https = null
         }
         }
         this.initHTTPS()
         this.initHTTPS()

+ 2 - 0
server/db/migrations/3.0.0.js

@@ -145,7 +145,9 @@ exports.up = async knex => {
     .createTable('jobs', table => {
     .createTable('jobs', table => {
       table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))
       table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))
       table.string('task').notNullable()
       table.string('task').notNullable()
+      table.boolean('useWorker').notNullable().defaultTo(false)
       table.jsonb('payload')
       table.jsonb('payload')
+      table.timestamp('waitUntil')
       table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now())
       table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now())
       table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now())
       table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now())
     })
     })

+ 6 - 6
server/graph/resolvers/system.js

@@ -1,7 +1,7 @@
 const _ = require('lodash')
 const _ = require('lodash')
-const Promise = require('bluebird')
-const getos = Promise.promisify(require('getos'))
-const os = require('os')
+const util = require('node:util')
+const getos = util.promisify(require('getos'))
+const os = require('node:os')
 const filesize = require('filesize')
 const filesize = require('filesize')
 const path = require('path')
 const path = require('path')
 const fs = require('fs-extra')
 const fs = require('fs-extra')
@@ -105,12 +105,12 @@ module.exports = {
     currentVersion () {
     currentVersion () {
       return WIKI.version
       return WIKI.version
     },
     },
-    async dbVersion () {
-      return _.get(WIKI.models, 'knex.client.version', 'Unknown Version')
-    },
     dbHost () {
     dbHost () {
       return WIKI.config.db.host
       return WIKI.config.db.host
     },
     },
+    dbVersion () {
+      return _.get(WIKI.db, 'knex.client.version', 'Unknown Version')
+    },
     hostname () {
     hostname () {
       return os.hostname()
       return os.hostname()
     },
     },

+ 4 - 7
server/helpers/security.js

@@ -1,5 +1,6 @@
-const Promise = require('bluebird')
-const crypto = require('crypto')
+const util = require('node:util')
+const crypto = require('node:crypto')
+const randomBytes = util.promisify(crypto.randomBytes)
 const passportJWT = require('passport-jwt')
 const passportJWT = require('passport-jwt')
 
 
 module.exports = {
 module.exports = {
@@ -17,11 +18,7 @@ module.exports = {
    * @returns
    * @returns
    */
    */
   async generateToken (length) {
   async generateToken (length) {
-    return Promise.fromCallback(clb => {
-      crypto.randomBytes(length, clb)
-    }).then(buf => {
-      return buf.toString('hex')
-    })
+    return (await randomBytes(length)).toString('hex')
   },
   },
 
 
   extractJWT: passportJWT.ExtractJwt.fromExtractors([
   extractJWT: passportJWT.ExtractJwt.fromExtractors([

+ 1 - 5
server/models/assets.js

@@ -1,12 +1,9 @@
-/* global WIKI */
-
 const Model = require('objection').Model
 const Model = require('objection').Model
 const moment = require('moment')
 const moment = require('moment')
 const path = require('path')
 const path = require('path')
 const fs = require('fs-extra')
 const fs = require('fs-extra')
 const _ = require('lodash')
 const _ = require('lodash')
 const assetHelper = require('../helpers/asset')
 const assetHelper = require('../helpers/asset')
-const Promise = require('bluebird')
 
 
 /**
 /**
  * Users model
  * Users model
@@ -199,9 +196,8 @@ module.exports = class Asset extends Model {
     } catch (err) {
     } catch (err) {
       return false
       return false
     }
     }
-    const sendFile = Promise.promisify(res.sendFile, {context: res})
     res.type(path.extname(assetPath))
     res.type(path.extname(assetPath))
-    await sendFile(cachePath, { dotfiles: 'deny' })
+    await new Promise(resolve => res.sendFile(cachePath, { dotfiles: 'deny' }, resolve))
     return true
     return true
   }
   }
 
 

+ 2 - 2
server/modules/storage/azure/storage.js

@@ -1,7 +1,7 @@
 const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob')
 const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob')
 const stream = require('stream')
 const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const pageHelper = require('../../../helpers/page.js')
 const pageHelper = require('../../../helpers/page.js')
 const _ = require('lodash')
 const _ = require('lodash')
 
 

+ 4 - 4
server/modules/storage/disk/common.js

@@ -1,8 +1,8 @@
 const fs = require('fs-extra')
 const fs = require('fs-extra')
-const path = require('path')
-const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const path = require('node:path')
+const stream = require('node:stream')
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const klaw = require('klaw')
 const klaw = require('klaw')
 const mime = require('mime-types').lookup
 const mime = require('mime-types').lookup
 const _ = require('lodash')
 const _ = require('lodash')

+ 5 - 5
server/modules/storage/disk/storage.js

@@ -1,11 +1,11 @@
 const fs = require('fs-extra')
 const fs = require('fs-extra')
-const path = require('path')
+const path = require('node:path')
 const tar = require('tar-fs')
 const tar = require('tar-fs')
-const zlib = require('zlib')
-const stream = require('stream')
+const zlib = require('node:zlib')
+const stream = require('node:stream')
 const _ = require('lodash')
 const _ = require('lodash')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const moment = require('moment')
 const moment = require('moment')
 
 
 const pageHelper = require('../../../helpers/page')
 const pageHelper = require('../../../helpers/page')

+ 3 - 3
server/modules/storage/gcs/storage.js

@@ -1,7 +1,7 @@
 const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob')
 const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob')
-const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const stream = require('node:stream')
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const pageHelper = require('../../../helpers/page.js')
 const pageHelper = require('../../../helpers/page.js')
 const _ = require('lodash')
 const _ = require('lodash')
 
 

+ 5 - 5
server/modules/storage/git/storage.js

@@ -1,12 +1,12 @@
-const path = require('path')
+const path = require('node:path')
 const sgit = require('simple-git/promise')
 const sgit = require('simple-git/promise')
 const fs = require('fs-extra')
 const fs = require('fs-extra')
 const _ = require('lodash')
 const _ = require('lodash')
-const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const stream = require('node:stream')
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const klaw = require('klaw')
 const klaw = require('klaw')
-const os = require('os')
+const os = require('node:os')
 
 
 const pageHelper = require('../../../helpers/page')
 const pageHelper = require('../../../helpers/page')
 const assetHelper = require('../../../helpers/asset')
 const assetHelper = require('../../../helpers/asset')

+ 3 - 3
server/modules/storage/s3/storage.js

@@ -1,7 +1,7 @@
 const S3 = require('aws-sdk/clients/s3')
 const S3 = require('aws-sdk/clients/s3')
-const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const stream = require('node:stream')
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const _ = require('lodash')
 const _ = require('lodash')
 const pageHelper = require('../../../helpers/page.js')
 const pageHelper = require('../../../helpers/page.js')
 
 

+ 4 - 4
server/modules/storage/sftp/storage.js

@@ -1,9 +1,9 @@
 const SSH2Promise = require('ssh2-promise')
 const SSH2Promise = require('ssh2-promise')
 const _ = require('lodash')
 const _ = require('lodash')
-const path = require('path')
-const stream = require('stream')
-const Promise = require('bluebird')
-const pipeline = Promise.promisify(stream.pipeline)
+const path = require('node:path')
+const stream = require('node:stream')
+const util = require('node:util')
+const pipeline = util.promisify(stream.pipeline)
 const pageHelper = require('../../../helpers/page.js')
 const pageHelper = require('../../../helpers/page.js')
 
 
 const getFilePath = (page, pathKey) => {
 const getFilePath = (page, pathKey) => {

+ 8 - 93
yarn.lock

@@ -2490,11 +2490,6 @@
   dependencies:
   dependencies:
     passport-oauth2 "^1.4.0"
     passport-oauth2 "^1.4.0"
 
 
-"@graphile/logger@^0.2.0":
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/@graphile/logger/-/logger-0.2.0.tgz#e484ec420162157c6e6f0cfb080fa29ef3a714ba"
-  integrity sha512-jjcWBokl9eb1gVJ85QmoaQ73CQ52xAaOCF29ukRbYNl6lY+ts0ErTaDYOBlejcbUs2OpaiqYLO5uDhyLFzWw4w==
-
 "@graphql-tools/merge@8.2.7":
 "@graphql-tools/merge@8.2.7":
   version "8.2.7"
   version "8.2.7"
   resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.7.tgz#add05bcc47df6b7390f31acbcadd986e160d58f9"
   resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.7.tgz#add05bcc47df6b7390f31acbcadd986e160d58f9"
@@ -3091,13 +3086,6 @@
   resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
   resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
   integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
   integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
 
 
-"@types/debug@^4.1.2":
-  version "4.1.7"
-  resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82"
-  integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==
-  dependencies:
-    "@types/ms" "*"
-
 "@types/debug@^4.1.5":
 "@types/debug@^4.1.5":
   version "4.1.5"
   version "4.1.5"
   resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
   resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
@@ -3236,11 +3224,6 @@
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
   integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
   integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
 
 
-"@types/ms@*":
-  version "0.7.31"
-  resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
-  integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
-
 "@types/node-fetch@^2.5.0":
 "@types/node-fetch@^2.5.0":
   version "2.5.4"
   version "2.5.4"
   resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.4.tgz#5245b6d8841fc3a6208b82291119bc11c4e0ce44"
   resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.4.tgz#5245b6d8841fc3a6208b82291119bc11c4e0ce44"
@@ -3268,20 +3251,6 @@
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
   integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
   integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
 
 
-"@types/parse-json@^4.0.0":
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
-  integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
-
-"@types/pg@>=6 <9":
-  version "8.6.5"
-  resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.5.tgz#2dce9cb468a6a5e0f1296a59aea3ac75dd27b702"
-  integrity sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==
-  dependencies:
-    "@types/node" "*"
-    pg-protocol "*"
-    pg-types "^2.2.0"
-
 "@types/prettier@^2.0.0":
 "@types/prettier@^2.0.0":
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4"
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4"
@@ -4926,16 +4895,16 @@ blob-util@2.0.2:
   resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
   resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
   integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
   integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
 
 
-bluebird@3.7.2, bluebird@^3.7.2:
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
-  integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-
 bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.5:
 bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.5:
   version "3.5.5"
   version "3.5.5"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
   integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
   integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
 
 
+bluebird@^3.7.2:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+  integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
 bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
 bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
   version "4.11.8"
   version "4.11.8"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
@@ -6363,17 +6332,6 @@ cosmiconfig@^5.0.0:
     js-yaml "^3.13.1"
     js-yaml "^3.13.1"
     parse-json "^4.0.0"
     parse-json "^4.0.0"
 
 
-cosmiconfig@^7.0.0:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
-  integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
-  dependencies:
-    "@types/parse-json" "^4.0.0"
-    import-fresh "^3.2.1"
-    parse-json "^5.0.0"
-    path-type "^4.0.0"
-    yaml "^1.10.0"
-
 cpu-features@0.0.2:
 cpu-features@0.0.2:
   version "0.0.2"
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.2.tgz#9f636156f1155fd04bdbaa028bb3c2fbef3cea7a"
   resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.2.tgz#9f636156f1155fd04bdbaa028bb3c2fbef3cea7a"
@@ -9591,21 +9549,6 @@ graceful-fs@^4.2.4:
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
   integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
   integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
 
 
-graphile-worker@0.13.0:
-  version "0.13.0"
-  resolved "https://registry.yarnpkg.com/graphile-worker/-/graphile-worker-0.13.0.tgz#8cf2ef75d1d58f2a634c4dcb7fe700c4fda9a77f"
-  integrity sha512-8Hl5XV6hkabZRhYzvbUfvjJfPFR5EPxYRVWlzQC2rqYHrjULTLBgBYZna5R9ukbnsbWSvn4vVrzOBIOgIC1jjw==
-  dependencies:
-    "@graphile/logger" "^0.2.0"
-    "@types/debug" "^4.1.2"
-    "@types/pg" ">=6 <9"
-    chokidar "^3.4.0"
-    cosmiconfig "^7.0.0"
-    json5 "^2.1.3"
-    pg ">=6.5 <9"
-    tslib "^2.1.0"
-    yargs "^16.2.0"
-
 graphlib@^2.1.7, graphlib@^2.1.8:
 graphlib@^2.1.7, graphlib@^2.1.8:
   version "2.1.8"
   version "2.1.8"
   resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
   resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
@@ -11524,11 +11467,6 @@ json5@^2.1.2:
   dependencies:
   dependencies:
     minimist "^1.2.5"
     minimist "^1.2.5"
 
 
-json5@^2.1.3:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
-  integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
-
 jsonfile@^4.0.0:
 jsonfile@^4.0.0:
   version "4.0.0"
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
   resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -14043,7 +13981,7 @@ pg-pool@^3.5.2:
   resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.5.2.tgz#ed1bed1fb8d79f1c6fd5fb1c99e990fbf9ddf178"
   resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.5.2.tgz#ed1bed1fb8d79f1c6fd5fb1c99e990fbf9ddf178"
   integrity sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==
   integrity sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==
 
 
-pg-protocol@*, pg-protocol@^1.5.0:
+pg-protocol@^1.5.0:
   version "1.5.0"
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.5.0.tgz#b5dd452257314565e2d54ab3c132adc46565a6a0"
   resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.5.0.tgz#b5dd452257314565e2d54ab3c132adc46565a6a0"
   integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==
   integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==
@@ -14070,7 +14008,7 @@ pg-tsquery@8.4.0:
   resolved "https://registry.yarnpkg.com/pg-tsquery/-/pg-tsquery-8.4.0.tgz#411293cce23ca1eeb8c29109af9fadf28f20a7d9"
   resolved "https://registry.yarnpkg.com/pg-tsquery/-/pg-tsquery-8.4.0.tgz#411293cce23ca1eeb8c29109af9fadf28f20a7d9"
   integrity sha512-m0jIxUVwLKSdmOAlqtlbo6K+EFIOZ/hyOMnoe8DmYFqEmOmvafIjGQFmcPP+z5MWd/p7ExxoKNIL31gmM+CwxQ==
   integrity sha512-m0jIxUVwLKSdmOAlqtlbo6K+EFIOZ/hyOMnoe8DmYFqEmOmvafIjGQFmcPP+z5MWd/p7ExxoKNIL31gmM+CwxQ==
 
 
-pg-types@^2.1.0, pg-types@^2.2.0:
+pg-types@^2.1.0:
   version "2.2.0"
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
   resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
   integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
   integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
@@ -14081,7 +14019,7 @@ pg-types@^2.1.0, pg-types@^2.2.0:
     postgres-date "~1.0.4"
     postgres-date "~1.0.4"
     postgres-interval "^1.1.0"
     postgres-interval "^1.1.0"
 
 
-pg@8.8.0, "pg@>=6.5 <9", pg@^8.7.3:
+pg@8.8.0, pg@^8.7.3:
   version "8.8.0"
   version "8.8.0"
   resolved "https://registry.yarnpkg.com/pg/-/pg-8.8.0.tgz#a77f41f9d9ede7009abfca54667c775a240da686"
   resolved "https://registry.yarnpkg.com/pg/-/pg-8.8.0.tgz#a77f41f9d9ede7009abfca54667c775a240da686"
   integrity sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==
   integrity sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==
@@ -19373,11 +19311,6 @@ y18n@^5.0.2:
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
   integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==
   integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==
 
 
-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.1.2:
 yallist@^2.1.2:
   version "2.1.2"
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
@@ -19393,11 +19326,6 @@ yallist@^4.0.0:
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
   integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
   integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
 
 
-yaml@^1.10.0:
-  version "1.10.2"
-  resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
-  integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-
 yargs-parser@^13.1.2:
 yargs-parser@^13.1.2:
   version "13.1.2"
   version "13.1.2"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
@@ -19497,19 +19425,6 @@ yargs@^15.4.1:
     y18n "^4.0.0"
     y18n "^4.0.0"
     yargs-parser "^18.1.2"
     yargs-parser "^18.1.2"
 
 
-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:
 yargs@^7.1.0:
   version "7.1.0"
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"