From a93459d01ef63262443b7a855134d9d1a96d4618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20H=C3=A4nninen?= Date: Thu, 20 Jan 2022 10:12:10 +0200 Subject: [PATCH 1/7] Merge pull request #303 from HSLdevcom/MM-314 MM-314 Add worker queue --- .env | 1 + .env.dev | 1 + .env.production | 1 + .env.stage | 1 + Dockerfile | 1 + README.md | 39 ++++-- constants.js | 1 + package.json | 4 + scripts/fileHandler.js | 82 ++++++++++++ scripts/server.js | 56 +++----- scripts/{generator.js => worker.js} | 162 +++++++++++------------ yarn.lock | 194 +++++++++++++++++++++++++++- 12 files changed, 411 insertions(+), 132 deletions(-) create mode 100644 scripts/fileHandler.js rename scripts/{generator.js => worker.js} (58%) diff --git a/.env b/.env index d13ae591..a06142d2 100644 --- a/.env +++ b/.env @@ -1,4 +1,5 @@ PG_CONNECTION_STRING= +REDIS_CONNECTION_STRING= JORE_GRAPHQL_URL=https://dev.kartat.hsl.fi/jore/graphql GENERATE_API_URL=http://localhost:8000 diff --git a/.env.dev b/.env.dev index 463cf024..defaead9 100644 --- a/.env.dev +++ b/.env.dev @@ -1,4 +1,5 @@ PG_CONNECTION_STRING= +REDIS_CONNECTION_STRING= JORE_GRAPHQL_URL=https://dev.kartat.hsl.fi/jore/graphql GENERATE_API_URL=https://dev.kartat.hsl.fi/map-generator diff --git a/.env.production b/.env.production index e5ca33d2..5aa7bf62 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,5 @@ PG_CONNECTION_STRING= +REDIS_CONNECTION_STRING= JORE_GRAPHQL_URL=https://prod.kartat.hsl.fi/jore/graphql GENERATE_API_URL=https://prod.kartat.hsl.fi/map-generator diff --git a/.env.stage b/.env.stage index 80ea70a7..2bfa00b4 100644 --- a/.env.stage +++ b/.env.stage @@ -1,4 +1,5 @@ PG_CONNECTION_STRING= +REDIS_CONNECTION_STRING= JORE_GRAPHQL_URL=https://stage.kartat.hsl.fi/jore/graphql GENERATE_API_URL=https://stage.kartat.hsl.fi/map-generator diff --git a/Dockerfile b/Dockerfile index 4d64f3bb..9a3ab6b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,5 +42,6 @@ CMD \ fc-cache -f -v && \ yarn run start:production && \ yarn run server:production && \ + yarn run worker:production && \ sleep 3 && \ node_modules/.bin/forever -f logs 1 diff --git a/README.md b/README.md index 6b39c178..0faffea2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# HSL Map Publisher +# HSL Map Publisher (Julistegeneraattori) This project is the server-side component of the poster publisher (the UI can be found in [HSLdevcom/hsl-map-publisher-ui](https://github.com/HSLdevcom/hsl-map-publisher-ui)) that generates the stop posters that you see on public transport stops around the Helsinki area. It uses PostgreSQL as the database where the poster data and generation status is stored, React for rendering the posters, Puppeteer for generating PDF's of the poster app and Koa as the server to tie everything together. @@ -38,11 +38,11 @@ It will make two layout passes to check if the map can be rendered. The ads (gra Each component will add itself to the "render queue" when mounted, an operation of which there are multiple examples in the code. Once the component has finished its own data fetching and layout procedures it removes itself from the render queue. Once the render queue is empty, the poster is deemed finished and the server will instruct Puppeteer to create a PDF of the page. The component can also pass an error when removing itself which triggers the whole poster to fail. -### Running the apps +### Running the app Server and REST API for printing components to PDF files and managing their metadata in a Postgres database. -Start Postgres: +#### 1. Start Postgres ``` docker run -p 0.0.0.0:5432:5432 --env POSTGRES_PASSWORD=postgres --name publisher-postgres postgres @@ -56,24 +56,41 @@ PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres Again, adjust the port if you are running your Publisher Postgres instance on an other port. -In development, start the Publisher server like this, prepending the Postgres connection string: +#### 2. Redis +Start Redis +``` +docker run --name redis --rm -p 6379:6379 -d redis +``` + +For default configuration, place the following to `.env`: +``` +REDIS_CONNECTION_STRING=redis://localhost:6379 +``` + +#### 3. Backend, worker and poster UI + +In development, start the Publisher backend server like this, prepending the Postgres connection string: +(or place the connection string to `.env`) ```bash -PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres npm run server:hot +PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn run server:hot ``` That command will run a Forever instance that watches for changes and restarts the server when they happen. Alternatively, to run the server with plain Node, leave off `hot`: - ```bash -PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres npm run server +PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn run server ``` -The React app needs to be started separately: +Then, start generator worker. (You can start multiple workers.) +``` +PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn worker +``` +Finally, start the React app ```bash -npm start +yarn start ``` Now you can use the UI with the server, or open a poster separately in your browser. The poster app needs `component` and `props` query parameters, and the server will echo the currently rendering URL in its console. But if you just need to open the poster app, you can use this link that will show H0454, Snellmaninkatu: @@ -84,6 +101,10 @@ You will have to create a template using the Publisher UI. The poster app will d If Azure credentials are not set in the .env file the posters will be stored locally. +#### 4. Start frontend + +See [hsl-map-publisher-ui](https://github.com/HSLdevcom/hsl-map-publisher-ui) for UI. + ### Running in Docker As before, make sure you are running a database for the publisher: diff --git a/constants.js b/constants.js index d018e4e6..b9bfe452 100644 --- a/constants.js +++ b/constants.js @@ -32,6 +32,7 @@ const secretsEnv = mapValues(process.env, (value, key) => { module.exports = { PG_CONNECTION_STRING: secretsEnv.PG_CONNECTION_STRING || '', + REDIS_CONNECTION_STRING: secretsEnv.REDIS_CONNECTION_STRING || '', JORE_GRAPHQL_URL: secretsEnv.JORE_GRAPHQL_URL || '', GENERATE_API_URL: secretsEnv.GENERATE_API_URL || '', AZURE_UPLOAD_CONTAINER: secretsEnv.AZURE_UPLOAD_CONTAINER || 'publisher-prod', diff --git a/package.json b/package.json index 99b287e0..8f62bd7b 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "server": "node -r dotenv/config scripts/server", "server:production": "forever start -c \"node --max_old_space_size=8192 -r dotenv/config\" scripts/server.js", "server:hot": "forever -w -t --killSignal=SIGTERM --watchDirectory scripts -c \"node --max_old_space_size=8192 -r dotenv/config\" scripts/server.js", + "worker": "node -r dotenv/config scripts/worker", + "worker:production": "forever start -c \"node -r dotenv/config\" scripts/worker.js", "knex": "PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres knex", "docker:build": "docker build -t hsl-map-publisher .", "docker:run": "docker run -d -p 4000:4000 --name publisher -v $(pwd)/output:/output -v $(pwd)/fonts:/fonts --link publisher-postgres -e \"PG_CONNECTION_STRING=postgres://postgres:postgres@publisher-postgres:5432/postgres\" --shm-size=1G hsl-map-publisher", @@ -89,6 +91,7 @@ "babel-plugin-transform-runtime": "^6.23.0", "babel-polyfill": "^6.26.0", "babel-preset-stage-0": "^6.24.1", + "bullmq": "^1.57.0", "cheerio": "^1.0.0-rc.2", "classnames": "^2.2.5", "clean-webpack-plugin": "^0.1.19", @@ -101,6 +104,7 @@ "hsl-map-style": "HSLdevcom/hsl-map-style#master", "html-webpack-plugin": "^4.0.0-alpha", "iconv-lite": "^0.4.19", + "ioredis": "^4.28.2", "knex": "^0.14.6", "koa": "^2.5.3", "koa-json-body": "^5.3.0", diff --git a/scripts/fileHandler.js b/scripts/fileHandler.js new file mode 100644 index 00000000..db443642 --- /dev/null +++ b/scripts/fileHandler.js @@ -0,0 +1,82 @@ +const fs = require('fs-extra'); +const path = require('path'); +const { spawn } = require('child_process'); + +const { AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY } = require('../constants'); + +const cwd = process.cwd(); + +const pdfOutputDir = path.join(cwd, 'output'); +const concatOutputDir = path.join(pdfOutputDir, 'concatenated'); + +fs.ensureDirSync(concatOutputDir); + +const pdfPath = id => path.join(pdfOutputDir, `${id}.pdf`); + +/** + * Concatenates posters to a multi-page PDF + * @param {string[]} ids - Ids to concatate + * @returns {Readable} - PDF stream + * @param ids + * @param title + */ +async function concatenate(ids, title) { + const concatFolderExists = await fs.pathExists(concatOutputDir); + if (!concatFolderExists) { + fs.ensureDirSync(concatOutputDir); + } + + const filenames = ids.map(id => pdfPath(id)); + const parsedTitle = title.replace('/', ''); + const filepath = path.join(concatOutputDir, `${parsedTitle}.pdf`); + const fileExists = await fs.pathExists(filepath); + + if (!fileExists) { + return new Promise((resolve, reject) => { + const pdftk = spawn('pdftk', [...filenames, 'cat', 'output', filepath]); + + pdftk.on('error', err => { + reject(err); + }); + + pdftk.on('close', code => { + if (code === 0) { + resolve(filepath); + } else { + reject(new Error(`PDFTK closed with code ${code}`)); + } + }); + }); + } + + return filepath; +} + +async function removeFiles(ids) { + if (!AZURE_STORAGE_ACCOUNT || !AZURE_STORAGE_KEY) { + console.log('Azure credentials not set. Not removing files.'); + return; + } + const filenames = ids.map(id => pdfPath(id)); + const removePromises = []; + + filenames.forEach(filename => { + const createPromise = async () => { + try { + await fs.remove(filename); + } catch (err) { + console.log(`Pdf ${filename} removal unsuccessful.`); + console.error(err); + } + }; + + removePromises.push(createPromise()); + }); + + await Promise.all(removePromises); +} + +module.exports = { + concatenate, + removeFiles, +}; diff --git a/scripts/server.js b/scripts/server.js index e1ba8907..9be9cf64 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -6,16 +6,21 @@ const Router = require('koa-router'); const cors = require('@koa/cors'); const jsonBody = require('koa-json-body'); const fs = require('fs-extra'); +const { Queue } = require('bullmq'); +const Redis = require('ioredis'); -const generator = require('./generator'); +const fileHandler = require('./fileHandler'); const authEndpoints = require('./auth/authEndpoints'); const { matchStopDataToRules } = require('./util/rules'); -const { DOMAINS_ALLOWED_TO_GENERATE, PUBLISHER_TEST_GROUP } = require('../constants'); +const { + DOMAINS_ALLOWED_TO_GENERATE, + PUBLISHER_TEST_GROUP, + REDIS_CONNECTION_STRING, +} = require('../constants'); const { migrate, - addEvent, getBuilds, getBuild, addBuild, @@ -23,7 +28,6 @@ const { removeBuild, getPoster, addPoster, - updatePoster, removePoster, getTemplates, addTemplate, @@ -39,6 +43,12 @@ const { downloadPostersFromCloud } = require('./cloudService'); const PORT = 4000; +const bullRedisConnection = new Redis(REDIS_CONNECTION_STRING, { + maxRetriesPerRequest: null, + enableReadyCheck: false, +}); +const queue = new Queue('publisher', { connection: bullRedisConnection }); + async function generatePoster(buildId, component, props, index) { const { stopId, date, template, selectedRuleTemplates } = props; const data = await getStopInfo({ stopId, date }); @@ -68,40 +78,14 @@ async function generatePoster(buildId, component, props, index) { order: index, }); - const onInfo = (message = 'No message.') => { - console.log(`${id}: ${message}`); // eslint-disable-line no-console - addEvent({ - posterId: id, - type: 'INFO', - message, - }); - }; - const onError = error => { - console.error(`${id}: ${error.message} ${error.stack}`); // eslint-disable-line no-console - addEvent({ - posterId: id, - type: 'ERROR', - message: error.message, - }); - }; - const options = { id, component, props: renderProps, template: chosenTemplate, - onInfo, - onError, }; - generator - .generate(options) - .then(({ success, uploaded }) => { - updatePoster({ - id, - status: success && uploaded ? 'READY' : 'FAILED', - }); - }) - .catch(error => console.error(error)); // eslint-disable-line no-console + + queue.add('generate', { options }, { jobId: id }); return { id }; } @@ -261,8 +245,8 @@ async function main() { ctx.throw(404, 'Poster ids not found.'); } try { - filename = await generator.concatenate(downloadedPosterIds, `${component}-${id}`); - await generator.removeFiles(downloadedPosterIds); + filename = await fileHandler.concatenate(downloadedPosterIds, `${component}-${id}`); + await fileHandler.removeFiles(downloadedPosterIds); } catch (err) { ctx.throw(500, err.message || 'PDF concatenation failed.'); } @@ -308,11 +292,11 @@ async function main() { 'asc', ); - filename = await generator.concatenate( + filename = await fileHandler.concatenate( orderedPosters.map(poster => poster.id), parsedTitle, ); - await generator.removeFiles(downloadedPosterIds); + await fileHandler.removeFiles(downloadedPosterIds); } catch (err) { ctx.throw(500, err.message || 'PDF concatenation failed.'); } diff --git a/scripts/generator.js b/scripts/worker.js similarity index 58% rename from scripts/generator.js rename to scripts/worker.js index 84d3cab1..38174de8 100644 --- a/scripts/generator.js +++ b/scripts/worker.js @@ -1,14 +1,19 @@ +const { Worker, QueueScheduler } = require('bullmq'); +const Redis = require('ioredis'); const fs = require('fs-extra'); const path = require('path'); const puppeteer = require('puppeteer'); const qs = require('qs'); -const { promisify } = require('util'); -const { spawn } = require('child_process'); const log = require('./util/log'); -const get = require('lodash/get'); const { uploadPosterToCloud } = require('./cloudService'); -const { AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY } = require('../constants'); +const { addEvent, updatePoster } = require('./store'); + +const { + AZURE_STORAGE_ACCOUNT, + AZURE_STORAGE_KEY, + REDIS_CONNECTION_STRING, +} = require('../constants'); const CLIENT_URL = 'http://localhost:5000'; const RENDER_TIMEOUT = 10 * 60 * 1000; @@ -16,13 +21,9 @@ const MAX_RENDER_ATTEMPTS = 3; const SCALE = 96 / 72; let browser = null; -let previous = Promise.resolve(); const cwd = process.cwd(); const pdfOutputDir = path.join(cwd, 'output'); -const concatOutputDir = path.join(pdfOutputDir, 'concatenated'); - -fs.ensureDirSync(concatOutputDir); const pdfPath = id => path.join(pdfOutputDir, `${id}.pdf`); @@ -142,86 +143,79 @@ async function renderComponentRetry(options) { return { success: false }; } -/** - * Adds component to render queue - * @param {Object} options - * @param {string} options.id - Unique id - * @param {string} options.component - React component to render - * @param {Object} options.props - Props to pass to component - * @param {function} options.onInfo - Callback (string) - * @param {function} options.onError - Callback (Error) - * @returns {Promise} - Always resolves with { success } - */ -function generate(options) { - previous = previous.then(() => renderComponentRetry(options)); - return previous; -} - -/** - * Concatenates posters to a multi-page PDF - * @param {string[]} ids - Ids to concatate - * @returns {Readable} - PDF stream - * @param ids - * @param title - */ -async function concatenate(ids, title) { - const concatFolderExists = await fs.pathExists(concatOutputDir); - if (!concatFolderExists) { - fs.ensureDirSync(concatOutputDir); - } +async function generate(options) { + const { id } = options; - const filenames = ids.map(id => pdfPath(id)); - const parsedTitle = title.replace('/', ''); - const filepath = path.join(concatOutputDir, `${parsedTitle}.pdf`); - const fileExists = await fs.pathExists(filepath); - - if (!fileExists) { - return new Promise((resolve, reject) => { - const pdftk = spawn('pdftk', [...filenames, 'cat', 'output', filepath]); - - pdftk.on('error', err => { - reject(err); - }); - - pdftk.on('close', code => { - if (code === 0) { - resolve(filepath); - } else { - reject(new Error(`PDFTK closed with code ${code}`)); - } - }); + const onInfo = (message = 'No message.') => { + console.log(`${id}: ${message}`); // eslint-disable-line no-console + addEvent({ + posterId: id, + type: 'INFO', + message, }); - } - - return filepath; -} - -async function removeFiles(ids) { - if (!AZURE_STORAGE_ACCOUNT || !AZURE_STORAGE_KEY) { - console.log('Azure credentials not set. Not removing files.'); - return; - } - const filenames = ids.map(id => pdfPath(id)); - const removePromises = []; - - filenames.forEach(filename => { - const createPromise = async () => { - try { - await fs.remove(filename); - } catch (err) { - console.log(`Pdf ${filename} removal unsuccessful.`); - console.error(err); - } - }; + }; + const onError = error => { + console.error(`${id}: ${error.message} ${error.stack}`); // eslint-disable-line no-console + addEvent({ + posterId: id, + type: 'ERROR', + message: error.message, + }); + }; - removePromises.push(createPromise()); + const { success, uploaded } = await renderComponentRetry({ + ...options, + onInfo, + onError, }); - await Promise.all(removePromises); + updatePoster({ + id, + status: success && uploaded ? 'READY' : 'FAILED', + }); } -module.exports = { - generate, - concatenate, - removeFiles, -}; +const bullRedisConnection = new Redis(REDIS_CONNECTION_STRING, { + maxRetriesPerRequest: null, + enableReadyCheck: false, +}); + +// Queue scheduler to restart stopped jobs. +const queueScheduler = new QueueScheduler('publisher', { + connection: bullRedisConnection, +}); + +// Worker implementation +const worker = new Worker( + 'publisher', + async job => { + const { options } = job.data; + await generate(options); + }, + { + connection: bullRedisConnection, + }, +); + +console.log('Worker ready for jobs!'); + +worker.on('active', job => { + console.log(`Started to process ${job.id}`); +}); + +worker.on('completed', job => { + console.log(`${job.id} has completed!`); +}); + +worker.on('failed', (job, err) => { + console.log(`${job.id} has failed with ${err.message}`); +}); + +worker.on('drained', () => console.log('Job queue empty! Waiting for new jobs...')); + +process.on('SIGINT', () => { + console.log('Shutting down worker...'); + worker.close(true); + queueScheduler.close(); + process.exit(0); +}); diff --git a/yarn.lock b/yarn.lock index 143352de..4ce667b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,6 +2015,21 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +bullmq@^1.57.0: + version "1.57.0" + resolved "https://registry.yarnpkg.com/bullmq/-/bullmq-1.57.0.tgz#7e9d0e2c63aff082597d3ca349a52e33b4357ff4" + integrity sha512-W5pjoOyjGh1C3LqSWbNmzH/LETV2mmZt1JDDVF0dw1U61BbyWz01TX1sNb+sPt58UoaZKTwhYuT5CaaNkTHrYQ== + dependencies: + cron-parser "^2.18.0" + get-port "^5.1.1" + glob "^7.2.0" + ioredis "^4.27.9" + lodash "^4.17.21" + msgpackr "^1.4.6" + semver "^6.3.0" + tslib "^1.14.1" + uuid "^8.3.2" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -2069,6 +2084,14 @@ cache-content-type@^1.0.0: mime-types "^2.1.18" ylru "^1.2.0" +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -2429,6 +2452,11 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +cluster-key-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" + integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== + co-body@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124" @@ -2739,6 +2767,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +cron-parser@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.18.0.tgz#de1bb0ad528c815548371993f81a54e5a089edcf" + integrity sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg== + dependencies: + is-nan "^1.3.0" + moment-timezone "^0.5.31" + cross-env@^5.1.1: version "5.2.1" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d" @@ -2983,6 +3019,13 @@ debug@^4.0.1, debug@^4.1.0: dependencies: ms "^2.1.1" +debug@^4.3.1: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -3112,6 +3155,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +denque@^1.1.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" + integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== + depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" @@ -4354,6 +4402,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-node-dimensions@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz#fb7b4bb57060fb4247dd51c9d690dfbec56b0823" @@ -4369,6 +4426,11 @@ get-port@^3.2.0: resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= +get-port@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -4453,6 +4515,18 @@ glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -4997,6 +5071,23 @@ invariant@^2.2.2: dependencies: loose-envify "^1.0.0" +ioredis@^4.27.9, ioredis@^4.28.2: + version "4.28.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.2.tgz#493ccd5d869fd0ec86c96498192718171f6c9203" + integrity sha512-kQ+Iv7+c6HsDdPP2XUHaMv8DhnSeAeKEwMbaoqsXYbO+03dItXt7+5jGQDRyjdRUV2rFJbzg7P4Qt1iX2tqkOg== + dependencies: + cluster-key-slot "^1.1.0" + debug "^4.3.1" + denque "^1.1.0" + lodash.defaults "^4.2.0" + lodash.flatten "^4.4.0" + lodash.isarguments "^3.1.0" + p-map "^2.1.0" + redis-commands "1.7.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -5229,6 +5320,14 @@ is-map@^2.0.1: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== +is-nan@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -5920,11 +6019,26 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + lodash.get@~4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5945,7 +6059,7 @@ lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== -lodash@^4.17.4: +lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6332,6 +6446,18 @@ mkdirp@0.x.x, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: dependencies: minimist "^1.2.5" +moment-timezone@^0.5.31: + version "0.5.34" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" + integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== + dependencies: + moment ">= 2.9.0" + +"moment@>= 2.9.0": + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + moment@^2.19.2: version "2.27.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" @@ -6359,11 +6485,26 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +msgpackr-extract@^1.0.14: + version "1.0.16" + resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-1.0.16.tgz#701c4f6e6f25c100ae84557092274e8fffeefe45" + integrity sha512-fxdRfQUxPrL/TizyfYfMn09dK58e+d65bRD/fcaVH4052vj30QOzzqxcQIS7B0NsqlypEQ/6Du3QmP2DhWFfCA== + dependencies: + nan "^2.14.2" + node-gyp-build "^4.2.3" + +msgpackr@^1.4.6: + version "1.5.1" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.5.1.tgz#2a8e39d25458406034b8cb50dc7d6a7abd3dfff2" + integrity sha512-I1CXFG8BYYSeIhtDlHpUVMsdDiyvP9JAh1d9QoBnkPx3ETPeH/1lR14hweM9GETs09wCWlaOyhtXxIc9boxAAA== + optionalDependencies: + msgpackr-extract "^1.0.14" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6388,6 +6529,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nan@^2.14.2: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + nanoassert@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d" @@ -6499,6 +6645,11 @@ node-fetch@^2.6.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-gyp-build@^4.2.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" + integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + "node-libs-browser@^1.0.0 || ^2.0.0", node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -6892,7 +7043,7 @@ p-map@^1.1.1, p-map@^1.2.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== -p-map@^2.0.0: +p-map@^2.0.0, p-map@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== @@ -8056,6 +8207,23 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" +redis-commands@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" + integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== + +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha1-62LSrbFeTq9GEMBK/hUpOEJQq60= + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ= + dependencies: + redis-errors "^1.0.0" + reduce-css-calc@^1.2.6: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" @@ -8476,6 +8644,11 @@ semver@4.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -8804,6 +8977,11 @@ staged-git-files@1.1.2: resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b" integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA== +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -9283,6 +9461,11 @@ tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tsscmp@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" @@ -9572,6 +9755,11 @@ uuid@^3.1.0, uuid@^3.2.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: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.0, v8-compile-cache@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" From 25ef4a9a90504d476e8626042a322cc4b7dac828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20H=C3=A4nninen?= Date: Thu, 5 May 2022 12:49:07 +0300 Subject: [PATCH 2/7] Merge some fixes from development --- .env.production => .env.prod | 0 Dockerfile | 21 +- README.md | 35 ++- fonts.sh | 49 ++-- package.json | 2 +- scripts/store.js | 2 - scripts/worker.js | 2 +- .../labelPlacement/itemContainer.js | 1 + src/components/map/customMap.js | 36 ++- src/components/map/stopMapContainer.js | 66 +++-- src/components/stopPoster/stopPoster.js | 2 +- src/util/promiseWrapper.js | 8 +- yarn.lock | 274 ++++++++++++++---- 13 files changed, 332 insertions(+), 166 deletions(-) rename .env.production => .env.prod (100%) diff --git a/.env.production b/.env.prod similarity index 100% rename from .env.production rename to .env.prod diff --git a/Dockerfile b/Dockerfile index 12bf4816..9a1645a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,13 @@ -FROM node:12 +FROM node:12-buster-slim -# This installs the necessary libs to make the bundled version of Chromium that Pupppeteer installs work RUN apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -yq \ - wget curl pdftk libgconf-2-4 gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 \ - libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ - libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 \ - libnss3 lsb-release xdg-utils --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -yq wget curl gnupg pdftk fontconfig fonts-liberation --no-install-recommends \ + # This installs the necessary libs to make the bundled version of Chromium that Puppeteer installs work && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -yq $(apt-cache depends google-chrome-unstable | awk '/depends:/{print$2}') --no-install-recommends \ - && rm -rf /var/lib/apt/lists/* \ - && rm -rf /src/*.deb - -RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \ - && mkdir -p /home/pptruser/Downloads \ - && chown -R pptruser:pptruser /home/pptruser + && DEBIAN_FRONTEND=noninteractive apt-get install -yq google-chrome-stable libxss1 --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* # Install Azure CLI to download the fonts # TODO: This takes almost 1G size in the docker image. Change Azure CLI to azcopy. See MM-262 @@ -33,7 +24,7 @@ RUN yarn && yarn cache clean COPY . ${WORK} -ARG BUILD_ENV=production +ARG BUILD_ENV=prod COPY .env.${BUILD_ENV} ${WORK}/.env RUN yarn run build diff --git a/README.md b/README.md index 0faffea2..087a3aaa 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ Server and REST API for printing components to PDF files and managing their meta docker run -p 0.0.0.0:5432:5432 --env POSTGRES_PASSWORD=postgres --name publisher-postgres postgres ``` -Adjust the port if you have many Postgres instances running on your machine. The server needs the `PG_CONNECTION_STRING` environment variable set, which it uses to connect to your Postgres instance. If you use the default Postgres port, it looks like this: +Adjust the port if you have many Postgres instances running on your machine. The server needs the `PG_CONNECTION_STRING` environment variable set, which it uses to connect to your Postgres instance. If you use the default Postgres port, place this to `.env`: -```bash +``` PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres ``` @@ -70,22 +70,21 @@ REDIS_CONNECTION_STRING=redis://localhost:6379 #### 3. Backend, worker and poster UI -In development, start the Publisher backend server like this, prepending the Postgres connection string: -(or place the connection string to `.env`) +In development, start the Publisher backend server like this, (make sure you have connection strings in `.env`) ```bash -PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn run server:hot +yarn run server:hot ``` That command will run a Forever instance that watches for changes and restarts the server when they happen. Alternatively, to run the server with plain Node, leave off `hot`: ```bash -PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn run server +yarn run server ``` Then, start generator worker. (You can start multiple workers.) ``` -PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/postgres yarn worker +yarn worker ``` Finally, start the React app @@ -105,24 +104,32 @@ If Azure credentials are not set in the .env file the posters will be stored loc See [hsl-map-publisher-ui](https://github.com/HSLdevcom/hsl-map-publisher-ui) for UI. -### Running in Docker +### Running in local Docker -As before, make sure you are running a database for the publisher: +As before, make sure you are running a database and broker for the publisher: ```bash docker run -p 0.0.0.0:5432:5432 --env POSTGRES_PASSWORD=postgres --name publisher-postgres postgres +docker run --name redis --rm -p 6379:6379 -d redis ``` +Remember to check the naming of the containers! If they are different, use your naming in `.env.local` and in next commands. Add also possible credentials to connection strings, if you have set up them, add fill up the variables left empty (`CLIENT_SECRET`, `API_CLIENT_SECRET` and domain restrictions). + +For fonts you have three options: +- Create `fonts/` -directory inside project folder. Place `Gotham Rounded` and `Gotham XNarrow` OpenType fonts there from Azure. +- Place `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_KEY` either via `.env.local` or Docker secrets. Fonts will be downloaded from Azure on startup. +- If no fonts or credentials are provided, the app use just the default fonts found inside Debian image. + +Due to licensing, we cannot include the fonts in the public repository. + Build the Docker image with the following command: ```bash -docker build -t hsldevcom/hsl-map-publisher . +docker build --build-arg BUILD_ENV=local -t hsl-map-publisher . ``` -And run the Docker container with this command: +And run the Docker container with this command (you can leave font-directory mounting away if you don't have them locally): ```bash -docker run -d -p 4000:4000 --name publisher -v $(pwd)/output:/output -v $(pwd)/fonts:/fonts --link publisher-postgres -e "PG_CONNECTION_STRING=postgres://postgres:postgres@publisher-postgres:5432/postgres" --shm-size=1G hsl-map-publisher +docker run -d -p 4000:4000 --name publisher -v $(pwd)/output:/output -v $(pwd)/fonts:/fonts --link publisher-postgres --link redis hsl-map-publisher ``` - -`fonts` is a directory containing `Gotham Rounded` and `Gotham XNarrow` OpenType fonts. Due to licensing, we cannot include the fonts in the repository. diff --git a/fonts.sh b/fonts.sh index f88e6868..59c06d47 100755 --- a/fonts.sh +++ b/fonts.sh @@ -1,39 +1,44 @@ #!/bin/bash set -e +font_dir=~/.local/share/fonts/opentype +mkdir -p $font_dir + # Check if the fonts already exist. Hey, we might be lucky! if [ -n "$(ls -A /fonts 2>/dev/null)" ]; then echo "Fonts seem to exist. If they do not, ensure /fonts dir is empty and try again." + cp -R /fonts $font_dir exit 0 fi -# Path to the Azure credentials supplied by Docker secrets -key_secret=/run/secrets/AZURE_STORAGE_KEY -account_secret=/run/secrets/AZURE_STORAGE_ACCOUNT - -# Check if the credentials exist. - -cat ${key_secret} - -if [ ! -f "$key_secret" ]; then - echo "Azure key not set. Fonts not downloaded." - exit 0 +# Read env for the script +if [ -f .env ]; then + source .env fi -if [ ! -f "$account_secret" ]; then - echo "Azure account not set. Fonts not downloaded." - exit 0 +# Find Azure credentials from secrets if not found from env +if [ -z "$AZURE_STORAGE_KEY" ] || [ -z "$AZURE_STORAGE_ACCOUNT" ]; then + # Path to the Azure credentials supplied by Docker secrets + key_secret=/run/secrets/AZURE_STORAGE_KEY + account_secret=/run/secrets/AZURE_STORAGE_ACCOUNT + + # Check if the secrets exits, otherwise use just default fonts + if [ ! -f "$key_secret" ]; then + echo "Azure key not set. Fonts not downloaded." + exit 0 + fi + if [ ! -f "$account_secret" ]; then + echo "Azure account not set. Fonts not downloaded." + exit 0 + fi + + # Read the credentials to envs + AZURE_STORAGE_KEY=$(<$key_secret) + AZURE_STORAGE_ACCOUNT=$(<$account_secret) fi -# Read the credentials so AZ CLI may use them. -AZURE_STORAGE_KEY=$(<$key_secret) -AZURE_STORAGE_ACCOUNT=$(<$account_secret) - container_name=${AZURE_STORAGE_CONTAINER:=fonts} -destination=~/.local/share/fonts/opentype - -mkdir -p ${destination} -az storage blob download-batch --destination $destination --source $container_name --pattern *.otf --no-progress --account-name $AZURE_STORAGE_ACCOUNT --account-key $AZURE_STORAGE_KEY +az storage blob download-batch --destination $font_dir --source $container_name --pattern *.otf --no-progress --account-name $AZURE_STORAGE_ACCOUNT --account-key $AZURE_STORAGE_KEY echo "Fonts downloaded." diff --git a/package.json b/package.json index d35a1c13..42468245 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "p-reduce": "^1.0.0", "pg": "^7.4.0", "prop-types": "^15.6.0", - "puppeteer": "^1.11.0", + "puppeteer": "^13.7.0", "qrcode": "^1.0.0", "qs": "^6.5.2", "raw-loader": "^0.5.1", diff --git a/scripts/store.js b/scripts/store.js index 79baa2d3..01f5c226 100644 --- a/scripts/store.js +++ b/scripts/store.js @@ -2,10 +2,8 @@ const uuidv1 = require('uuid/v1'); const camelCase = require('lodash/camelCase'); const snakeCase = require('lodash/snakeCase'); const pMap = require('p-map'); -const pReduce = require('p-reduce'); const merge = require('lodash/merge'); const get = require('lodash/get'); -const pick = require('lodash/pick'); const flatMap = require('lodash/flatMap'); const config = require('../knexfile'); diff --git a/scripts/worker.js b/scripts/worker.js index 38174de8..e53be5a5 100644 --- a/scripts/worker.js +++ b/scripts/worker.js @@ -79,7 +79,7 @@ async function renderComponent(options) { throw new Error(error); } - await page.emulateMedia('screen'); + await page.emulateMediaType('screen'); let printOptions = {}; if (props.printTimetablesAsA4) { diff --git a/src/components/labelPlacement/itemContainer.js b/src/components/labelPlacement/itemContainer.js index 31fa6aed..49ca907a 100644 --- a/src/components/labelPlacement/itemContainer.js +++ b/src/components/labelPlacement/itemContainer.js @@ -29,6 +29,7 @@ class ItemContainer extends Component { componentWillUnmount() { this.worker.terminate(); + renderQueue.remove(this); } updateChildren() { diff --git a/src/components/map/customMap.js b/src/components/map/customMap.js index 595faaf4..9ddd8470 100644 --- a/src/components/map/customMap.js +++ b/src/components/map/customMap.js @@ -20,7 +20,7 @@ class CustomMap extends Component { setMapHeight: PropTypes.func.isRequired, mapZoneSymbols: PropTypes.bool, mapZones: PropTypes.bool, - salesPoint: PropTypes.bool, + showSalesPoint: PropTypes.bool, minimapZoneSymbols: PropTypes.bool, minimapZones: PropTypes.bool, }; @@ -28,7 +28,7 @@ class CustomMap extends Component { static defaultProps = { mapZoneSymbols: false, mapZones: false, - salesPoint: false, + showSalesPoint: false, minimapZoneSymbols: false, minimapZones: false, }; @@ -42,6 +42,14 @@ class CustomMap extends Component { renderQueue.add(this); } + componentDidUpdate() { + renderQueue.remove(this); + } + + componentWillUnmount() { + renderQueue.remove(this); + } + onResize = ({ client: { width, height } }) => { const { mapWidth, mapHeight } = this.state; const { setMapHeight, template } = this.props; @@ -53,15 +61,19 @@ class CustomMap extends Component { return; } - setMapHeight(height); + if (height !== mapHeight) { + setMapHeight(height); + } - this.setState( - { - mapWidth: width, - mapHeight: height, - }, - () => renderQueue.remove(this), - ); + if (height !== mapHeight || width !== mapWidth) { + this.setState( + { + mapWidth: width, + mapHeight: height, + }, + () => renderQueue.remove(this), + ); + } }; render() { @@ -72,7 +84,7 @@ class CustomMap extends Component { isSummerTimetable, mapZoneSymbols, mapZones, - salesPoint, + showSalesPoint, minimapZoneSymbols, minimapZones, } = this.props; @@ -138,7 +150,7 @@ class CustomMap extends Component { showCitybikes={isSummerTimetable} mapZoneSymbols={mapZoneSymbols} mapZones={mapZones} - salesPoint={salesPoint} + showSalesPoint={showSalesPoint} minimapZoneSymbols={minimapZoneSymbols} minimapZones={minimapZones} /> diff --git a/src/components/map/stopMapContainer.js b/src/components/map/stopMapContainer.js index c37d2ee3..4efd6f69 100644 --- a/src/components/map/stopMapContainer.js +++ b/src/components/map/stopMapContainer.js @@ -165,17 +165,19 @@ const nearbyItemsMapper = mapProps(props => { const nearbyStops = projectedStops.filter(({ stopIds }) => !stopIds.includes(props.stopId)); // Calculate distances to sale points and get the nearest one - const nearestSalePoint = projectedSalePoints - .map(sp => { - // Euclidean distance - const distance = haversine( - { latitude: sp.lat, longitude: sp.lon }, - { latitude: projectedCurrentLocation.lat, longitude: projectedCurrentLocation.lon }, - { unit: 'meter' }, - ); - return { ...sp, distance }; - }) - .reduce((prev, curr) => (prev && curr.distance > prev.distance ? prev : curr), null); + const nearestSalePoint = props.showSalesPoint + ? projectedSalePoints + .map(sp => { + // Euclidean distance + const distance = haversine( + { latitude: sp.lat, longitude: sp.lon }, + { latitude: projectedCurrentLocation.lat, longitude: projectedCurrentLocation.lon }, + { unit: 'meter' }, + ); + return { ...sp, distance }; + }) + .reduce((prev, curr) => (prev && curr.distance > prev.distance ? prev : curr), null) + : null; const mapOptions = { center: [viewport.longitude, viewport.latitude], @@ -262,30 +264,30 @@ const mapInterestsMapper = mapProps(props => { }; }); -const getSalePoints = async () => { - const response = await fetch(process.env.SALES_POINT_DATA_URL, { method: 'GET' }); - const data = await response.json(); - const result = data.features - .filter(sp => SALE_POINT_TYPES.includes(sp.properties.Tyyppi)) - .map(sp => { - const { properties } = sp; - const { coordinates } = sp.geometry; - const [lon, lat] = coordinates; - return { - id: properties.ID, - type: properties.Tyyppi, - title: properties.Nimi, - address: properties.Osoite, - lat, - lon, - }; - }); - return result; -}; +const getSalePoints = () => + fetch(process.env.SALES_POINT_DATA_URL, { method: 'GET' }) + .then(response => response.json()) + .then(data => + data.features + .filter(sp => SALE_POINT_TYPES.includes(sp.properties.Tyyppi)) + .map(sp => { + const { properties } = sp; + const { coordinates } = sp.geometry; + const [lon, lat] = coordinates; + return { + id: properties.ID, + type: properties.Tyyppi, + title: properties.Nimi, + address: properties.Osoite, + lat, + lon, + }; + }), + ); const salePointsMapper = mapProps(props => { // If sales points are not configured, do not fetch them but return empty array - const salePoints = props.salesPoint ? getSalePoints() : Promise.resolve([]); + const salePoints = props.showSalesPoint ? getSalePoints() : Promise.resolve([]); return { ...props, salePoints, diff --git a/src/components/stopPoster/stopPoster.js b/src/components/stopPoster/stopPoster.js index dad25385..23f62ca4 100644 --- a/src/components/stopPoster/stopPoster.js +++ b/src/components/stopPoster/stopPoster.js @@ -437,7 +437,7 @@ class StopPoster extends Component { } mapZoneSymbols={mapZoneSymbols} mapZones={mapZones} - salesPoint={salesPoint} + showSalesPoint={salesPoint} minimapZoneSymbols={minimapZoneSymbols} minimapZones={minimapZones} /> diff --git a/src/util/promiseWrapper.js b/src/util/promiseWrapper.js index fea11e77..3740c7cd 100644 --- a/src/util/promiseWrapper.js +++ b/src/util/promiseWrapper.js @@ -14,14 +14,8 @@ const hocFactory = propName => WrappedComponent => } } - componentWillReceiveProps(nextProps) { - if (nextProps[propName] && nextProps[propName] !== this.props[propName]) { - this.setState({ loading: true }); - this.handlePromise(nextProps[propName]); - } - } - componentWillUnmount() { + renderQueue.remove(this.promise); this.promise = null; } diff --git a/yarn.lock b/yarn.lock index 3958a792..953ea2dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -239,6 +239,13 @@ "@types/webpack-sources" "*" source-map "^0.6.0" +"@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" @@ -471,12 +478,12 @@ address@^1.0.1: resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== -agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: - es6-promisify "^5.0.0" + debug "4" ajv-errors@^1.0.0: version "1.0.1" @@ -1742,6 +1749,11 @@ base64-js@^1.0.2: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -1784,6 +1796,15 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -2010,6 +2031,14 @@ buffer@^5.1.0, buffer@^5.4.3: base64-js "^1.0.2" ieee754 "^1.1.4" +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== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -2606,7 +2635,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.2: +concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -2782,6 +2811,13 @@ cross-env@^5.1.1: dependencies: cross-spawn "^6.0.5" +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-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -3005,6 +3041,13 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" +debug@4, debug@4.3.4, debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -3208,6 +3251,11 @@ detect-port@1.2.3: address "^1.0.1" debug "^2.6.0" +devtools-protocol@0.0.981744: + version "0.0.981744" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.981744.tgz#9960da0370284577d46c28979a0b32651022bacf" + integrity sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3424,7 +3472,7 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -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== @@ -3530,18 +3578,6 @@ es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -3971,15 +4007,16 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^1.6.6: - version "1.7.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" - integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== +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: - concat-stream "^1.6.2" - debug "^2.6.9" - mkdirp "^0.5.4" + debug "^4.1.1" + get-stream "^5.1.0" yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" eyes@0.1.x, eyes@~0.1.8: version "0.1.8" @@ -4160,6 +4197,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" @@ -4332,6 +4377,11 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -4448,6 +4498,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -4878,13 +4935,13 @@ 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@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== +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 "^4.3.0" - debug "^3.1.0" + agent-base "6" + debug "4" husky@^1.1.3: version "1.3.1" @@ -4931,6 +4988,11 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -6019,6 +6081,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -6363,7 +6432,7 @@ mime@1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== -mime@^2.0.3, mime@^2.4.4: +mime@^2.4.4: version "2.4.6" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== @@ -6444,7 +6513,12 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.x.x, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: +mkdirp-classic@^0.5.2: + 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.x.x, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -6637,6 +6711,13 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" +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== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^1.0.1, node-fetch@^1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -7022,7 +7103,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -7043,6 +7124,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^1.1.1, p-map@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -7210,6 +7298,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@1.0.1, path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -7368,6 +7461,13 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pkg-dir@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" @@ -7775,7 +7875,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.1: +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== @@ -7817,7 +7917,7 @@ property-expr@^1.5.0: resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== -proxy-from-env@^1.0.0: +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== @@ -7896,19 +7996,23 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer@^1.11.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-1.20.0.tgz#e3d267786f74e1d87cf2d15acc59177f471bbe38" - integrity sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ== - dependencies: - debug "^4.1.0" - extract-zip "^1.6.6" - https-proxy-agent "^2.2.1" - mime "^2.0.3" - progress "^2.0.1" - proxy-from-env "^1.0.0" - rimraf "^2.6.1" - ws "^6.1.0" +puppeteer@^13.7.0: + version "13.7.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-13.7.0.tgz#18e16f83e397cf02f7a0804c67c1603d381cfb0b" + integrity sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA== + dependencies: + cross-fetch "3.1.5" + debug "4.3.4" + devtools-protocol "0.0.981744" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + pkg-dir "4.2.0" + 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.5.0" q@^1.1.2: version "1.5.1" @@ -8162,7 +8266,7 @@ readable-stream@2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1, readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, 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== @@ -8526,6 +8630,13 @@ rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf 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" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -9264,6 +9375,27 @@ tape@~2.3.2: resumer "~0.0.0" through "~2.3.4" +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== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tarn@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.5.tgz#7be88622e951738b9fa3fb77477309242cdddc2d" @@ -9327,7 +9459,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@2, through@^2.3.6, through@~2.3.4: +through@2, through@^2.3.6, through@^2.3.8, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -9434,6 +9566,11 @@ tough-cookie@^3.0.1: psl "^1.1.28" punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + trim-newlines@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" @@ -9536,6 +9673,14 @@ uglify-to-browserify@~1.0.0: resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= +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" + unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -9828,6 +9973,11 @@ watchpack@^1.6.1: chokidar "^3.4.0" watchpack-chokidar2 "^2.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webpack-cli@^3.0.8: version "3.3.12" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" @@ -9965,6 +10115,14 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.1.0.tgz#49d630cdfa308dba7f2819d49d09364f540dbcc6" integrity sha512-pgmbsVWKpH9GxLXZmtdowDIqtb/rvPyjjQv3z9wLcmgWKFHilKnZD3ldgrOlwJoPGOUluQsRPWd52yVkPfmI1A== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" @@ -10120,6 +10278,11 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" @@ -10128,13 +10291,6 @@ ws@^4.0.0: async-limiter "~1.0.0" safe-buffer "~5.1.0" -ws@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" From 062d3e85835345dfdde495d908a75f1801f7c047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20H=C3=A4nninen?= Date: Tue, 10 May 2022 14:59:56 +0300 Subject: [PATCH 3/7] MM-381 Fix infinite render loop with diagram --- src/components/stopPoster/stopPoster.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/stopPoster/stopPoster.js b/src/components/stopPoster/stopPoster.js index 23f62ca4..2344ba4e 100644 --- a/src/components/stopPoster/stopPoster.js +++ b/src/components/stopPoster/stopPoster.js @@ -58,9 +58,6 @@ class StopPoster extends Component { adsPhase: false, diagramOptions: defaultDiagramOptions, }; - } - - componentWillMount() { renderQueue.add(this); } @@ -193,6 +190,11 @@ class StopPoster extends Component { // TODO: This is kind of dirty fix. Binarysearch to get acceptable // height for routetree. const { diagramOptions } = this.state; + + if (diagramOptions.heightValues.length === 0) { + this.setState({ hasDiagram: false }); + return; + } diagramOptions.binarySearching = true; diagramOptions.middleHeightValue = diagramOptions.heightValues[Math.floor(diagramOptions.heightValues.length / 2)]; From e89a5066de2ae524e5a96f85168ac6582541e1f7 Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 1 Jul 2022 14:14:48 +0300 Subject: [PATCH 4/7] trunk routes hotfix --- src/util/domain.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/util/domain.js b/src/util/domain.js index 4c5f6c77..d0efe86f 100644 --- a/src/util/domain.js +++ b/src/util/domain.js @@ -8,7 +8,20 @@ import trunkIcon from 'icons/icon_trunk.svg'; import zoneByShortId from 'data/zoneByShortId'; // TODO: Get routes from api? -const TRUNK_ROUTES = ['20', '30', '40', '200', '500', '510', '550', '560', '570']; +const TRUNK_ROUTES = [ + '20', + '30', + '40', + '200', + '500', + '510', + '550', + '560', + '570', + '300', + '400', + '600', +]; const RAIL_ROUTE_ID_REGEXP = /^300[12]/; const SUBWAY_ROUTE_ID_REGEXP = /^31/; const U_LINE_REGEX = /^7/; From 584177e59e96b269d450b0fbbdd65e7f91f845e2 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 4 Jul 2022 17:18:38 +0300 Subject: [PATCH 5/7] package.json and yarn.lock update --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 42468245..93a78a13 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "graphql": "^0.11.7", "graphql-tag": "^2.5.0", "haversine": "^1.1.1", - "hsl-map-style": "HSLdevcom/hsl-map-style#master", + "hsl-map-style": "hsldevcom/hsl-map-style#master", "html-webpack-plugin": "^4.0.0-alpha", "iconv-lite": "^0.4.19", "ioredis": "^4.28.2", diff --git a/yarn.lock b/yarn.lock index 953ea2dd..a423d16f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4829,9 +4829,9 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hsl-map-style@HSLdevcom/hsl-map-style#master: +hsl-map-style@hsldevcom/hsl-map-style#master: version "1.0.0" - resolved "https://codeload.github.com/HSLdevcom/hsl-map-style/tar.gz/09e8966f4c30b6d08dd64503bfad73fb9685141f" + resolved "https://codeload.github.com/hsldevcom/hsl-map-style/tar.gz/c8edc1963dc1b7f33e644488c292ebb06b68b520" dependencies: lodash "^4.17.4" From e84a0a4c84409940e5712e3a95c160224042e093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20H=C3=A4nninen?= Date: Fri, 12 Aug 2022 15:33:54 +0300 Subject: [PATCH 6/7] Require authentication on API --- scripts/auth/authEndpoints.js | 2 +- scripts/server.js | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/scripts/auth/authEndpoints.js b/scripts/auth/authEndpoints.js index 2d7442d8..ca67362c 100644 --- a/scripts/auth/authEndpoints.js +++ b/scripts/auth/authEndpoints.js @@ -111,7 +111,7 @@ const checkExistingSession = async (req, res, session) => { body: response, }; } - console.log('No existing session'); + // console.log('No existing session'); const response = { isOk: false, }; diff --git a/scripts/server.js b/scripts/server.js index 9be9cf64..aa299de8 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -96,7 +96,30 @@ const errorHandler = async (ctx, next) => { } catch (error) { ctx.status = error.status || 500; ctx.body = { message: error.message }; - console.error(error); // eslint-disable-line no-console + if (ctx.status !== 401) { + console.error(error); // eslint-disable-line no-console + } + } +}; + +const authMiddleware = async (ctx, next) => { + const endpointsNotRequiringAuthentication = ['/login', '/logout', '/session']; + if (endpointsNotRequiringAuthentication.includes(ctx.path)) { + // Do not check the authentication beforehands for session related paths. + await next(); + } else { + const authResponse = await authEndpoints.checkExistingSession( + ctx.request, + ctx.response, + ctx.session, + ); + + if (!authResponse.body.isOk) { + // Not authenticated, throw 401 + ctx.throw(401); + } else { + await next(); + } } }; @@ -347,6 +370,7 @@ async function main() { credentials: true, }), ) + .use(authMiddleware) .use(jsonBody({ fallback: true, limit: '10mb' })) .use(router.routes()) .use(router.allowedMethods()) From 1b0c5858e5a18bf60e79a527980329d8bf5a8e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20H=C3=A4nninen?= Date: Mon, 15 Aug 2022 12:13:02 +0300 Subject: [PATCH 7/7] Fix template query from localhost --- scripts/server.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/scripts/server.js b/scripts/server.js index aa299de8..8fe194b4 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -103,8 +103,24 @@ const errorHandler = async (ctx, next) => { }; const authMiddleware = async (ctx, next) => { - const endpointsNotRequiringAuthentication = ['/login', '/logout', '/session']; - if (endpointsNotRequiringAuthentication.includes(ctx.path)) { + // Helper function to allow specific requests without authentication + const allowAuthException = ctx2 => { + // Allow session related requests + if (['/login', '/logout', '/session'].includes(ctx2.path)) { + return true; + } + // Allow GET localhost:4000/templates/..., so that puppeteer can get the template. + if ( + ctx2.path.startsWith('/templates/') && + ctx.method === 'GET' && + ctx.host === 'localhost:4000' + ) { + return true; + } + return false; + }; + + if (allowAuthException(ctx)) { // Do not check the authentication beforehands for session related paths. await next(); } else {