From 33547ddce90e21b03cac6ea238a6744d447c65bf Mon Sep 17 00:00:00 2001 From: Nicolas Giard Date: Sun, 11 Sep 2022 00:59:38 +0000 Subject: [PATCH] feat: site logo upload + extensions fix --- .gitignore | 2 +- package.json | 2 + server/controllers/common.js | 24 +++ server/core/servers.js | 5 +- server/db/migrations/3.0.0.js | 15 +- server/graph/resolvers/hooks.js | 1 - server/graph/resolvers/site.js | 27 ++- server/graph/resolvers/system.js | 4 +- server/models/sites.js | 5 + server/modules/extensions/git/ext.js | 1 + server/modules/extensions/pandoc/ext.js | 1 + server/modules/extensions/puppeteer/ext.js | 25 ++- server/modules/extensions/sharp/ext.js | 69 ++++++- server/views/base.pug | 12 +- server/web.js | 3 +- ux/quasar.config.js | 3 +- ux/src/layouts/AuthLayout.vue | 68 ------- ux/src/pages/AdminExtensions.vue | 6 +- ux/src/pages/AdminGeneral.vue | 10 +- ux/src/pages/Login.vue | 74 ++++++- ux/src/stores/site.js | 4 +- yarn.lock | 215 +++++++++++++++++++-- 22 files changed, 465 insertions(+), 111 deletions(-) diff --git a/.gitignore b/.gitignore index 2db728f8..793f2a63 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ npm-debug.log* # Generated assets /assets /assets-legacy -server/views/base.pug +/server/views/base.pug # Webpack .webpack-cache diff --git a/package.json b/package.json index e1725b2e..d3990164 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,7 @@ "pg-tsquery": "8.4.0", "pug": "3.0.2", "punycode": "2.1.1", + "puppeteer-core": "17.1.3", "qr-image": "3.2.0", "rate-limiter-flexible": "2.3.8", "remove-markdown": "0.3.0", @@ -164,6 +165,7 @@ "scim-query-filter-parser": "2.0.4", "semver": "7.3.7", "serve-favicon": "2.5.0", + "sharp": "0.31.0", "simple-git": "2.21.0", "socket.io": "4.5.2", "ssh2": "1.9.0", diff --git a/server/controllers/common.js b/server/controllers/common.js index d55ff351..805d2537 100644 --- a/server/controllers/common.js +++ b/server/controllers/common.js @@ -9,6 +9,7 @@ const path = require('path') /* global WIKI */ const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/ +const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets') /** * Robots.txt @@ -33,6 +34,29 @@ router.get('/healthz', (req, res, next) => { } }) +/** + * Site Asset + */ +router.get('/_site/:siteId?/:resource', async (req, res, next) => { + const site = req.params.siteId ? WIKI.sites[req.params.siteId] : await WIKI.models.sites.getSiteByHostname({ hostname: req.hostname }) + if (!site) { + return res.status(404).send('Site Not Found') + } + switch (req.params.resource) { + case 'logo': { + if (site.config.assets.logo) { + res.sendFile(path.join(siteAssetsPath, `logo-${site.id}.${site.config.assets.logoExt}`)) + } else { + res.sendFile(path.join(WIKI.ROOTPATH, 'assets/_assets/logo-wikijs.svg')) + } + break + } + default: { + return res.status(404).send('Invalid Site Resource') + } + } +}) + /** * New v3 vue app */ diff --git a/server/core/servers.js b/server/core/servers.js index 5ba59982..60fe51c2 100644 --- a/server/core/servers.js +++ b/server/core/servers.js @@ -6,6 +6,7 @@ const Promise = require('bluebird') const _ = require('lodash') const io = require('socket.io') const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core') +const { graphqlUploadExpress } = require('graphql-upload') /* global WIKI */ @@ -132,7 +133,8 @@ module.exports = { const graphqlSchema = require('../graph') this.graph = new ApolloServer({ schema: graphqlSchema, - uploads: false, + csrfPrevention: true, + cache: 'bounded', context: ({ req, res }) => ({ req, res }), plugins: [ process.env.NODE_ENV === 'development' ? ApolloServerPluginLandingPageGraphQLPlayground({ @@ -145,6 +147,7 @@ module.exports = { ] }) await this.graph.start() + WIKI.app.use(graphqlUploadExpress()) this.graph.applyMiddleware({ app: WIKI.app, cors: false, path: '/_graphql' }) }, /** diff --git a/server/db/migrations/3.0.0.js b/server/db/migrations/3.0.0.js index 063114af..f23ef345 100644 --- a/server/db/migrations/3.0.0.js +++ b/server/db/migrations/3.0.0.js @@ -56,7 +56,7 @@ exports.up = async knex => { }) // ASSET DATA -------------------------- .createTable('assetData', table => { - table.uuid('id').notNullable().index() + table.uuid('id').notNullable().primary() table.binary('data').notNullable() }) // ASSET FOLDERS ----------------------- @@ -485,6 +485,11 @@ exports.up = async knex => { locale: 'en', localeNamespacing: false, localeNamespaces: [], + assets: { + logo: false, + logoExt: 'svg', + favicon: false + }, theme: { dark: false, colorPrimary: '#1976D2', @@ -580,10 +585,18 @@ exports.up = async knex => { { id: userGuestId, email: 'guest@example.com', + auth: {}, name: 'Guest', isSystem: true, isActive: true, isVerified: true, + meta: {}, + prefs: { + timezone: 'America/New_York', + dateFormat: 'YYYY-MM-DD', + timeFormat: '12h', + darkMode: false + }, localeCode: 'en' } ]) diff --git a/server/graph/resolvers/hooks.js b/server/graph/resolvers/hooks.js index cf30dd6a..99619b2c 100644 --- a/server/graph/resolvers/hooks.js +++ b/server/graph/resolvers/hooks.js @@ -6,7 +6,6 @@ const _ = require('lodash') module.exports = { Query: { async hooks () { - WIKI.logger.warn('Seriously man') return WIKI.models.hooks.query().orderBy('name') }, async hookById (obj, args) { diff --git a/server/graph/resolvers/site.js b/server/graph/resolvers/site.js index 9dd1b24e..7e8affbb 100644 --- a/server/graph/resolvers/site.js +++ b/server/graph/resolvers/site.js @@ -2,6 +2,8 @@ const graphHelper = require('../../helpers/graph') const _ = require('lodash') const CleanCSS = require('clean-css') const path = require('path') +const fs = require('fs-extra') +const { v4: uuid } = require('uuid') /* global WIKI */ @@ -154,24 +156,41 @@ module.exports = { if (!WIKI.extensions.ext.sharp.isInstalled) { throw new Error('This feature requires the Sharp extension but it is not installed.') } - console.info(mimetype) const destFormat = mimetype.startsWith('image/svg') ? 'svg' : 'png' - const destPath = path.resolve( + const destFolder = path.resolve( process.cwd(), WIKI.config.dataPath, - `assets/logo.${destFormat}` + `assets` ) + const destPath = path.join(destFolder, `logo-${args.id}.${destFormat}`) + await fs.ensureDir(destFolder) + // -> Resize await WIKI.extensions.ext.sharp.resize({ format: destFormat, inputStream: createReadStream(), outputPath: destPath, - width: 100 + height: 72 }) + // -> Save logo meta to DB + const site = await WIKI.models.sites.query().findById(args.id) + if (!site.config.assets.logo) { + site.config.assets.logo = uuid() + } + site.config.assets.logoExt = destFormat + await WIKI.models.sites.query().findById(args.id).patch({ config: site.config }) + await WIKI.models.sites.reloadCache() + // -> Save image data to DB + const imgBuffer = await fs.readFile(destPath) + await WIKI.models.knex('assetData').insert({ + id: site.config.assets.logo, + data: imgBuffer + }).onConflict('id').merge() WIKI.logger.info('New site logo processed successfully.') return { operation: graphHelper.generateSuccess('Site logo uploaded successfully') } } catch (err) { + WIKI.logger.warn(err) return graphHelper.generateError(err) } }, diff --git a/server/graph/resolvers/system.js b/server/graph/resolvers/system.js index 50ac3f11..33d9af3d 100644 --- a/server/graph/resolvers/system.js +++ b/server/graph/resolvers/system.js @@ -42,7 +42,7 @@ module.exports = { await WIKI.extensions.ext[args.key].install() // TODO: broadcast ext install return { - status: graphHelper.generateSuccess('Extension installed successfully') + operation: graphHelper.generateSuccess('Extension installed successfully') } } catch (err) { return graphHelper.generateError(err) @@ -55,7 +55,7 @@ module.exports = { await WIKI.configSvc.applyFlags() await WIKI.configSvc.saveToDb(['flags']) return { - status: graphHelper.generateSuccess('System Flags applied successfully') + operation: graphHelper.generateSuccess('System Flags applied successfully') } }, async updateSystemSecurity (obj, args, context) { diff --git a/server/models/sites.js b/server/models/sites.js index f6cf247a..fbdfb40b 100644 --- a/server/models/sites.js +++ b/server/models/sites.js @@ -84,6 +84,11 @@ module.exports = class Site extends Model { locale: 'en', localeNamespacing: false, localeNamespaces: [], + assets: { + logo: false, + logoExt: 'svg', + favicon: false + }, theme: { dark: false, colorPrimary: '#1976D2', diff --git a/server/modules/extensions/git/ext.js b/server/modules/extensions/git/ext.js index 63484263..598c935c 100644 --- a/server/modules/extensions/git/ext.js +++ b/server/modules/extensions/git/ext.js @@ -5,6 +5,7 @@ module.exports = { title: 'Git', description: 'Distributed version control system. Required for the Git storage module.', isInstalled: false, + isInstallable: false, async isCompatible () { return true }, diff --git a/server/modules/extensions/pandoc/ext.js b/server/modules/extensions/pandoc/ext.js index 6efa93c6..d68f481b 100644 --- a/server/modules/extensions/pandoc/ext.js +++ b/server/modules/extensions/pandoc/ext.js @@ -9,6 +9,7 @@ module.exports = { return os.arch() === 'x64' }, isInstalled: false, + isInstallable: false, async check () { try { await cmdExists('pandoc') diff --git a/server/modules/extensions/puppeteer/ext.js b/server/modules/extensions/puppeteer/ext.js index aa80110a..29de79f2 100644 --- a/server/modules/extensions/puppeteer/ext.js +++ b/server/modules/extensions/puppeteer/ext.js @@ -1,5 +1,10 @@ -const cmdExists = require('command-exists') const os = require('os') +const path = require('path') +const util = require('util') +const exec = util.promisify(require('child_process').exec) +const fs = require('fs-extra') + +/* global WIKI */ module.exports = { key: 'puppeteer', @@ -9,13 +14,27 @@ module.exports = { return os.arch() === 'x64' }, isInstalled: false, + isInstallable: true, async check () { try { - await cmdExists('pandoc') - this.isInstalled = true + this.isInstalled = await fs.pathExists(path.join(process.cwd(), 'node_modules/puppeteer-core/.local-chromium')) } catch (err) { this.isInstalled = false } return this.isInstalled + }, + async install () { + try { + const { stdout, stderr } = await exec('node install.js', { + cwd: path.join(process.cwd(), 'node_modules/puppeteer-core'), + timeout: 300000, + windowsHide: true + }) + this.isInstalled = true + WIKI.logger.info(stdout) + WIKI.logger.warn(stderr) + } catch (err) { + WIKI.logger.error(err) + } } } diff --git a/server/modules/extensions/sharp/ext.js b/server/modules/extensions/sharp/ext.js index af45a819..63b45bf3 100644 --- a/server/modules/extensions/sharp/ext.js +++ b/server/modules/extensions/sharp/ext.js @@ -1,6 +1,9 @@ const fs = require('fs-extra') const os = require('os') const path = require('path') +const util = require('util') +const exec = util.promisify(require('child_process').exec) +const { pipeline } = require('stream/promises') /* global WIKI */ @@ -12,8 +15,72 @@ module.exports = { return os.arch() === 'x64' }, isInstalled: false, + isInstallable: true, async check () { - this.isInstalled = await fs.pathExists(path.join(WIKI.ROOTPATH, 'node_modules/sharp')) + this.isInstalled = await fs.pathExists(path.join(process.cwd(), 'node_modules/sharp/wiki_installed.txt')) return this.isInstalled + }, + async install () { + try { + const { stdout, stderr } = await exec('node install/libvips && node install/dll-copy', { + cwd: path.join(process.cwd(), 'node_modules/sharp'), + timeout: 120000, + windowsHide: true + }) + await fs.ensureFile(path.join(process.cwd(), 'node_modules/sharp/wiki_installed.txt')) + this.isInstalled = true + WIKI.logger.info(stdout) + WIKI.logger.warn(stderr) + } catch (err) { + WIKI.logger.error(err) + } + }, + sharp: null, + async load () { + if (!this.sharp) { + this.sharp = require('sharp') + } + }, + /** + * RESIZE IMAGE + */ + async resize ({ + format = 'png', + inputStream = null, + inputPath = null, + outputStream = null, + outputPath = null, + width = null, + height = null, + fit = 'cover', + background = { r: 0, g: 0, b: 0, alpha: 0 } + }) { + this.load() + + if (inputPath) { + inputStream = fs.createReadStream(inputPath) + } + if (!inputStream) { + throw new Error('Failed to open readable input stream for image resizing.') + } + if (outputPath) { + outputStream = fs.createWriteStream(outputPath) + } + if (!outputStream) { + throw new Error('Failed to open writable output stream for image resizing.') + } + + if (format === 'svg') { + return pipeline([inputStream, outputStream]) + } else { + const transformer = this.sharp().resize({ + width, + height, + fit, + background + }).toFormat(format) + + return pipeline([inputStream, transformer, outputStream]) + } } } diff --git a/server/views/base.pug b/server/views/base.pug index 87a39f78..fc252f35 100644 --- a/server/views/base.pug +++ b/server/views/base.pug @@ -54,20 +54,28 @@ html(lang=siteConfig.lang) //- CSS + + link( + type='text/css' + rel='stylesheet' + href='/_assets-legacy/css/app.629ebe3c082227dbee31.css' + ) + + //- JS script( type='text/javascript' - src='/_assets-legacy/js/runtime.js' + src='/_assets-legacy/js/runtime.js?1662846772' ) script( type='text/javascript' - src='/_assets-legacy/js/app.js' + src='/_assets-legacy/js/app.js?1662846772' ) diff --git a/server/web.js b/server/web.js index a2b61ba0..6b2196a1 100644 --- a/server/web.js +++ b/server/web.js @@ -181,8 +181,7 @@ module.exports = async () => { lang: currentSite.config.locale, rtl: false, // TODO: handle RTL company: currentSite.config.company, - contentLicense: currentSite.config.contentLicense, - logoUrl: currentSite.config.logoUrl + contentLicense: currentSite.config.contentLicense } res.locals.langs = await WIKI.models.locales.getNavLocales({ cache: true }) res.locals.analyticsCode = await WIKI.models.analytics.getCode({ cache: true }) diff --git a/ux/quasar.config.js b/ux/quasar.config.js index 1266940c..270a0a35 100644 --- a/ux/quasar.config.js +++ b/ux/quasar.config.js @@ -97,7 +97,8 @@ module.exports = configure(function (/* ctx */) { open: false, // opens browser window automatically port: 3001, proxy: { - '/_graphql': 'http://localhost:3000/_graphql' + '/_graphql': 'http://localhost:3000/_graphql', + '/_site': 'http://localhost:3000' } }, diff --git a/ux/src/layouts/AuthLayout.vue b/ux/src/layouts/AuthLayout.vue index 673110bd..4cb6cf4d 100644 --- a/ux/src/layouts/AuthLayout.vue +++ b/ux/src/layouts/AuthLayout.vue @@ -9,73 +9,5 @@ q-layout(view='hHh lpr lff') diff --git a/ux/src/pages/AdminExtensions.vue b/ux/src/pages/AdminExtensions.vue index 684e6fe1..de8a5cf9 100644 --- a/ux/src/pages/AdminExtensions.vue +++ b/ux/src/pages/AdminExtensions.vue @@ -174,7 +174,7 @@ async function install (ext) { installExtension ( key: $key ) { - status { + operation { succeeded message } @@ -185,7 +185,7 @@ async function install (ext) { key: ext.key } }) - if (respRaw.data?.installExtension?.status?.succeeded) { + if (respRaw.data?.installExtension?.operation?.succeeded) { $q.notify({ type: 'positive', message: t('admin.extensions.installSuccess') @@ -193,7 +193,7 @@ async function install (ext) { ext.isInstalled = true // this.$forceUpdate() } else { - throw new Error(respRaw.data?.installExtension?.status?.message || 'An unexpected error occured') + throw new Error(respRaw.data?.installExtension?.operation?.message || 'An unexpected error occured') } } catch (err) { $q.notify({ diff --git a/ux/src/pages/AdminGeneral.vue b/ux/src/pages/AdminGeneral.vue index fc3af28f..16e00055 100644 --- a/ux/src/pages/AdminGeneral.vue +++ b/ux/src/pages/AdminGeneral.vue @@ -255,16 +255,16 @@ q-page.admin-general dark style='height: 64px;' ) - q-btn(dense, flat, to='/') + q-btn(dense, flat, v-if='adminStore.currentSiteId') q-avatar( v-if='state.config.logoText' size='34px' square ) - img(src='/_assets/logo-wikijs.svg') + img(:src='`/_site/` + adminStore.currentSiteId + `/logo?` + state.assetTimestamp') img( v-else - src='https://m.media-amazon.com/images/G/01/audibleweb/arya/navigation/audible_logo._V517446980_.svg' + :src='`/_site/` + adminStore.currentSiteId + `/logo?` + state.assetTimestamp' style='height: 34px;' ) q-toolbar-title.text-h6(v-if='state.config.logoText') {{state.config.title}} @@ -456,6 +456,7 @@ useMeta({ const state = reactive({ loading: 0, + assetTimestamp: (new Date()).toISOString(), config: { hostname: '', title: '', @@ -678,7 +679,7 @@ async function uploadLogo () { id: $id image: $image ) { - status { + operation { succeeded slug message @@ -695,6 +696,7 @@ async function uploadLogo () { type: 'positive', message: t('admin.general.logoUploadSuccess') }) + state.assetTimestamp = (new Date()).toISOString() } catch (err) { $q.notify({ type: 'negative', diff --git a/ux/src/pages/Login.vue b/ux/src/pages/Login.vue index 7fc6857c..65f31027 100644 --- a/ux/src/pages/Login.vue +++ b/ux/src/pages/Login.vue @@ -2,8 +2,8 @@ .auth .auth-content .auth-logo - img(src='/_assets/logo-wikijs.svg' :alt='siteStore.title') - h2.auth-site-title {{ siteStore.title }} + img(src='/_site/logo' :alt='siteStore.title') + h2.auth-site-title(v-if='siteStore.logoText') {{ siteStore.title }} p.text-grey-7 Login to continue auth-login-panel .auth-bg(aria-hidden="true") @@ -412,5 +412,75 @@ onMounted(() => { diff --git a/ux/src/stores/site.js b/ux/src/stores/site.js index 0e5edaec..37b78977 100644 --- a/ux/src/stores/site.js +++ b/ux/src/stores/site.js @@ -13,7 +13,7 @@ export const useSiteStore = defineStore('site', { dark: false, title: '', description: '', - logoUrl: '', + logoText: true, search: '', searchIsFocused: false, searchIsLoading: false, @@ -98,7 +98,7 @@ export const useSiteStore = defineStore('site', { this.hostname = clone(siteInfo.hostname) this.title = clone(siteInfo.title) this.description = clone(siteInfo.description) - this.logoUrl = clone(siteInfo.logoUrl) + this.logoText = clone(siteInfo.logoText) this.company = clone(siteInfo.company) this.contentLicense = clone(siteInfo.contentLicense) this.theme = { diff --git a/yarn.lock b/yarn.lock index 23884a90..9cd0b5ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3368,6 +3368,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@types/zen-observable@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" @@ -5166,7 +5173,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.5.0: +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -5928,6 +5935,14 @@ color-string@^1.4.0, color-string@^1.5.2: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + color@^0.11.0: version "0.11.4" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" @@ -5961,6 +5976,14 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +color@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + colorette@2.0.19: version "2.0.19" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" @@ -6363,6 +6386,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-fetch@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-fetch@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-1.1.1.tgz#dede6865ae30f37eae62ac90ebb7bdac002b05a0" @@ -7364,6 +7394,13 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + deep-extend@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" @@ -7507,11 +7544,21 @@ detect-libc@^1.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-libc@^2.0.0, detect-libc@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +devtools-protocol@0.0.1036444: + version "0.0.1036444" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1036444.tgz#a570d3cdde61527c82f9b03919847b8ac7b1c2b9" + integrity sha512-0y4f/T8H9lsESV9kKP1HDUXgHxCdniFeJh6Erq+FbdOEvp/Ydp9t8kcAAM5gOd17pMrTDlFWntoHtzzeTUWKNw== + dezalgo@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -8516,6 +8563,11 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" @@ -8664,6 +8716,17 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extract-zip@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" @@ -9292,6 +9355,11 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -9956,6 +10024,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -12346,6 +12422,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + mini-css-extract-plugin@0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6" @@ -12396,6 +12477,11 @@ minimist@^1.1.1, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.3: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -12481,6 +12567,11 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz#54c441ce4c96cd7790e10b41a87aa51068ecab2b" integrity sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g== +mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" @@ -12645,6 +12736,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -12717,6 +12813,18 @@ node-2fa@1.1.2: notp "^2.0.3" thirty-two "0.0.2" +node-abi@^3.3.0: + version "3.24.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.24.0.tgz#b9d03393a49f2c7e147d0c99f180e680c27c1599" + integrity sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw== + dependencies: + semver "^7.3.5" + +node-addon-api@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501" + integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA== + node-cache@5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" @@ -12732,7 +12840,7 @@ node-fetch@1.7.3: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.1, node-fetch@^2.6.7: +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== @@ -15039,6 +15147,24 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +prebuild-install@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" + integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -15119,7 +15245,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0: +progress@2.0.3, progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -15181,6 +15307,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -15464,6 +15595,23 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" +puppeteer-core@17.1.3: + version "17.1.3" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-17.1.3.tgz#3a8e16c9a251f3592e1ad06a11edd9a813df9698" + integrity sha512-gm3d5fTVEc+h7jVtT3Y1k8OL1awaOzln44UfsJhUJKH/tyO/wn/zOxyAHTQt9aX/yo37IS0dfisU3i3P8qvZnw== + dependencies: + cross-fetch "3.1.5" + debug "4.3.4" + devtools-protocol "0.0.1036444" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + progress "2.0.3" + proxy-from-env "1.1.0" + rimraf "3.0.2" + tar-fs "2.1.1" + unbzip2-stream "1.4.3" + ws "8.8.1" + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -16253,6 +16401,13 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" +rimraf@3.0.2, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -16267,13 +16422,6 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@~2.4.0: version "2.4.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" @@ -16522,7 +16670,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.7: +semver@7.3.7, semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -16679,6 +16827,20 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +sharp@0.31.0: + version "0.31.0" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.31.0.tgz#ce9b5202a5667486721cf07fd5b52360b1c2275a" + integrity sha512-ft96f8WzGxavg0rkLpMw90MTPMUZDyf0tHjPPh8Ob59xt6KzX8EqtotcqZGUm7kwqpX2pmYiyYX2LL0IZ/FDEw== + dependencies: + color "^4.2.3" + detect-libc "^2.0.1" + node-addon-api "^5.0.0" + prebuild-install "^7.1.1" + semver "^7.3.7" + simple-get "^4.0.1" + tar-fs "^2.1.1" + tunnel-agent "^0.6.0" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -16732,6 +16894,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0, simple-get@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-git@2.21.0: version "2.21.0" resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-2.21.0.tgz#d25d3fdc6a139cd7f80f197541a6f9f6e9d4cbc8" @@ -17457,7 +17633,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar-fs@2.1.1: +tar-fs@2.1.1, tar-fs@^2.0.0, tar-fs@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== @@ -17609,7 +17785,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@2: +through@2, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -17982,6 +18158,14 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unbzip2-stream@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -18977,6 +19161,11 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@8.8.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + ws@^6.0.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"