diff --git a/lib/browser.js b/lib/browser.js index 57ebdf0d..ca6d6f36 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -238,7 +238,7 @@ export async function newPage(poolResource) { */ export async function clearPage(poolResource, hardReset = false) { try { - if (!poolResource.page.isClosed()) { + if (poolResource.page && !poolResource.page.isClosed()) { if (hardReset) { // Navigate to about:blank await poolResource.page.goto('about:blank', { @@ -254,6 +254,7 @@ export async function clearPage(poolResource, hardReset = false) { '
'; }); } + return true; } } catch (error) { logWithStack( @@ -264,6 +265,7 @@ export async function clearPage(poolResource, hardReset = false) { // Set the `workLimit` to exceeded in order to recreate the resource poolResource.workCount = getOptions().pool.workLimit + 1; } + return false; } /** @@ -506,6 +508,12 @@ function _setPageEvents(poolResource) { // Set the pageerror listener poolResource.page.on('pageerror', async (error) => { + // It would seem like this may fire at the same time or shortly before + // a page is closed. + if (page.isClosed()) { + return; + } + await poolResource.page.$eval( '#container', (element, errorMessage) => { diff --git a/lib/export.js b/lib/export.js index f27f08b1..234fb41b 100644 --- a/lib/export.js +++ b/lib/export.js @@ -136,8 +136,12 @@ export async function puppeteerExport(page, chart, options) { }); // Set final height and width for viewport - const viewportHeight = Math.ceil(size.chartHeight || exportOptions.height); - const viewportWidth = Math.ceil(size.chartWidth || exportOptions.width); + const viewportHeight = Math.abs( + Math.ceil(size.chartHeight || exportOptions.height) + ); + const viewportWidth = Math.abs( + Math.ceil(size.chartWidth || exportOptions.width) + ); // Get the clip region for the page const { x, y } = await _getClipRegion(page); @@ -279,20 +283,13 @@ async function _createImage(page, type, encoding, clip, rasterizationTimeout) { */ async function _createPDF(page, height, width, encoding, rasterizationTimeout) { await page.emulateMediaType('screen'); - return Promise.race([ - page.pdf({ - // This will remove an extra empty page in PDF exports - height: height + 1, - width, - encoding - }), - new Promise((_resolve, reject) => - setTimeout( - () => reject(new ExportError('Rasterization timeout', 408)), - rasterizationTimeout || 1500 - ) - ) - ]); + return page.pdf({ + // This will remove an extra empty page in PDF exports + height: height + 1, + width, + encoding, + timeout: rasterizationTimeout || 1500 + }); } /** diff --git a/lib/highcharts.js b/lib/highcharts.js index b6e348e9..9fc36da7 100644 --- a/lib/highcharts.js +++ b/lib/highcharts.js @@ -121,7 +121,10 @@ export async function triggerExport(chartOptions, options, displayErrors) { setOptions(globalOptions); } - Highcharts[options.export.constr || 'chart']( + let constr = options.export.constr || 'chart'; + constr = typeof Highcharts[constr] !== 'undefined' ? constr : 'chart'; + + Highcharts[constr]( 'container', finalOptions, finalCallback diff --git a/lib/pool.js b/lib/pool.js index 044bd708..f63bb856 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -85,15 +85,22 @@ export async function initPool(poolOptions = getOptions().pool, puppeteerArgs) { // Set events pool.on('release', async (resource) => { - log(4, `[pool] Pool resource [${resource.id}] - Releasing a worker.`); + // Clear page + const r = await clearPage(resource, false); + log( + 4, + `[pool] Releasing a worker with ID ${resource.id}. Clear page status: ${r}.` + ); + //// log(4, `[pool] Pool resource [${resource.id}] - Releasing a worker.`); await clearPage(resource, false); }); - pool.on('destroySuccess', (_eventId, resource) => { + pool.on('destroySuccess', (eventId, resource) => { log( 4, `[pool] Pool resource [${resource.id}] - Destroyed a worker successfully.` ); + //// log(4, `[pool] Destroyed a worker with ID ${resource.id}.`); resource.page = null; }); @@ -248,13 +255,23 @@ export async function postWork(chart, options) { if (result.message === 'Rasterization timeout') { // Set the `workLimit` to exceeded in order to recreate the resource workerHandle.workCount = options.pool.workLimit + 1; + workerHandle.page = null; } - throw new ExportError( - (options.payload?.requestId - ? `Request: ${options.payload?.requestId} - ` - : '') + `Error encountered during export: ${exportCounter()}ms.` - ).setError(result); + if ( + result.name === 'TimeoutError' || + result.message === 'Rasterization timeout' + ) { + throw new ExportError( + 'Rasterization timeout: your chart may be too complex or large, and failed to render within the allotted time.' + ).setError(result); + } else { + throw new ExportError( + (options.payload?.requestId + ? `For request with ID ${options.payload?.requestId} - ` + : '') + `Error encountered during export: ${exportCounter()}ms.` + ).setError(result); + } } // Check the Puppeteer export time @@ -449,7 +466,7 @@ function _factory(poolOptions) { } // Check if the `page` is not valid - if (!poolResource.page) { + if (poolResource.page) { // Check if the `page` is closed if (poolResource.page.isClosed()) { log( diff --git a/lib/server/error.js b/lib/server/error.js index d2493e2f..cc89d64e 100644 --- a/lib/server/error.js +++ b/lib/server/error.js @@ -47,7 +47,7 @@ function logErrorMiddleware(error, request, response, next) { function returnErrorMiddleware(error, request, response, next) { // Gather all requied information for the response const { statusCode: stCode, status, message, stack } = error; - const statusCode = stCode || status || 500; + const statusCode = stCode || status || 400; // Set and return response response.status(statusCode).json({ statusCode, message, stack }); diff --git a/lib/server/routes/ui.js b/lib/server/routes/ui.js index 27e232a1..5255a9b9 100644 --- a/lib/server/routes/ui.js +++ b/lib/server/routes/ui.js @@ -22,6 +22,8 @@ import { __dirname } from '../../utils.js'; export default (app) => !app ? false - : app.get('/', (request, response) => { - response.sendFile(join(__dirname, 'public', 'index.html')); + : app.get('/', (_request, response) => { + response.sendFile(join(__dirname, 'public', 'index.html'), { + acceptRanges: false + }); }); diff --git a/lib/server/server.js b/lib/server/server.js index 718abe3f..cd096d66 100644 --- a/lib/server/server.js +++ b/lib/server/server.js @@ -39,14 +39,6 @@ import ExportError from '../errors/ExportError.js'; // Array of an active servers const activeServers = new Map(); -// Enable parsing of form data (files) with Multer package -const upload = multer({ - storage: multer.memoryStorage(), - limits: { - fieldSize: 50 * 1024 * 1024 - } -}); - // Create express app const app = express(); @@ -54,26 +46,33 @@ const app = express(); app.disable('x-powered-by'); // Enable CORS support -app.use( - cors({ - methods: ['POST', 'GET', 'OPTIONS'] - }) -); - -// Enable body parser for JSON data -app.use( - express.json({ - limit: 50 * 1024 * 1024 - }) -); - -// Enable body parser for URL-encoded form data -app.use( - express.urlencoded({ - extended: true, - limit: 50 * 1024 * 1024 - }) -); +app.use(cors()); + +// Getting a lot of RangeNotSatisfiableError exception. +// Even though this is a deprecated options, let's try to set it to false. +app.use((_req, res, next) => { + res.set('Accept-Ranges', 'none'); + next(); +}); + +// TODO: Read from config/env +// NOTE: +// Too big limits lead to timeouts in the export process when the +// rasterization timeout is set too low. +const uploadLimitMiB = 3; +const uploadLimitBytes = uploadLimitMiB * 1024 * 1024; + +// Enable parsing of form data (files) with Multer package +const upload = multer({ + storage: multer.memoryStorage(), + limits: { + fieldSize: uploadLimitBytes + } +}); + +// Enable body parser +app.use(express.json({ limit: uploadLimitBytes })); +app.use(express.urlencoded({ extended: true, limit: uploadLimitBytes })); // Use only non-file multipart form fields app.use(upload.none()); @@ -287,8 +286,13 @@ export function post(path, ...middlewares) { * @param {http.Server} server - The HTTP/HTTPS server instance. */ function _attachServerErrorHandlers(server) { - server.on('clientError', (error) => { - logWithStack(1, error, `[server] Client error: ${error.message}`); + server.on('clientError', (error, socket) => { + logWithStack( + 1, + error, + `[server] Client error: ${error.message}, destroying socket.` + ); + socket.destroy(); }); server.on('error', (error) => { diff --git a/package-lock.json b/package-lock.json index edda362c..2d8b3ca5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,47 +1,44 @@ { "name": "highcharts-export-server", - "version": "4.0.4", + "version": "4.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "highcharts-export-server", - "version": "4.0.4", + "version": "4.0.2", "license": "MIT", "dependencies": { "colors": "1.4.0", "cors": "^2.8.5", - "dompurify": "3.1.6", + "dompurify": "^3.1.6", "dotenv": "^16.4.5", - "express": "^4.21.1", - "express-rate-limit": "^7.4.1", + "express": "^4.19.2", + "express-rate-limit": "^7.3.1", "https-proxy-agent": "^7.0.5", - "jsdom": "^25.0.1", - "jsonwebtoken": "^9.0.2", + "jsdom": "^24.1.0", "multer": "^1.4.5-lts.1", "prompts": "^2.4.2", - "puppeteer": "^23.7.0", + "puppeteer": "^22.12.1", "tarn": "^3.0.2", - "uuid": "^11.0.2", - "ws": "^8.18.0", + "uuid": "^10.0.0", "zod": "^3.23.8" }, "bin": { "highcharts-export-server": "bin/cli.js" }, "devDependencies": { - "@jest/globals": "^29.7.0", "@rollup/plugin-terser": "^0.4.4", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-prettier": "^5.2.1", - "husky": "^9.1.6", + "husky": "^9.1.7", "jest": "^29.7.0", "lint-staged": "^15.2.10", "nodemon": "^3.1.7", - "prettier": "^3.3.3", - "rollup": "^4.24.4" + "prettier": "^3.4.1", + "rollup": "^4.27.4" }, "engines": { "node": ">=18.12.0" @@ -1188,12 +1185,12 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.1.tgz", - "integrity": "sha512-0kdAbmic3J09I6dT8e9vE2JOCSt13wHCW5x/ly8TSt2bDtuIWe2TgLZZDHdcziw9AVCzflMAXCrVyRIhIs44Ng==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz", + "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==", "license": "Apache-2.0", "dependencies": { - "debug": "^4.3.7", + "debug": "^4.3.5", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.4.0", @@ -1633,9 +1630,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", - "integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==", + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "devOptional": true, "license": "MIT", "dependencies": { @@ -2343,12 +2340,6 @@ "node": "*" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2500,9 +2491,9 @@ } }, "node_modules/chromium-bidi": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.8.0.tgz", - "integrity": "sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz", + "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==", "license": "Apache-2.0", "dependencies": { "mitt": "3.0.1", @@ -3081,9 +3072,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1367902", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", - "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", + "version": "0.0.1312386", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", "license": "BSD-3-Clause" }, "node_modules/diff-sequences": { @@ -3127,15 +3118,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3143,9 +3125,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.65", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", - "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", + "version": "1.5.66", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.66.tgz", + "integrity": "sha512-pI2QF6+i+zjPbqRzJwkMvtvkdI7MjVbSh2g8dlMguDJIXEPw+kwasS1Jl+YGPEBfGVxsVgGUratAKymPdPo2vQ==", "dev": true, "license": "ISC" }, @@ -5858,12 +5840,12 @@ "license": "MIT" }, "node_modules/jsdom": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", - "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", + "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", "license": "MIT", "dependencies": { - "cssstyle": "^4.1.0", + "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", @@ -5876,7 +5858,7 @@ "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.0.0", + "tough-cookie": "^4.1.4", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", @@ -5962,61 +5944,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6298,42 +6225,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6341,12 +6232,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -7402,6 +7287,15 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/psl": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.13.0.tgz", + "integrity": "sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + } + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -7429,37 +7323,34 @@ } }, "node_modules/puppeteer": { - "version": "23.9.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.9.0.tgz", - "integrity": "sha512-WfB8jGwFV+qrD9dcJJVvWPFJBU6kxeu2wxJz9WooDGfM3vIiKLgzImEDBxUQnCBK/2cXB3d4dV6gs/LLpgfLDg==", + "version": "22.15.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz", + "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.4.1", - "chromium-bidi": "0.8.0", + "@puppeteer/browsers": "2.3.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1367902", - "puppeteer-core": "23.9.0", - "typed-query-selector": "^2.12.0" + "devtools-protocol": "0.0.1312386", + "puppeteer-core": "22.15.0" }, "bin": { - "puppeteer": "lib/cjs/puppeteer/node/cli.js" + "puppeteer": "lib/esm/puppeteer/node/cli.js" }, "engines": { "node": ">=18" } }, "node_modules/puppeteer-core": { - "version": "23.9.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.9.0.tgz", - "integrity": "sha512-hLVrav2HYMVdK0YILtfJwtnkBAwNOztUdR4aJ5YKDvgsbtagNr6urUJk9HyjRA9e+PaLI3jzJ0wM7A4jSZ7Qxw==", + "version": "22.15.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", + "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.4.1", - "chromium-bidi": "0.8.0", - "debug": "^4.3.7", - "devtools-protocol": "0.0.1367902", - "typed-query-selector": "^2.12.0", + "@puppeteer/browsers": "2.3.0", + "chromium-bidi": "0.6.3", + "debug": "^4.3.6", + "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" }, "engines": { @@ -7498,6 +7389,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7650,6 +7547,12 @@ "node": ">=0.10.0" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -8646,24 +8549,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "license": "MIT" }, - "node_modules/tldts": { - "version": "6.1.64", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.64.tgz", - "integrity": "sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw==", - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.64" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.64", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.64.tgz", - "integrity": "sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q==", - "license": "MIT" - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -8704,15 +8589,27 @@ } }, "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "node": ">=16" + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" } }, "node_modules/tr46": { @@ -8896,12 +8793,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-query-selector": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "license": "MIT" - }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -9007,6 +8898,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", @@ -9029,16 +8930,16 @@ } }, "node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/esm/bin/uuid" + "uuid": "dist/bin/uuid" } }, "node_modules/v8-to-istanbul": { @@ -9230,9 +9131,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", + "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", "dev": true, "license": "MIT", "dependencies": {