From 7f896e5c557f767b1e99beb2b97c9cf3a017a946 Mon Sep 17 00:00:00 2001 From: azka Date: Mon, 27 Jan 2025 13:26:56 +0500 Subject: [PATCH 1/5] refactor backend phase 1(postgresql integration,apis backend,store response,ddl) --- bun.lockb | Bin 77714 -> 96237 bytes index.ts | 17 +- package-lock.json | 2987 ++++++++++++++++++++++++++ package.json | 11 +- src/config/db.ts | 18 + src/config/env.ts | 7 + src/controller/website.controller.ts | 36 + src/database/website.query.ts | 6 + src/models/website.model.ts | 0 src/routes/website.routes.ts | 12 + src/services/pagespeed.service.ts | 23 + src/sheets.ts | 122 +- src/utils/logger.ts | 4 + 13 files changed, 3179 insertions(+), 64 deletions(-) create mode 100644 package-lock.json create mode 100644 src/config/db.ts create mode 100644 src/config/env.ts create mode 100644 src/controller/website.controller.ts create mode 100644 src/database/website.query.ts create mode 100644 src/models/website.model.ts create mode 100644 src/routes/website.routes.ts create mode 100644 src/services/pagespeed.service.ts create mode 100644 src/utils/logger.ts diff --git a/bun.lockb b/bun.lockb index 05dcbace93f7944374302573615212f331733469..4ca0da16724cb68dce148ff154f046db729bc7a2 100755 GIT binary patch delta 25261 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 delta 14485 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 pCMS+6EiOvL|D5f { + console.log(`Server is running on http://localhost:${config.PORT}`); + }); + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..da6a03e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2987 @@ +{ + "name": "watchtower", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "watchtower", + "dependencies": { + "@google-cloud/local-auth": "^3.0.1", + "@googleapis/sheets": "^6.0.0", + "axios": "^1.7.9", + "bun": "^1.2.0", + "circular-json": "^0.5.9", + "dotenv": "^16.4.7", + "elysia": "^1.2.10", + "googleapis": "^140.0.0", + "pg": "^8.13.1", + "yargs": "^17.7.2" + }, + "bin": { + "watchtower": "index.ts" + }, + "devDependencies": { + "@types/bun": "latest", + "@types/pg": "^8.11.11", + "@types/yargs": "^17.0.32", + "lighthouse": "^12.0.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.2.tgz", + "integrity": "sha512-6sE5nyvDloULiyOMbOTJEEgWL32w+VHkZQs8S02Lnn8Y/O5aQhjOEXwWzvR7SsBE/exxlSpY2EsWZgqHbtLatg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.6", + "@formatjs/intl-localematcher": "0.5.10", + "decimal.js": "10", + "tslib": "2" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz", + "integrity": "sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.0.tgz", + "integrity": "sha512-Hp81uTjjdTk3FLh/dggU5NK7EIsVWc5/ZDWrIldmf2rBuPejuZ13CZ/wpVE2SToyi4EiroPTQ1XJcJuZFIxTtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.2", + "@formatjs/icu-skeleton-parser": "1.8.12", + "tslib": "2" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.12.tgz", + "integrity": "sha512-QRAY2jC1BomFQHYDMcZtClqHR55EEnB96V7Xbk/UiBodsuFc5kujybzt87+qj1KqmJozFhk6n4KiT1HKwAkcfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.2", + "tslib": "2" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz", + "integrity": "sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, + "node_modules/@google-cloud/local-auth": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/local-auth/-/local-auth-3.0.1.tgz", + "integrity": "sha512-YJ3GFbksfHyEarbVHPSCzhKpjbnlAhdzg2SEf79l6ODukrSM1qUOqfopY232Xkw26huKSndyzmJz+A6b2WYn7Q==", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.1", + "google-auth-library": "^9.0.0", + "open": "^7.0.3", + "server-destroy": "^1.0.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@googleapis/sheets": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@googleapis/sheets/-/sheets-6.1.0.tgz", + "integrity": "sha512-6ja4IxUNOiL17jlDxjUDzT7uQgiov2Q4l28Z9CtdJMbg9OsHHodQbAf+U0z/u3V8u84UgbdtQR5Go9w31UPHKw==", + "license": "Apache-2.0", + "dependencies": { + "googleapis-common": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@oven/bun-darwin-aarch64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.2.0.tgz", + "integrity": "sha512-51gx0Q7MJshZn554VEHj599/TVW+IDcYITWDzxeRyBN96vrbnYT9sGT58tCvN/yVrJBcTH83aHgjsOefM/egrQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.2.0.tgz", + "integrity": "sha512-LxbuMT5h5IgBbBpCzUCz9JlAIRcVy9tLJ54s+X6H8qpaDNf4TL+bmZQEog/VZMHdyFVQignSiTI6zPkPnoF+Kw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-darwin-x64-baseline": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.2.0.tgz", + "integrity": "sha512-ZgtE37T6ogQjp25JZRYbxy4Iziw7+THEnm2Mb+SyjimLSmU10d0fgYsPrT5ZIWfsMh42IXPgUFksG7IY7CmR/A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-linux-aarch64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.2.0.tgz", + "integrity": "sha512-1N10z7tQE1CwrSHuhdQFxl1vUd86VKqt1258a++m9EUwZ+uQMYnoevKyDc2TiwJF4yXG1AHc1STz7biQ1q/wNA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-aarch64-musl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.2.0.tgz", + "integrity": "sha512-sXfkddLwsOF6x2YfDkmbfuwV5BgaI53G1nh2/cq7iLf1HhdWDhbmB4i9Dw68Gy3tXTrezOOQqZ5+un5OOOXXxg==", + "cpu": [ + "aarch64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.2.0.tgz", + "integrity": "sha512-QGXdeY0zkTSMYqIJ1crDF8gvRx0JeRYjd/nmfpxnuxyVNjUUVZHaQKMHvGGptPmkzvhEvCYnWmh2wmCFQmCZBw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64-baseline": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.2.0.tgz", + "integrity": "sha512-eXxEbZxUO02EAofgMW1SCiMlGgS0F8NSvF7xTgSAxl8WYYDAR9GVu37DIwGokXBKBuysgdZuBUb7IpWzB+n6IQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64-musl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.2.0.tgz", + "integrity": "sha512-pJjVzEiS9HXuWy4LdbmiOLUmU1l2pUAWbbd43OocJRYvZL54cZpE+x0yUyEb38vd+jkHQu0ty8jHMyl+fBNUZA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64-musl-baseline": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl-baseline/-/bun-linux-x64-musl-baseline-1.2.0.tgz", + "integrity": "sha512-/M53/WHnhKjgFxQXljapXMnQvkdZ9EzK9LuWjZ0Kw3WCx9n2v7MS2803vjpiVwUxoDYpq1+wSyXIaEloZQ/R5w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-windows-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.2.0.tgz", + "integrity": "sha512-inCrG8tQJ9Sz5N8uVoDwoR+QFDLbOcfAkGtjEvnn6djeyDx8PbO8IErhbrpkb+10vtGDFWaOr0XVS7kuSu08Fw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oven/bun-windows-x64-baseline": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.2.0.tgz", + "integrity": "sha512-A+U0PGh0twPTbUNwK2BZcFR8fWDumWOAiTReTWTK0wOIcQIy9DCTzKhxBffYNwLhf8BxLkJpoEag7wL1AWiejg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@paulirish/trace_engine": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.39.tgz", + "integrity": "sha512-2Y/ejHX5DDi5bjfWY/0c/BLVSfQ61Jw1Hy60Hnh0hfEO632D3FVctkzT4Q/lVAdvIPR0bUaok9JDTr1pu/OziA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "third-party-web": "latest" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", + "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.3.tgz", + "integrity": "sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/core": "7.120.3", + "@sentry/types": "7.120.3", + "@sentry/utils": "7.120.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/core": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.3.tgz", + "integrity": "sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/types": "7.120.3", + "@sentry/utils": "7.120.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/integrations": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.120.3.tgz", + "integrity": "sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/core": "7.120.3", + "@sentry/types": "7.120.3", + "@sentry/utils": "7.120.3", + "localforage": "^1.8.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/node": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.120.3.tgz", + "integrity": "sha512-t+QtekZedEfiZjbkRAk1QWJPnJlFBH/ti96tQhEq7wmlk3VszDXraZvLWZA0P2vXyglKzbWRGkT31aD3/kX+5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry-internal/tracing": "7.120.3", + "@sentry/core": "7.120.3", + "@sentry/integrations": "7.120.3", + "@sentry/types": "7.120.3", + "@sentry/utils": "7.120.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/types": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.3.tgz", + "integrity": "sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/utils": { + "version": "7.120.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.3.tgz", + "integrity": "sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/types": "7.120.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.14", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.14.tgz", + "integrity": "sha512-TJ7Al17j3+by5y2QkTLcF/oBVMbgXBhILVgi9PuwpxQVZZvGh5BFRzWbJPmZVNKpbRLjuMzFuRwR+tdFPqCkvA==", + "license": "MIT" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bun": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.2.0.tgz", + "integrity": "sha512-5N1JqdahfpBlAv4wy6svEYcd/YfO2GNrbL95JOmFx8nkE6dbK4R0oSE5SpBA4vBRqgrOUAXF8Dpiz+gi7r80SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bun-types": "1.2.0" + } + }, + "node_modules/@types/node": { + "version": "22.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", + "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/pg": { + "version": "8.11.11", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz", + "integrity": "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/ws": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", + "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.1.tgz", + "integrity": "sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^3.0.0", + "bare-stream": "^2.0.0" + }, + "engines": { + "bare": ">=1.7.0" + } + }, + "node_modules/bare-os": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.4.0.tgz", + "integrity": "sha512-9Ous7UlnKbe3fMi7Y+qh0DwAup6A1JkYgPnjvMDNOlmnxNRQvQ/7Nst+OnUQKzk0iAT0m9BisbDVp9gCv8+ETA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.6.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.4.tgz", + "integrity": "sha512-G6i3A74FjNq4nVrrSTUz5h3vgXzBJnjmWAVlBWaZETkgu+LgKd7AiyOml3EDJY1AHlIbBHKDXE+TUT53Ff8OaA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "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/bun": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.2.0.tgz", + "integrity": "sha512-QUt9418MMPgylSsfOjGABV0aodlVZmQ6goCn/o0tf6jVKkPFgaMw643iv+Uo5uqEKtECaDCbCmssqofq1nVgvw==", + "cpu": [ + "arm64", + "x64", + "aarch64" + ], + "hasInstallScript": true, + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32" + ], + "bin": { + "bun": "bin/bun.exe", + "bunx": "bin/bun.exe" + }, + "optionalDependencies": { + "@oven/bun-darwin-aarch64": "1.2.0", + "@oven/bun-darwin-x64": "1.2.0", + "@oven/bun-darwin-x64-baseline": "1.2.0", + "@oven/bun-linux-aarch64": "1.2.0", + "@oven/bun-linux-aarch64-musl": "1.2.0", + "@oven/bun-linux-x64": "1.2.0", + "@oven/bun-linux-x64-baseline": "1.2.0", + "@oven/bun-linux-x64-musl": "1.2.0", + "@oven/bun-linux-x64-musl-baseline": "1.2.0", + "@oven/bun-windows-x64": "1.2.0", + "@oven/bun-windows-x64-baseline": "1.2.0" + } + }, + "node_modules/bun-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.2.0.tgz", + "integrity": "sha512-KEaJxyZfbV/c4eyG0vyehDpYmBGreNiQbZIqvVHJwZ4BmeuWlNZ7EAzMN2Zcd7ailmS/tGVW0BgYbGf+lGEpWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/ws": "~8.5.10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chrome-launcher": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.1.2.tgz", + "integrity": "sha512-YclTJey34KUm5jB1aEJCq807bSievi7Nb/TU4Gu504fUYi3jw3KCIaH6L7nFWQhdEgH3V+wCh+kKD1P5cXnfxw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^2.0.1" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chromium-bidi": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", + "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "deprecated": "CircularJSON is in maintenance only, flatted is its successor.", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/csp_evaluator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", + "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1312386", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/elysia": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.2.10.tgz", + "integrity": "sha512-QcNl2FjhHFRpKaqy1NoMpyCjJ7OcKBnHwLUkqGu09QwIV84PFb82ILvYJG4GS1RbGv76OA50luaqBLrM3SLZ2w==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.13", + "cookie": "^1.0.2", + "memoirist": "^0.2.0", + "openapi-types": "^12.1.3" + }, + "peerDependencies": { + "@sinclair/typebox": ">= 0.34.0", + "openapi-types": ">= 12.0.0", + "typescript": ">= 5.0.0" + }, + "peerDependenciesMeta": { + "openapi-types": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/google-auth-library": { + "version": "9.15.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", + "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/googleapis": { + "version": "140.0.1", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-140.0.1.tgz", + "integrity": "sha512-ZGvBX4mQcFXO9ACnVNg6Aqy3KtBPB5zTuue43YVLxwn8HSv8jB7w+uDKoIPSoWuxGROgnj2kbng6acXncOQRNA==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^9.0.0", + "googleapis-common": "^7.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/googleapis-common": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", + "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "gaxios": "^6.0.3", + "google-auth-library": "^9.7.0", + "qs": "^6.7.0", + "url-template": "^2.0.8", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "license": "MIT", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-link-header": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.3.tgz", + "integrity": "sha512-3cZ0SRL8fb9MUlU3mKM61FcQvPfXx2dBrZW3Vbg5CXa8jFlK8OaEpePenLe1oEXQduhz8b0QjsqfS59QP4AJDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/image-ssim": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/intl-messageformat": { + "version": "10.7.14", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.14.tgz", + "integrity": "sha512-mMGnE4E1otdEutV5vLUdCxRJygHB5ozUBxsPB5qhitewssrS/qGruq9bmvIRkkGsNeK5ZWLfYRld18UHGTIifQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.2", + "@formatjs/fast-memoize": "2.2.6", + "@formatjs/icu-messageformat-parser": "2.11.0", + "tslib": "2" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/js-library-detector": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", + "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "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": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lighthouse": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-12.3.0.tgz", + "integrity": "sha512-OaLE8DasnwQkn2CBo2lKtD+IQv42mNP3T+Vaw29I++rAh0Zpgc6SM15usdIYyzhRMR5EWFxze5Fyb+HENJSh2A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@paulirish/trace_engine": "0.0.39", + "@sentry/node": "^7.0.0", + "axe-core": "^4.10.2", + "chrome-launcher": "^1.1.2", + "configstore": "^5.0.1", + "csp_evaluator": "1.1.1", + "devtools-protocol": "0.0.1312386", + "enquirer": "^2.3.6", + "http-link-header": "^1.1.1", + "intl-messageformat": "^10.5.3", + "jpeg-js": "^0.4.4", + "js-library-detector": "^6.7.0", + "lighthouse-logger": "^2.0.1", + "lighthouse-stack-packs": "1.12.2", + "lodash-es": "^4.17.21", + "lookup-closest-locale": "6.2.0", + "metaviewport-parser": "0.3.0", + "open": "^8.4.0", + "parse-cache-control": "1.0.1", + "puppeteer-core": "^23.10.4", + "robots-parser": "^3.0.1", + "semver": "^5.3.0", + "speedline-core": "^1.4.3", + "third-party-web": "^0.26.1", + "tldts-icann": "^6.1.16", + "ws": "^7.0.0", + "yargs": "^17.3.1", + "yargs-parser": "^21.0.0" + }, + "bin": { + "chrome-debug": "core/scripts/manual-chrome-launcher.js", + "lighthouse": "cli/index.js", + "smokehouse": "cli/test/smokehouse/frontends/smokehouse-bin.js" + }, + "engines": { + "node": ">=18.16" + } + }, + "node_modules/lighthouse-logger": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-2.0.1.tgz", + "integrity": "sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/lighthouse-stack-packs": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.12.2.tgz", + "integrity": "sha512-Ug8feS/A+92TMTCK6yHYLwaFMuelK/hAKRMdldYkMNwv+d9PtWxjXEg6rwKtsUXTADajhdrhXyuNCJ5/sfmPFw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/lighthouse/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lookup-closest-locale": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoirist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memoirist/-/memoirist-0.2.0.tgz", + "integrity": "sha512-DA1V11OWsKmYjgYHfT1luus0FtTjUbILfI9s5M+ckK29tBLON6GDhH5GwxDz7E1ou4Bdzm9vhbeCaRAWxwG+0g==", + "license": "MIT" + }, + "node_modules/metaviewport-parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", + "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT" + }, + "node_modules/pac-proxy-agent": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pg": { + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", + "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.7.0", + "pg-pool": "^3.7.0", + "pg-protocol": "^1.7.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-pool": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", + "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", + "dev": true, + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.1.0", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pg/node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postgres-date": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-range": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer-core": { + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", + "integrity": "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1367902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core/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==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/puppeteer-core/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/robots-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", + "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speedline-core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", + "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "image-ssim": "^0.2.0", + "jpeg-js": "^0.4.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/streamx": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", + "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", + "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/third-party-web": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.26.2.tgz", + "integrity": "sha512-taJ0Us0lKoYBqcbccMuDElSUPOxmBfwlHe1OkHQ3KFf+RwovvBHdXhbFk9XJVQE2vHzxbTwvwg5GFsT9hbDokQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tldts-core": { + "version": "6.1.74", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.74.tgz", + "integrity": "sha512-gTwtY6L2GfuxiL4CWpLknv9JDYYqBvKCk/BT5uAaAvCA0s6pzX7lr2IrkQZSUlnSjRHIjTl8ZwKCVXJ7XNRWYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tldts-icann": { + "version": "6.1.74", + "resolved": "https://registry.npmjs.org/tldts-icann/-/tldts-icann-6.1.74.tgz", + "integrity": "sha512-v8pT30geByIeKzU8rbAGEhMx/mJQIJhkt1mE286IyEAvZNzqcyQIumW96syfHVio/L7Eq6y8Q5YVQRw0uVyqaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.74" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "license": "BSD" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json index caa32b4..b33b2a2 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ }, "devDependencies": { "@types/bun": "latest", + "@types/pg": "^8.11.11", "@types/yargs": "^17.0.32", "lighthouse": "^12.0.0" }, @@ -16,8 +17,14 @@ "dependencies": { "@google-cloud/local-auth": "^3.0.1", "@googleapis/sheets": "^6.0.0", - "dotenv": "^16.4.5", + "axios": "^1.7.9", + "bun": "^1.2.0", + "circular-json": "^0.5.9", + "dotenv": "^16.4.7", + "elysia": "^1.2.10", + "flatted": "^3.3.2", "googleapis": "^140.0.0", + "pg": "^8.13.1", "yargs": "^17.7.2" } -} \ No newline at end of file +} diff --git a/src/config/db.ts b/src/config/db.ts new file mode 100644 index 0000000..0ecc6cb --- /dev/null +++ b/src/config/db.ts @@ -0,0 +1,18 @@ +import { Client } from "pg"; +import { config } from "./env"; + +const client = new Client({ + connectionString: config.DATABASE_URL, +}); + +export const connectDB = async () => { + try { + await client.connect(); + console.log("Connected to PostgreSQL"); + } catch (error) { + console.error("Database connection failed", error); + process.exit(1); + } +}; + +export default client; diff --git a/src/config/env.ts b/src/config/env.ts new file mode 100644 index 0000000..223a8bb --- /dev/null +++ b/src/config/env.ts @@ -0,0 +1,7 @@ +import "dotenv/config"; + +export const config = { + DATABASE_URL: process.env.DATABASE_URL as string, + PAGESPEED_API_KEY: process.env.PAGESPEED_API_KEY as string, + PORT: process.env.PORT || 3000, +}; diff --git a/src/controller/website.controller.ts b/src/controller/website.controller.ts new file mode 100644 index 0000000..040abe4 --- /dev/null +++ b/src/controller/website.controller.ts @@ -0,0 +1,36 @@ +import { get_websites, store_website_stats } from "../database/website.query"; +import { fetchPageSpeedData } from "../services/pagespeed.service"; +import pg from "pg"; +import { config } from "../config/env"; +import CircularJSON from "circular-json"; + +const client = new pg.Client({ + connectionString: config.DATABASE_URL, +}); +export const fetchAndStoreWebsiteStats = async () => { + try { + await client.connect(); + + const query = get_websites(); + const websites = await client.query(query); + + // Process all websites in parallel using Promise.allSettled + await Promise.allSettled( + websites.rows.map(async (website) => { + try { + const stats = await fetchPageSpeedData(website.url); + const safeStats = CircularJSON.stringify(stats); + await client.query(store_website_stats(website.id, safeStats)); + console.log(`Successfully stored stats for: ${website.url}`); + } catch (innerError) { + console.error(`Failed to process ${website.url}:`, innerError); + } + }) + ); + + return true; + } catch (error) { + console.error("Error fetching and storing stats:", error); + } + }; + \ No newline at end of file diff --git a/src/database/website.query.ts b/src/database/website.query.ts new file mode 100644 index 0000000..cb0a171 --- /dev/null +++ b/src/database/website.query.ts @@ -0,0 +1,6 @@ +const get_websites = () => `SELECT id,url FROM websites;`; +const store_website_stats = (websiteId: number, stats: object) => ` + INSERT INTO website_stats (website_id, stats) + VALUES (${websiteId}, '${JSON.stringify(stats)}'::jsonb) returning id; +`; +export {get_websites,store_website_stats}; \ No newline at end of file diff --git a/src/models/website.model.ts b/src/models/website.model.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/website.routes.ts b/src/routes/website.routes.ts new file mode 100644 index 0000000..401a2d5 --- /dev/null +++ b/src/routes/website.routes.ts @@ -0,0 +1,12 @@ +import { Elysia } from "elysia"; +import { fetchAndStoreWebsiteStats } from "../controller/website.controller"; + +const router = new Elysia(); + +router.post("/fetch-stats", async () => { + await fetchAndStoreWebsiteStats(); + return { message: "Response Stored Successfully." }; +}); + +export default router; + diff --git a/src/services/pagespeed.service.ts b/src/services/pagespeed.service.ts new file mode 100644 index 0000000..718f323 --- /dev/null +++ b/src/services/pagespeed.service.ts @@ -0,0 +1,23 @@ +import axios from "axios"; +import { config } from "../config/env"; + +export const fetchPageSpeedData = async (url: string) => { + try { + const response = await axios.get( + `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}&key=${config.PAGESPEED_API_KEY}` + ); + + const json = response.data; + const cleanedResponse = { + url: json.id, + fetchTime: json.lighthouseResult.fetchTime, + performance: json.lighthouseResult.categories.performance + }; + + return cleanedResponse; + + } catch (error) { + console.error("Error fetching PageSpeed data:", error); + throw new Error("Failed to fetch website statistics"); + } +}; diff --git a/src/sheets.ts b/src/sheets.ts index 39489a4..ab8986a 100644 --- a/src/sheets.ts +++ b/src/sheets.ts @@ -1,72 +1,72 @@ -import { sheets, sheets_v4 } from "@googleapis/sheets"; -import { authenticate } from "@google-cloud/local-auth"; -import { OAuth2Client } from 'google-auth-library'; -import {google} from 'googleapis'; +// import { sheets, sheets_v4 } from "@googleapis/sheets"; +// import { authenticate } from "@google-cloud/local-auth"; +// import { OAuth2Client } from 'google-auth-library'; +// import {google} from 'googleapis'; -const sheetsModule: sheets_v4.Sheets = sheets("v4"); +// const sheetsModule: sheets_v4.Sheets = sheets("v4"); -let auth: OAuth2Client | JSONClient | Compute | null = null; +// // let auth: OAuth2Client | JSONClient | Compute | null = null; -/** - * Perform authentication using the key file and return an instance of the client. - * - * This function will only perform the authentication once every time the CLI is run if needed. - */ -async function getOAuth2Token(): Promise { - if (auth == null) { - const googleAuth = new google.auth.GoogleAuth({ - keyFilename: "oauth2.keys.json", - scopes: [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/spreadsheets", - ], - }); +// /** +// * Perform authentication using the key file and return an instance of the client. +// * +// * This function will only perform the authentication once every time the CLI is run if needed. +// */ +// async function getOAuth2Token(): Promise { +// if (auth == null) { +// const googleAuth = new google.auth.GoogleAuth({ +// keyFilename: "oauth2.keys.json", +// scopes: [ +// "https://www.googleapis.com/auth/drive", +// "https://www.googleapis.com/auth/drive.file", +// "https://www.googleapis.com/auth/spreadsheets", +// ], +// }); - auth = await googleAuth.getClient(); - } +// auth = await googleAuth.getClient(); +// } - return auth; -} +// return auth; +// } -/** - * Append some data values to a certain spreadsheet with a given range. - * @param {string} spreadsheetId - The id of the spreadsheet we want to append to. - * @param {string} range - The sheet and cells in the spreadsheet that we want to append to. For example, - * the range 'Scores!A2:B' means accessing the Scores sheet, from cell A2 to B. - * @param {any[][]} values - The values that we want to append to the spreadsheet at the specified range. - * This is a list of lists, corresponding to first the row and then the cells. - */ -export async function appendToSheet(spreadsheetId: string, range: string, values: any[][]) { - const auth = await getOAuth2Token(); +// /** +// * Append some data values to a certain spreadsheet with a given range. +// * @param {string} spreadsheetId - The id of the spreadsheet we want to append to. +// * @param {string} range - The sheet and cells in the spreadsheet that we want to append to. For example, +// * the range 'Scores!A2:B' means accessing the Scores sheet, from cell A2 to B. +// * @param {any[][]} values - The values that we want to append to the spreadsheet at the specified range. +// * This is a list of lists, corresponding to first the row and then the cells. +// */ +// export async function appendToSheet(spreadsheetId: string, range: string, values: any[][]) { +// const auth = await getOAuth2Token(); - await sheetsModule.spreadsheets.values.append({ - auth, - spreadsheetId, - range, - valueInputOption: "USER_ENTERED", - requestBody: { values }, - }); -} +// await sheetsModule.spreadsheets.values.append({ +// auth, +// spreadsheetId, +// range, +// valueInputOption: "USER_ENTERED", +// requestBody: { values }, +// }); +// } -/** - * Read data from a certain spreadsheet with a given range. - * @param {string} spreadsheetId - The id of the spreadsheet we want to read from. - * @param {string} range - The sheet and cells in the spreadsheet that we want to append to. For example, - * the range 'Scores!A2:B' means accessing the Scores sheet, from cell A2 to B. - */ -export async function getSheetData(spreadsheetId: string, range: string): Promise { - const auth = await getOAuth2Token(); +// /** +// * Read data from a certain spreadsheet with a given range. +// * @param {string} spreadsheetId - The id of the spreadsheet we want to read from. +// * @param {string} range - The sheet and cells in the spreadsheet that we want to append to. For example, +// * the range 'Scores!A2:B' means accessing the Scores sheet, from cell A2 to B. +// */ +// export async function getSheetData(spreadsheetId: string, range: string): Promise { +// const auth = await getOAuth2Token(); - const results = await sheetsModule.spreadsheets.values.get({ - auth, - spreadsheetId, - range, - }); +// const results = await sheetsModule.spreadsheets.values.get({ +// auth, +// spreadsheetId, +// range, +// }); - if (results.data.values != null) { - return results.data.values - } +// if (results.data.values != null) { +// return results.data.values +// } - return [] -} \ No newline at end of file +// return [] +// } \ No newline at end of file diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..81accc9 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,4 @@ +export const logger = (message: string) => { + console.log(`[${new Date().toISOString()}] ${message}`); + }; + \ No newline at end of file From 3eaadb16b789f70ca1eb1ada97d85ae25d4d731d Mon Sep 17 00:00:00 2001 From: azka Date: Thu, 30 Jan 2025 18:37:01 +0500 Subject: [PATCH 2/5] refactor code --- src/{ => backend_v1}/cli.ts | 0 src/{ => backend_v1}/crawler.ts | 0 src/{ => backend_v1}/service.ts | 0 src/{ => backend_v1}/sheets.ts | 0 src/controller/website.controller.ts | 32 +++++++++++++++++++++++++--- src/database/website.query.ts | 15 ++++++++++++- src/routes/website.routes.ts | 10 +++++++-- 7 files changed, 51 insertions(+), 6 deletions(-) rename src/{ => backend_v1}/cli.ts (100%) rename src/{ => backend_v1}/crawler.ts (100%) rename src/{ => backend_v1}/service.ts (100%) rename src/{ => backend_v1}/sheets.ts (100%) diff --git a/src/cli.ts b/src/backend_v1/cli.ts similarity index 100% rename from src/cli.ts rename to src/backend_v1/cli.ts diff --git a/src/crawler.ts b/src/backend_v1/crawler.ts similarity index 100% rename from src/crawler.ts rename to src/backend_v1/crawler.ts diff --git a/src/service.ts b/src/backend_v1/service.ts similarity index 100% rename from src/service.ts rename to src/backend_v1/service.ts diff --git a/src/sheets.ts b/src/backend_v1/sheets.ts similarity index 100% rename from src/sheets.ts rename to src/backend_v1/sheets.ts diff --git a/src/controller/website.controller.ts b/src/controller/website.controller.ts index 040abe4..43fc771 100644 --- a/src/controller/website.controller.ts +++ b/src/controller/website.controller.ts @@ -1,4 +1,4 @@ -import { get_websites, store_website_stats } from "../database/website.query"; +import { get_stats_q, get_websites, store_website_stats } from "../database/website.query"; import { fetchPageSpeedData } from "../services/pagespeed.service"; import pg from "pg"; import { config } from "../config/env"; @@ -13,8 +13,6 @@ export const fetchAndStoreWebsiteStats = async () => { const query = get_websites(); const websites = await client.query(query); - - // Process all websites in parallel using Promise.allSettled await Promise.allSettled( websites.rows.map(async (website) => { try { @@ -33,4 +31,32 @@ export const fetchAndStoreWebsiteStats = async () => { console.error("Error fetching and storing stats:", error); } }; + export const get_states = async (param: Param) => { + try { + await client.connect(); + + const query = get_stats_q(param); + const stats = await client.query(query); + + if (stats.rows.length > 0) { + + const parsedStats = stats.rows.map(row => { + return { + ...row, + stats: row.stats ? JSON.parse(row.stats) : null + }; + }); + + return parsedStats; + } else { + console.log("No data found"); + return []; + } + } catch (error) { + console.error("Error fetching and storing stats:", error); + return { message: "Error fetching stats", error: error.message }; + } finally { + await client.end(); // Make sure to close the client connection + } + }; \ No newline at end of file diff --git a/src/database/website.query.ts b/src/database/website.query.ts index cb0a171..d09113b 100644 --- a/src/database/website.query.ts +++ b/src/database/website.query.ts @@ -3,4 +3,17 @@ const store_website_stats = (websiteId: number, stats: object) => ` INSERT INTO website_stats (website_id, stats) VALUES (${websiteId}, '${JSON.stringify(stats)}'::jsonb) returning id; `; -export {get_websites,store_website_stats}; \ No newline at end of file + + interface Param { + url?: string; + } + + const get_stats_q = (param: Param) => ` + SELECT ws.website_id, w.url,ws.stats + FROM ${process.env.schema}.website_stats ws + JOIN ${process.env.schema}.websites w + ON ws.website_id = w.id + ${param.url && param.url !== "" ? `WHERE w.url = '${param.url}'` : ""} + `; + +export {get_websites,store_website_stats,get_stats_q}; \ No newline at end of file diff --git a/src/routes/website.routes.ts b/src/routes/website.routes.ts index 401a2d5..db7f43e 100644 --- a/src/routes/website.routes.ts +++ b/src/routes/website.routes.ts @@ -1,12 +1,18 @@ import { Elysia } from "elysia"; -import { fetchAndStoreWebsiteStats } from "../controller/website.controller"; +import { fetchAndStoreWebsiteStats, get_states } from "../controller/website.controller"; const router = new Elysia(); -router.post("/fetch-stats", async () => { +router.post("/store-stats", async () => { await fetchAndStoreWebsiteStats(); return { message: "Response Stored Successfully." }; }); +router.get("/get-stats", async () => { + return get_states(); + return { message: "Response Stord Successfully." }; + }); + + export default router; From fabfefd29ec4ed17c6ac742f86491f8b966410b6 Mon Sep 17 00:00:00 2001 From: azka Date: Thu, 30 Jan 2025 21:36:06 +0500 Subject: [PATCH 3/5] refactor code backend --- package-lock.json | 51 ++++++++++++++++++++++++++++ package.json | 2 ++ src/config/db.ts | 24 ++++++------- src/controller/website.controller.ts | 11 +++--- src/database/website.query.ts | 8 ++--- src/ddl/generic.sql | 16 +++++++++ src/routes/website.routes.ts | 9 +++-- 7 files changed, 97 insertions(+), 24 deletions(-) create mode 100644 src/ddl/generic.sql diff --git a/package-lock.json b/package-lock.json index da6a03e..6179072 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,10 @@ "circular-json": "^0.5.9", "dotenv": "^16.4.7", "elysia": "^1.2.10", + "flatted": "^3.3.2", "googleapis": "^140.0.0", + "node-cache": "^5.1.2", + "node-cron": "^3.0.3", "pg": "^8.13.1", "yargs": "^17.7.2" }, @@ -846,6 +849,15 @@ "node": ">=12" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1250,6 +1262,12 @@ "pend": "~1.2.0" } }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -1971,6 +1989,39 @@ "node": ">= 0.4.0" } }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "license": "MIT", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "license": "ISC", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-cron/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", diff --git a/package.json b/package.json index b33b2a2..f001836 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "elysia": "^1.2.10", "flatted": "^3.3.2", "googleapis": "^140.0.0", + "node-cache": "^5.1.2", + "node-cron": "^3.0.3", "pg": "^8.13.1", "yargs": "^17.7.2" } diff --git a/src/config/db.ts b/src/config/db.ts index 0ecc6cb..242cad8 100644 --- a/src/config/db.ts +++ b/src/config/db.ts @@ -1,18 +1,18 @@ -import { Client } from "pg"; -import { config } from "./env"; +import pg from "pg"; +import { config } from "../config/env"; -const client = new Client({ +// Create a connection pool +const pool = new pg.Pool({ connectionString: config.DATABASE_URL, }); -export const connectDB = async () => { - try { - await client.connect(); - console.log("Connected to PostgreSQL"); - } catch (error) { - console.error("Database connection failed", error); - process.exit(1); +// Test the connection +pool.query("SELECT NOW()", (err) => { + if (err) { + console.error("Failed to connect to the database:", err); + } else { + console.log("Database connected successfully."); } -}; +}); -export default client; +export { pool }; \ No newline at end of file diff --git a/src/controller/website.controller.ts b/src/controller/website.controller.ts index 43fc771..b9377b5 100644 --- a/src/controller/website.controller.ts +++ b/src/controller/website.controller.ts @@ -3,13 +3,15 @@ import { fetchPageSpeedData } from "../services/pagespeed.service"; import pg from "pg"; import { config } from "../config/env"; import CircularJSON from "circular-json"; - +import NodeCache from "node-cache"; +import { pool } from "../config/db"; +const cache = new NodeCache({ stdTTL: 0 }); const client = new pg.Client({ connectionString: config.DATABASE_URL, }); export const fetchAndStoreWebsiteStats = async () => { try { - await client.connect(); + const client = await pool.connect(); const query = get_websites(); const websites = await client.query(query); @@ -33,11 +35,9 @@ export const fetchAndStoreWebsiteStats = async () => { }; export const get_states = async (param: Param) => { try { - await client.connect(); - + const client = await pool.connect(); const query = get_stats_q(param); const stats = await client.query(query); - if (stats.rows.length > 0) { const parsedStats = stats.rows.map(row => { @@ -59,4 +59,3 @@ export const fetchAndStoreWebsiteStats = async () => { await client.end(); // Make sure to close the client connection } }; - \ No newline at end of file diff --git a/src/database/website.query.ts b/src/database/website.query.ts index d09113b..622d234 100644 --- a/src/database/website.query.ts +++ b/src/database/website.query.ts @@ -8,12 +8,12 @@ const store_website_stats = (websiteId: number, stats: object) => ` url?: string; } - const get_stats_q = (param: Param) => ` + const get_stats_q = (url:string) => ` SELECT ws.website_id, w.url,ws.stats - FROM ${process.env.schema}.website_stats ws - JOIN ${process.env.schema}.websites w + FROM website_stats ws + JOIN websites w ON ws.website_id = w.id - ${param.url && param.url !== "" ? `WHERE w.url = '${param.url}'` : ""} + --${url && url !== "" ? `WHERE w.url = '${url}'` : ""} `; export {get_websites,store_website_stats,get_stats_q}; \ No newline at end of file diff --git a/src/ddl/generic.sql b/src/ddl/generic.sql new file mode 100644 index 0000000..3a31163 --- /dev/null +++ b/src/ddl/generic.sql @@ -0,0 +1,16 @@ +CREATE TABLE public.websites ( + id serial4 NOT NULL, + "name" varchar(255) NOT NULL, + url text NOT NULL, + created_at timestamp DEFAULT now() NULL, + CONSTRAINT websites_pkey PRIMARY KEY (id), + CONSTRAINT websites_url_key UNIQUE (url) +); +CREATE TABLE public.website_stats ( + id serial4 NOT NULL, + website_id int4 NULL, + stats jsonb NOT NULL, + fetched_at timestamp DEFAULT now() NULL, + CONSTRAINT website_stats_pkey PRIMARY KEY (id), + CONSTRAINT website_stats_website_id_fkey FOREIGN KEY (website_id) REFERENCES public.websites(id) +); \ No newline at end of file diff --git a/src/routes/website.routes.ts b/src/routes/website.routes.ts index db7f43e..551e3ea 100644 --- a/src/routes/website.routes.ts +++ b/src/routes/website.routes.ts @@ -1,6 +1,6 @@ import { Elysia } from "elysia"; import { fetchAndStoreWebsiteStats, get_states } from "../controller/website.controller"; - +import cron from "node-cron"; const router = new Elysia(); router.post("/store-stats", async () => { @@ -12,7 +12,12 @@ router.get("/get-stats", async () => { return get_states(); return { message: "Response Stord Successfully." }; }); - + // Monthly cron job + cron.schedule("0 0 1 * *", async () => { + console.log("Running monthly PageSpeed insights update..."); + await fetchAndStoreWebsiteStats(); + console.log("Monthly update completed."); + }); export default router; From 9e9f343dedef58ce7c9922a5db2e69cc82f25db9 Mon Sep 17 00:00:00 2001 From: azka Date: Fri, 31 Jan 2025 17:08:49 +0500 Subject: [PATCH 4/5] scrap all govt websites and add them to db instead of manual insertion --- package-lock.json | 474 +++++++++++++++++++++++---- package.json | 2 + src/controller/website.controller.ts | 8 +- src/database/website.query.ts | 6 +- src/services/pagespeed.service.ts | 90 ++++- 5 files changed, 501 insertions(+), 79 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6179072..64834e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,9 @@ "googleapis": "^140.0.0", "node-cache": "^5.1.2", "node-cron": "^3.0.3", + "node-fetch": "^3.3.2", "pg": "^8.13.1", + "puppeteer": "^24.1.1", "yargs": "^17.7.2" }, "bin": { @@ -33,6 +35,29 @@ "typescript": "^5.0.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.2.tgz", @@ -400,7 +425,6 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true, "license": "MIT" }, "node_modules/@types/bun": { @@ -417,7 +441,7 @@ "version": "22.10.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -466,7 +490,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -516,6 +539,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -529,7 +558,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "license": "MIT", "dependencies": { "tslib": "^2.0.1" @@ -569,14 +597,12 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "dev": true, "license": "Apache-2.0" }, "node_modules/bare-events": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "dev": true, "license": "Apache-2.0", "optional": true }, @@ -584,7 +610,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.1.tgz", "integrity": "sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==", - "dev": true, "license": "Apache-2.0", "optional": true, "dependencies": { @@ -600,7 +625,6 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.4.0.tgz", "integrity": "sha512-9Ous7UlnKbe3fMi7Y+qh0DwAup6A1JkYgPnjvMDNOlmnxNRQvQ/7Nst+OnUQKzk0iAT0m9BisbDVp9gCv8+ETA==", - "dev": true, "license": "Apache-2.0", "optional": true, "engines": { @@ -611,7 +635,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "dev": true, "license": "Apache-2.0", "optional": true, "dependencies": { @@ -622,7 +645,6 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.4.tgz", "integrity": "sha512-G6i3A74FjNq4nVrrSTUz5h3vgXzBJnjmWAVlBWaZETkgu+LgKd7AiyOml3EDJY1AHlIbBHKDXE+TUT53Ff8OaA==", - "dev": true, "license": "Apache-2.0", "optional": true, "dependencies": { @@ -665,7 +687,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -684,7 +705,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -709,7 +729,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" @@ -795,6 +814,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/chrome-launcher": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.1.2.tgz", @@ -915,6 +943,32 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -936,7 +990,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 14" @@ -980,7 +1033,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "license": "MIT", "dependencies": { "ast-types": "^0.13.4", @@ -1090,7 +1142,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -1110,6 +1161,24 @@ "node": ">=8.6" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1166,7 +1235,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", @@ -1188,7 +1256,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -1202,7 +1269,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -1212,7 +1278,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -1228,7 +1293,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -1249,19 +1313,40 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true, "license": "MIT" }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/flatted": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", @@ -1302,6 +1387,18 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1327,6 +1424,26 @@ "node": ">=14" } }, + "node_modules/gaxios/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/gcp-metadata": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", @@ -1390,7 +1507,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -1406,7 +1522,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", - "dev": true, "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", @@ -1534,7 +1649,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -1561,7 +1675,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -1592,6 +1705,22 @@ "dev": true, "license": "MIT" }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1619,7 +1748,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, "license": "MIT", "dependencies": { "jsbn": "1.1.0", @@ -1629,6 +1757,12 @@ "node": ">= 12" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -1711,11 +1845,28 @@ "node": ">=12" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, "license": "MIT" }, "node_modules/json-bigint": { @@ -1727,6 +1878,12 @@ "bignumber.js": "^9.0.0" } }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/jwa": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", @@ -1856,6 +2013,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/localforage": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", @@ -1884,7 +2047,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -1970,7 +2132,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, "license": "MIT" }, "node_modules/ms": { @@ -1983,7 +2144,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -2022,24 +2182,50 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "license": "MIT", "dependencies": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-fetch/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" } }, "node_modules/object-inspect": { @@ -2065,7 +2251,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -2097,7 +2282,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", - "dev": true, "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -2117,7 +2301,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, "license": "MIT", "dependencies": { "degenerator": "^5.0.0", @@ -2127,17 +2310,46 @@ "node": ">= 14" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", "dev": true }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, "license": "MIT" }, "node_modules/pg": { @@ -2297,6 +2509,12 @@ "split2": "^4.1.0" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, "node_modules/postgres-array": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", @@ -2351,7 +2569,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -2361,7 +2578,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -2387,13 +2603,33 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "node_modules/puppeteer": { + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.1.1.tgz", + "integrity": "sha512-fuhceZ5HZuDXVuaMIRxUuDHfCJLmK0pXh8FlzVQ0/+OApStevxZhU5kAVeYFOEqeCF5OoAyZjcWbdQK27xW/9A==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.7.0", + "chromium-bidi": "1.1.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1380148", + "puppeteer-core": "24.1.1", + "typed-query-selector": "^2.12.0" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/puppeteer-core": { "version": "23.11.1", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", @@ -2441,6 +2677,106 @@ } } }, + "node_modules/puppeteer/node_modules/@puppeteer/browsers": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.7.0.tgz", + "integrity": "sha512-bO61XnTuopsz9kvtfqhVbH6LTM1koxK0IlBR+yuVrM2LB7mk8+5o1w18l5zqd5cs8xlf+ntgambqRqGifMDjog==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer/node_modules/chromium-bidi": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-1.1.0.tgz", + "integrity": "sha512-HislCEczCuamWm3+55Lig9XKmMF13K+BGKum9rwtDAzgUAHT4h5jNwhDmD4U20VoVUG8ujnv9UZ89qiIf5uF8w==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "zod": "3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/puppeteer/node_modules/devtools-protocol": { + "version": "0.0.1380148", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1380148.tgz", + "integrity": "sha512-1CJABgqLxbYxVI+uJY/UDUHJtJ0KZTSjNYJYKqd9FRoXT33WDakDHNxRapMEgzeJ/C3rcs01+avshMnPmKQbvA==", + "license": "BSD-3-Clause" + }, + "node_modules/puppeteer/node_modules/puppeteer-core": { + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.1.1.tgz", + "integrity": "sha512-7FF3gq6bpIsbq3I8mfbodXh3DCzXagoz3l2eGv1cXooYU4g0P4mcHQVHuBD4iSZPXNg8WjzlP5kmRwK9UvwF0A==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.7.0", + "chromium-bidi": "1.1.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1380148", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer/node_modules/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/puppeteer/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/puppeteer/node_modules/zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -2460,7 +2796,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true, "license": "MIT" }, "node_modules/require-directory": { @@ -2472,6 +2807,15 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/robots-parser": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", @@ -2601,7 +2945,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6.0.0", @@ -2612,7 +2955,6 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -2627,7 +2969,6 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -2642,7 +2983,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "optional": true, "engines": { @@ -2677,14 +3017,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/streamx": { "version": "2.21.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", - "dev": true, "license": "MIT", "dependencies": { "fast-fifo": "^1.3.2", @@ -2725,7 +3063,6 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -2740,7 +3077,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, "license": "MIT", "dependencies": { "b4a": "^1.6.4", @@ -2752,7 +3088,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" @@ -2769,7 +3104,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, "license": "MIT" }, "node_modules/tldts-core": { @@ -2799,14 +3133,12 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "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==", - "dev": true, "license": "MIT" }, "node_modules/typedarray-to-buffer": { @@ -2837,7 +3169,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, "license": "MIT", "dependencies": { "buffer": "^5.2.1", @@ -2848,7 +3179,7 @@ "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/unique-string": { @@ -2883,6 +3214,15 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -2920,7 +3260,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -3017,7 +3356,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", diff --git a/package.json b/package.json index f001836..517bffe 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "googleapis": "^140.0.0", "node-cache": "^5.1.2", "node-cron": "^3.0.3", + "node-fetch": "^3.3.2", "pg": "^8.13.1", + "puppeteer": "^24.1.1", "yargs": "^17.7.2" } } diff --git a/src/controller/website.controller.ts b/src/controller/website.controller.ts index b9377b5..d3d3e3f 100644 --- a/src/controller/website.controller.ts +++ b/src/controller/website.controller.ts @@ -1,5 +1,5 @@ import { get_stats_q, get_websites, store_website_stats } from "../database/website.query"; -import { fetchPageSpeedData } from "../services/pagespeed.service"; +import { fetchPageSpeedData, searchAndStoreGovPkWebsites } from "../services/pagespeed.service"; import pg from "pg"; import { config } from "../config/env"; import CircularJSON from "circular-json"; @@ -12,15 +12,15 @@ const client = new pg.Client({ export const fetchAndStoreWebsiteStats = async () => { try { const client = await pool.connect(); - + const pksites= await searchAndStoreGovPkWebsites(); const query = get_websites(); const websites = await client.query(query); await Promise.allSettled( websites.rows.map(async (website) => { try { const stats = await fetchPageSpeedData(website.url); - const safeStats = CircularJSON.stringify(stats); - await client.query(store_website_stats(website.id, safeStats)); + //const safeStats = CircularJSON.stringify(stats); + await client.query(store_website_stats(website.id, stats)); console.log(`Successfully stored stats for: ${website.url}`); } catch (innerError) { console.error(`Failed to process ${website.url}:`, innerError); diff --git a/src/database/website.query.ts b/src/database/website.query.ts index 622d234..c18bc42 100644 --- a/src/database/website.query.ts +++ b/src/database/website.query.ts @@ -1,8 +1,10 @@ const get_websites = () => `SELECT id,url FROM websites;`; const store_website_stats = (websiteId: number, stats: object) => ` INSERT INTO website_stats (website_id, stats) - VALUES (${websiteId}, '${JSON.stringify(stats)}'::jsonb) returning id; + VALUES (${websiteId}, '${JSON.stringify(stats)}'::jsonb) ON CONFLICT (website_id) DO NOTHING returning id; `; +const store_websites=(values:string)=> ` +insert into public.websites (url) values ${values} ON CONFLICT (url) DO NOTHING RETURNING id;` interface Param { url?: string; @@ -16,4 +18,4 @@ const store_website_stats = (websiteId: number, stats: object) => ` --${url && url !== "" ? `WHERE w.url = '${url}'` : ""} `; -export {get_websites,store_website_stats,get_stats_q}; \ No newline at end of file +export {get_websites,store_website_stats,get_stats_q,store_websites}; \ No newline at end of file diff --git a/src/services/pagespeed.service.ts b/src/services/pagespeed.service.ts index 718f323..120ea6f 100644 --- a/src/services/pagespeed.service.ts +++ b/src/services/pagespeed.service.ts @@ -1,6 +1,5 @@ import axios from "axios"; import { config } from "../config/env"; - export const fetchPageSpeedData = async (url: string) => { try { const response = await axios.get( @@ -8,16 +7,97 @@ export const fetchPageSpeedData = async (url: string) => { ); const json = response.data; + // console.log("API Response:", JSON.stringify(json, null, 2)); // Log the entire response + + // Check if the required fields exist + if (!json.lighthouseResult || !json.lighthouseResult.categories) { + throw new Error("Invalid API response structure"); + } + //console.log(json.lighthouseResult.categories) + const performanceScore = json.lighthouseResult.categories.performance?.score ; + const largest_contentful_paint = json.originLoadingExperience.metrics["LARGEST_CONTENTFUL_PAINT_MS"].percentile/1000 ; + const interaction_to_next_paint=json.originLoadingExperience.metrics["INTERACTION_TO_NEXT_PAINT"].percentile/1000; + const cumulative_shift_layout = json.lighthouseResult.audits["cumulative-layout-shift"].score/1000 ; + const first_contentful_paint = json.originLoadingExperience.metrics["LARGEST_CONTENTFUL_PAINT_MS"].percentile/1000 ; + const time_to_first_bite=json.originLoadingExperience.metrics["EXPERIMENTAL_TIME_TO_FIRST_BYTE"].percentile/1000; + const speed_index = json.lighthouseResult.audits["speed-index"].displayValue ; + const total_blocking_time = json.lighthouseResult.audits["total-blocking-time"].numericValue/1000 ; const cleanedResponse = { url: json.id, fetchTime: json.lighthouseResult.fetchTime, - performance: json.lighthouseResult.categories.performance + performanceScore, + largest_contentful_paint, + interaction_to_next_paint, + cumulative_shift_layout, + first_contentful_paint, + time_to_first_bite, + speed_index + //total_blocking_time }; - - return cleanedResponse; - + return cleanedResponse; } catch (error) { console.error("Error fetching PageSpeed data:", error); throw new Error("Failed to fetch website statistics"); } }; +import fetch from "node-fetch"; + +const API_KEY = process.env.SEARCH_API_KEY; +const CX = process.env.CX; +const query = "site:.gov.pk"; +const MAX_PAGES = 40; +const RESULTS_PER_PAGE = 10; +import { pool } from "../config/db"; +import pg from "pg"; +import { store_websites } from "../database/website.query"; + +const client = new pg.Client({ + connectionString: config.DATABASE_URL, +}); +export const searchAndStoreGovPkWebsites = async () => { + const client = await pool.connect(); + let allWebsites = new Set(); // Using Set to avoid duplicates + + for (let page = 0; page < MAX_PAGES; page++) { + const startIndex = page * RESULTS_PER_PAGE + 1; // 1, 11, 21, ..., 91 + const url = `https://www.googleapis.com/customsearch/v1?q=${query}&key=${API_KEY}&cx=${CX}&start=${startIndex}`; + + try { + const response = await fetch(url); + const data = await response.json(); + + if (!data.items) { + console.log(`No results found on page ${page + 1}.`); + break; // Stop if there are no more results + } + + const websites = data.items.map((item: any) => { + let hostname = new URL(item.link).hostname; + return `https://${hostname}`; // Ensure "https://" is added + }); + + websites.forEach((site) => allWebsites.add(site)); + } catch (error) { + console.error(`Error fetching page ${page + 1}:`, error); + break; // Stop on error + } + } + + if (allWebsites.size === 0) { + console.log("No new websites found."); + return []; + } + + const values = [...allWebsites].map((url) => `('${url}')`).join(", "); + + try { + const result = await pool.query(store_websites(values)); + console.log(`Inserted ${result.rowCount} new websites.`); + return result.rows.map((row) => row.id); + } catch (error) { + console.error("Error inserting websites:", error); + throw error; + } finally { + client.release(); + } +}; From 01c5893f31910f6fb8fbb6bbc3aed378e7e805c8 Mon Sep 17 00:00:00 2001 From: azka Date: Mon, 3 Feb 2025 19:38:33 +0500 Subject: [PATCH 5/5] retries logic --- src/controller/website.controller.ts | 41 ++++++++++++------ src/services/pagespeed.service.ts | 62 ++++++++++++++-------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/controller/website.controller.ts b/src/controller/website.controller.ts index d3d3e3f..872f3ba 100644 --- a/src/controller/website.controller.ts +++ b/src/controller/website.controller.ts @@ -10,16 +10,20 @@ const client = new pg.Client({ connectionString: config.DATABASE_URL, }); export const fetchAndStoreWebsiteStats = async () => { - try { - const client = await pool.connect(); - const pksites= await searchAndStoreGovPkWebsites(); - const query = get_websites(); - const websites = await client.query(query); + try { + const client = await pool.connect(); + const pksites = await searchAndStoreGovPkWebsites(); + const query = get_websites(); + const websites = await client.query(query); + + const batchSize = 5; // Limit concurrent requests + const websiteBatches = chunkArray(websites.rows, batchSize); + + for (const batch of websiteBatches) { await Promise.allSettled( - websites.rows.map(async (website) => { + batch.map(async (website) => { try { const stats = await fetchPageSpeedData(website.url); - //const safeStats = CircularJSON.stringify(stats); await client.query(store_website_stats(website.id, stats)); console.log(`Successfully stored stats for: ${website.url}`); } catch (innerError) { @@ -27,12 +31,23 @@ export const fetchAndStoreWebsiteStats = async () => { } }) ); - - return true; - } catch (error) { - console.error("Error fetching and storing stats:", error); + console.log("Batch processed. Waiting before next batch..."); + await new Promise((resolve) => setTimeout(resolve, 5000)); // Add a delay between batches } - }; + + return true; + } catch (error) { + console.error("Error fetching and storing stats:", error); + } +}; + +// Helper function to split websites into batches +function chunkArray(array, size) { + return Array.from({ length: Math.ceil(array.length / size) }, (_, i) => + array.slice(i * size, i * size + size) + ); +} + export const get_states = async (param: Param) => { try { const client = await pool.connect(); @@ -43,7 +58,7 @@ export const fetchAndStoreWebsiteStats = async () => { const parsedStats = stats.rows.map(row => { return { ...row, - stats: row.stats ? JSON.parse(row.stats) : null + stats: row.stats }; }); diff --git a/src/services/pagespeed.service.ts b/src/services/pagespeed.service.ts index 120ea6f..c696aaf 100644 --- a/src/services/pagespeed.service.ts +++ b/src/services/pagespeed.service.ts @@ -1,45 +1,51 @@ import axios from "axios"; import { config } from "../config/env"; -export const fetchPageSpeedData = async (url: string) => { +import { pool } from "../config/db"; +import pg from "pg"; +import { store_websites } from "../database/website.query"; +export const fetchPageSpeedData = async (url: string, retries = 3, delay = 2000): Promise => { try { const response = await axios.get( - `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}&key=${config.PAGESPEED_API_KEY}` + `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}&key=${config.PAGESPEED_API_KEY}`, + { timeout: 15000 } // Increase timeout to 15 seconds ); const json = response.data; - // console.log("API Response:", JSON.stringify(json, null, 2)); // Log the entire response - - // Check if the required fields exist if (!json.lighthouseResult || !json.lighthouseResult.categories) { throw new Error("Invalid API response structure"); } - //console.log(json.lighthouseResult.categories) - const performanceScore = json.lighthouseResult.categories.performance?.score ; - const largest_contentful_paint = json.originLoadingExperience.metrics["LARGEST_CONTENTFUL_PAINT_MS"].percentile/1000 ; - const interaction_to_next_paint=json.originLoadingExperience.metrics["INTERACTION_TO_NEXT_PAINT"].percentile/1000; - const cumulative_shift_layout = json.lighthouseResult.audits["cumulative-layout-shift"].score/1000 ; - const first_contentful_paint = json.originLoadingExperience.metrics["LARGEST_CONTENTFUL_PAINT_MS"].percentile/1000 ; - const time_to_first_bite=json.originLoadingExperience.metrics["EXPERIMENTAL_TIME_TO_FIRST_BYTE"].percentile/1000; - const speed_index = json.lighthouseResult.audits["speed-index"].displayValue ; - const total_blocking_time = json.lighthouseResult.audits["total-blocking-time"].numericValue/1000 ; - const cleanedResponse = { + + return { url: json.id, fetchTime: json.lighthouseResult.fetchTime, - performanceScore, - largest_contentful_paint, - interaction_to_next_paint, - cumulative_shift_layout, - first_contentful_paint, - time_to_first_bite, - speed_index - //total_blocking_time + performanceScore: json.lighthouseResult.categories.performance?.score || 0, + largest_contentful_paint: + json.originLoadingExperience?.metrics?.["LARGEST_CONTENTFUL_PAINT_MS"]?.percentile / 1000 || 0, + interaction_to_next_paint: + json.originLoadingExperience?.metrics?.["INTERACTION_TO_NEXT_PAINT"]?.percentile / 1000 || 0, + cumulative_shift_layout: + json.lighthouseResult?.audits?.["cumulative-layout-shift"]?.score || 0, + first_contentful_paint: + json.originLoadingExperience?.metrics?.["FIRST_CONTENTFUL_PAINT_MS"]?.percentile / 1000 || 0, + time_to_first_bite: + json.originLoadingExperience?.metrics?.["EXPERIMENTAL_TIME_TO_FIRST_BYTE"]?.percentile / 1000 || 0, + speed_index: json.lighthouseResult?.audits?.["speed-index"]?.numericValue / 1000 || 0, + total_blocking_time: + json.lighthouseResult?.audits?.["total-blocking-time"]?.numericValue / 1000 || 0, }; - return cleanedResponse; } catch (error) { - console.error("Error fetching PageSpeed data:", error); - throw new Error("Failed to fetch website statistics"); + console.error(`Error fetching PageSpeed data for ${url}:`, error.message); + + if (retries > 0) { + console.log(`Retrying ${url} in ${delay / 1000} seconds...`); + await new Promise((resolve) => setTimeout(resolve, delay)); + return fetchPageSpeedData(url, retries - 1, delay * 2); // Exponential backoff + } + + throw new Error(`Failed to fetch website statistics after multiple attempts: ${url}`); } }; + import fetch from "node-fetch"; const API_KEY = process.env.SEARCH_API_KEY; @@ -47,10 +53,6 @@ const CX = process.env.CX; const query = "site:.gov.pk"; const MAX_PAGES = 40; const RESULTS_PER_PAGE = 10; -import { pool } from "../config/db"; -import pg from "pg"; -import { store_websites } from "../database/website.query"; - const client = new pg.Client({ connectionString: config.DATABASE_URL, });