diff --git a/App/FeatureSet/Notification/API/PushRelay.ts b/App/FeatureSet/Notification/API/PushRelay.ts new file mode 100644 index 0000000000..7cb8d443c1 --- /dev/null +++ b/App/FeatureSet/Notification/API/PushRelay.ts @@ -0,0 +1,108 @@ +import Express, { + ExpressRequest, + ExpressResponse, + ExpressRouter, + NextFunction, +} from "Common/Server/Utils/Express"; +import Response from "Common/Server/Utils/Response"; +import BadDataException from "Common/Types/Exception/BadDataException"; +import { JSONObject } from "Common/Types/JSON"; +import PushNotificationService from "Common/Server/Services/PushNotificationService"; + +const router: ExpressRouter = Express.getRouter(); + +// Simple in-memory rate limiter by IP +const rateLimitMap: Map = + new Map(); +const RATE_LIMIT_WINDOW_MS: number = 60 * 1000; // 1 minute +const RATE_LIMIT_MAX_REQUESTS: number = 60; // 60 requests per minute per IP + +function isRateLimited(ip: string): boolean { + const now: number = Date.now(); + const entry: { count: number; resetTime: number } | undefined = + rateLimitMap.get(ip); + + if (!entry || now > entry.resetTime) { + rateLimitMap.set(ip, { count: 1, resetTime: now + RATE_LIMIT_WINDOW_MS }); + return false; + } + + entry.count++; + + return entry.count > RATE_LIMIT_MAX_REQUESTS; +} + +// Clean up stale rate limit entries every 5 minutes +setInterval( + () => { + const now: number = Date.now(); + for (const [ip, entry] of rateLimitMap.entries()) { + if (now > entry.resetTime) { + rateLimitMap.delete(ip); + } + } + }, + 5 * 60 * 1000, +); + +router.post( + "/send", + async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => { + try { + const clientIp: string = + (req.headers["x-forwarded-for"] as string)?.split(",")[0]?.trim() || + req.socket.remoteAddress || + "unknown"; + + if (isRateLimited(clientIp)) { + res.status(429).json({ + message: "Rate limit exceeded. Please try again later.", + }); + return; + } + + if (!PushNotificationService.hasExpoAccessToken()) { + throw new BadDataException( + "Push relay is not configured. EXPO_ACCESS_TOKEN is not set on this server.", + ); + } + + const body: JSONObject = req.body as JSONObject; + + const to: string | undefined = body["to"] as string | undefined; + + if (!to || !PushNotificationService.isValidExpoPushToken(to)) { + throw new BadDataException( + "Invalid or missing push token. Must be a valid Expo push token.", + ); + } + + const title: string | undefined = body["title"] as string | undefined; + const messageBody: string | undefined = body["body"] as + | string + | undefined; + + if (!title && !messageBody) { + throw new BadDataException( + "At least one of 'title' or 'body' must be provided.", + ); + } + + await PushNotificationService.sendRelayPushNotification({ + to: to, + title: title, + body: messageBody, + data: (body["data"] as { [key: string]: string }) || {}, + sound: (body["sound"] as string) || "default", + priority: (body["priority"] as string) || "high", + channelId: (body["channelId"] as string) || "default", + }); + + return Response.sendJsonObjectResponse(req, res, { success: true }); + } catch (err) { + return next(err); + } + }, +); + +export default router; diff --git a/App/FeatureSet/Notification/Index.ts b/App/FeatureSet/Notification/Index.ts index a13bc135fc..c78ebdaebb 100644 --- a/App/FeatureSet/Notification/Index.ts +++ b/App/FeatureSet/Notification/Index.ts @@ -4,6 +4,7 @@ import MailAPI from "./API/Mail"; import SmsAPI from "./API/SMS"; import WhatsAppAPI from "./API/WhatsApp"; import PushNotificationAPI from "./API/PushNotification"; +import PushRelayAPI from "./API/PushRelay"; import SMTPConfigAPI from "./API/SMTPConfig"; import PhoneNumberAPI from "./API/PhoneNumber"; import IncomingCallAPI from "./API/IncomingCall"; @@ -21,6 +22,7 @@ const NotificationFeatureSet: FeatureSet = { app.use([`/${APP_NAME}/sms`, "/sms"], SmsAPI); app.use([`/${APP_NAME}/whatsapp`, "/whatsapp"], WhatsAppAPI); app.use([`/${APP_NAME}/push`, "/push"], PushNotificationAPI); + app.use([`/${APP_NAME}/push-relay`, "/push-relay"], PushRelayAPI); app.use([`/${APP_NAME}/call`, "/call"], CallAPI); app.use([`/${APP_NAME}/smtp-config`, "/smtp-config"], SMTPConfigAPI); app.use([`/${APP_NAME}/phone-number`, "/phone-number"], PhoneNumberAPI); diff --git a/App/package-lock.json b/App/package-lock.json index f62bc411cc..81d088ee4a 100644 --- a/App/package-lock.json +++ b/App/package-lock.json @@ -12,6 +12,7 @@ "@sendgrid/mail": "^8.1.0", "Common": "file:../Common", "ejs": "^3.1.9", + "expo-server-sdk": "^5.0.0", "handlebars": "^4.7.8", "nodemailer": "^6.9.7", "ts-node": "^10.9.1", @@ -2166,6 +2167,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2299,6 +2306,20 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/expo-server-sdk": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-5.0.0.tgz", + "integrity": "sha512-GEp1XYLU80iS/hdRo3c2n092E8TgTXcHSuw6Lw68dSoWaAgiLPI2R+e5hp5+hGF1TtJZOi2nxtJX63+XA3iz9g==", + "license": "MIT", + "dependencies": { + "promise-limit": "^2.7.0", + "promise-retry": "^2.0.1", + "undici": "^7.2.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4167,6 +4188,25 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/promise-limit": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz", + "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==", + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -4290,6 +4330,15 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -4801,6 +4850,15 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/App/package.json b/App/package.json index fdbcd3e32d..a2e6cf4178 100644 --- a/App/package.json +++ b/App/package.json @@ -23,6 +23,7 @@ "@sendgrid/mail": "^8.1.0", "Common": "file:../Common", "ejs": "^3.1.9", + "expo-server-sdk": "^5.0.0", "handlebars": "^4.7.8", "nodemailer": "^6.9.7", "ts-node": "^10.9.1", diff --git a/CLI/package-lock.json b/CLI/package-lock.json index d83223abe1..8dfb70b4f4 100644 --- a/CLI/package-lock.json +++ b/CLI/package-lock.json @@ -83,7 +83,6 @@ "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", "license": "MIT", - "peer": true, "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", @@ -118,7 +117,6 @@ "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz", "integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==", "license": "MIT", - "peer": true, "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", @@ -290,7 +288,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -811,60 +808,47 @@ "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.23.0.tgz", "integrity": "sha512-iI/Ssl8T5ZEn9s899Qz67m92M6RU8thf/aqD7cUHB2yHmkCjqbw7s7NaODTsyArAsnyu7DGJMWm7EhbfFXDNgQ==", "license": "MIT", - "peer": true, "dependencies": { "@bull-board/api": "5.23.0" } }, "node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.1.tgz", + "integrity": "sha512-fRHyv6/f542qQqiRGalrfJl/evD39mAvbJLCekPazhiextEatq1Jx1K/i9gSd5NNO0ds03ek0Cbo/4uVKmOBcw==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/gast": "11.1.1", + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/cst-dts-gen/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==", - "license": "MIT" - }, "node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.1.tgz", + "integrity": "sha512-Ko/5vPEYy1vn5CbCjjvnSO4U7GgxyGm+dfUZZJIWTlQFkXkyym0jFYrWEU10hyCjrA7rQtiHtBr0EaZqvHFZvg==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/gast/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==", - "license": "MIT" - }, "node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.1.tgz", + "integrity": "sha512-ctRw1OKSXkOrR8VTvOxrQ5USEc4sNrfwXHa1NuTcR7wre4YbjPcKw+82C2uylg/TEwFRgwLmbhlln4qkmDyteg==", "license": "Apache-2.0" }, "node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.1.tgz", + "integrity": "sha512-wb2ToxG8LkgPYnKe9FH8oGn3TMCBdnwiuNC5l5y+CtlaVRbCytU0kbVsk6CGrqTL4ZN4ksJa0TXOYbxpbthtqw==", "license": "Apache-2.0" }, "node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.1.tgz", + "integrity": "sha512-71eTYMzYXYSFPrbg/ZwftSaSDld7UYlS8OQa3lNnn9jzNtpFbaReRRyghzqS7rI3CDaorqpPJJcXGHK+FE1TVQ==", "license": "Apache-2.0" }, "node_modules/@clickhouse/client": { @@ -2151,12 +2135,12 @@ "license": "MIT" }, "node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", + "integrity": "sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==", "license": "MIT", "dependencies": { - "langium": "3.3.1" + "langium": "^4.0.0" } }, "node_modules/@monaco-editor/loader": { @@ -2312,7 +2296,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -4765,7 +4748,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz", "integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -4808,7 +4790,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5019,7 +5000,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5816,7 +5796,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6164,17 +6143,17 @@ } }, "node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.1.tgz", + "integrity": "sha512-f0yv5CPKaFxfsPTBzX7vGuim4oIC1/gcS7LUGdBSwl2dU6+FON6LVUksdOo1qJjoUvXNn45urgh8C+0a24pACQ==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/cst-dts-gen": "11.1.1", + "@chevrotain/gast": "11.1.1", + "@chevrotain/regexp-to-ast": "11.1.1", + "@chevrotain/types": "11.1.1", + "@chevrotain/utils": "11.1.1", + "lodash-es": "4.17.23" } }, "node_modules/chevrotain-allstar": { @@ -6189,12 +6168,6 @@ "chevrotain": "^11.0.0" } }, - "node_modules/chevrotain/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==", - "license": "MIT" - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -6446,9 +6419,9 @@ }, "node_modules/Common": { "name": "@oneuptime/common", - "version": "9.5.10", - "resolved": "https://registry.npmjs.org/@oneuptime/common/-/common-9.5.10.tgz", - "integrity": "sha512-4UZ553L89Kd6pNVrUAZlB/eSiBI1e8QEm/5hWkHc+Pfv54yzkj1Smb7VssPlrLHU811I5iimI1/ZK+mD4B7aKA==", + "version": "9.5.13", + "resolved": "https://registry.npmjs.org/@oneuptime/common/-/common-9.5.13.tgz", + "integrity": "sha512-hHLUeApW4ILQcte5avvmj87m7w//tfcClDWWLsqkBWUSU94a4NSvpTEXh3dEN8WX3ty9/r7eYnobrjJK+7zIDA==", "license": "Apache-2.0", "dependencies": { "@asteasolutions/zod-to-openapi": "^7.3.2", @@ -6853,7 +6826,6 @@ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10" } @@ -7275,7 +7247,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -9227,7 +9198,6 @@ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.9.3.tgz", "integrity": "sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA==", "license": "MIT", - "peer": true, "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", @@ -9626,7 +9596,6 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -10522,19 +10491,20 @@ } }, "node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", "license": "MIT", "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" + "vscode-uri": "~3.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.10.0", + "npm": ">=10.2.3" } }, "node_modules/layout-base": { @@ -11181,14 +11151,14 @@ } }, "node_modules/mermaid": { - "version": "11.12.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", - "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "version": "11.12.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.3.tgz", + "integrity": "sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", - "@mermaid-js/parser": "^0.6.3", + "@mermaid-js/parser": "^1.0.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -11200,7 +11170,7 @@ "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", - "lodash-es": "^4.17.21", + "lodash-es": "^4.17.23", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", @@ -11956,6 +11926,7 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", "license": "MIT", + "peer": true, "dependencies": { "dompurify": "3.2.7", "marked": "14.0.0" @@ -11966,6 +11937,7 @@ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -11975,6 +11947,7 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", "license": "MIT", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -12583,7 +12556,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz", "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.11.0", "pg-pool": "^3.11.0", @@ -13205,7 +13177,6 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -13502,7 +13473,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -13587,7 +13557,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -15998,7 +15967,6 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -16311,7 +16279,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16754,9 +16721,9 @@ "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "license": "MIT" }, "node_modules/walker": { @@ -17157,7 +17124,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -17166,8 +17132,7 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/zustand": { "version": "4.5.7", diff --git a/Common/Server/API/UserCallAPI.ts b/Common/Server/API/UserCallAPI.ts index 04ababc076..a38cb15bf8 100644 --- a/Common/Server/API/UserCallAPI.ts +++ b/Common/Server/API/UserCallAPI.ts @@ -2,6 +2,7 @@ import UserMiddleware from "../Middleware/UserAuthorization"; import UserCallService, { Service as UserCallServiceType, } from "../Services/UserCallService"; +import UserNotificationRuleService from "../Services/UserNotificationRuleService"; import { ExpressRequest, ExpressResponse, @@ -9,8 +10,10 @@ import { OneUptimeRequest, } from "../Utils/Express"; import Response from "../Utils/Response"; +import logger from "../Utils/Logger"; import BaseAPI from "./BaseAPI"; import BadDataException from "../../Types/Exception/BadDataException"; +import ObjectID from "../../Types/ObjectID"; import UserCall from "../../Models/DatabaseModels/UserCall"; import UserSMS from "../../Models/DatabaseModels/UserSMS"; @@ -52,6 +55,7 @@ export default class UserCallAPI extends BaseAPI< }, select: { userId: true, + projectId: true, verificationCode: true, }, }); @@ -95,6 +99,21 @@ export default class UserCallAPI extends BaseAPI< }, }); + // Create default notification rules for this verified call number + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(item.projectId!.toString()), + userId: new ObjectID(item.userId!.toString()), + notificationMethod: { + userCallId: item.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendEmptySuccessResponse(req, res); } catch (err) { return next(err); diff --git a/Common/Server/API/UserEmailAPI.ts b/Common/Server/API/UserEmailAPI.ts index 74efcacde1..8a3e8e806e 100644 --- a/Common/Server/API/UserEmailAPI.ts +++ b/Common/Server/API/UserEmailAPI.ts @@ -2,6 +2,7 @@ import UserMiddleware from "../Middleware/UserAuthorization"; import UserEmailService, { Service as UserEmailServiceType, } from "../Services/UserEmailService"; +import UserNotificationRuleService from "../Services/UserNotificationRuleService"; import { ExpressRequest, ExpressResponse, @@ -9,8 +10,10 @@ import { OneUptimeRequest, } from "../Utils/Express"; import Response from "../Utils/Response"; +import logger from "../Utils/Logger"; import BaseAPI from "./BaseAPI"; import BadDataException from "../../Types/Exception/BadDataException"; +import ObjectID from "../../Types/ObjectID"; import UserEmail from "../../Models/DatabaseModels/UserEmail"; export default class UserEmailAPI extends BaseAPI< @@ -51,6 +54,7 @@ export default class UserEmailAPI extends BaseAPI< }, select: { userId: true, + projectId: true, verificationCode: true, }, }); @@ -94,6 +98,21 @@ export default class UserEmailAPI extends BaseAPI< }, }); + // Create default notification rules for this verified email + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(item.projectId!.toString()), + userId: new ObjectID(item.userId!.toString()), + notificationMethod: { + userEmailId: item.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendEmptySuccessResponse(req, res); } catch (err) { return next(err); diff --git a/Common/Server/API/UserPushAPI.ts b/Common/Server/API/UserPushAPI.ts index 4f85a4a403..5543f91686 100644 --- a/Common/Server/API/UserPushAPI.ts +++ b/Common/Server/API/UserPushAPI.ts @@ -2,8 +2,10 @@ import UserMiddleware from "../Middleware/UserAuthorization"; import UserPushService, { Service as UserPushServiceType, } from "../Services/UserPushService"; +import UserNotificationRuleService from "../Services/UserNotificationRuleService"; import PushNotificationService from "../Services/PushNotificationService"; import PushNotificationUtil from "../Utils/PushNotificationUtil"; +import logger from "../Utils/Logger"; import { ExpressRequest, ExpressResponse, @@ -13,11 +15,23 @@ import { import Response from "../Utils/Response"; import BaseAPI from "./BaseAPI"; import BadDataException from "../../Types/Exception/BadDataException"; +import NotAuthenticatedException from "../../Types/Exception/NotAuthenticatedException"; import ObjectID from "../../Types/ObjectID"; import PushDeviceType from "../../Types/PushNotification/PushDeviceType"; import UserPush from "../../Models/DatabaseModels/UserPush"; import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage"; +function getAuthenticatedUserId(req: ExpressRequest): ObjectID { + const userId: ObjectID | undefined = (req as OneUptimeRequest) + .userAuthorization?.userId; + if (!userId) { + throw new NotAuthenticatedException( + "You must be logged in to perform this action.", + ); + } + return userId; +} + export default class UserPushAPI extends BaseAPI< UserPush, UserPushServiceType @@ -32,6 +46,8 @@ export default class UserPushAPI extends BaseAPI< try { req = req as OneUptimeRequest; + const userId: ObjectID = getAuthenticatedUserId(req); + if (!req.body.deviceToken) { return Response.sendErrorResponse( req, @@ -65,7 +81,7 @@ export default class UserPushAPI extends BaseAPI< // Check if device is already registered const existingDevice: UserPush | null = await this.service.findOneBy({ query: { - userId: (req as OneUptimeRequest).userAuthorization!.userId!, + userId: userId, projectId: new ObjectID(req.body.projectId), deviceToken: req.body.deviceToken, }, @@ -78,17 +94,18 @@ export default class UserPushAPI extends BaseAPI< }); if (existingDevice) { - // Mark as used and return a specific response indicating device was already registered - throw new BadDataException( - "This device is already registered for push notifications", + return Response.sendErrorResponse( + req, + res, + new BadDataException( + "This device is already registered for push notifications", + ), ); } // Create new device registration const userPush: UserPush = new UserPush(); - userPush.userId = ( - req as OneUptimeRequest - ).userAuthorization!.userId!; + userPush.userId = userId; userPush.projectId = new ObjectID(req.body.projectId); userPush.deviceToken = req.body.deviceToken; userPush.deviceType = req.body.deviceType; @@ -102,6 +119,21 @@ export default class UserPushAPI extends BaseAPI< }, }); + // Create default notification rules for this registered push device + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(req.body.projectId), + userId, + notificationMethod: { + userPushId: savedDevice.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendJsonObjectResponse(req, res, { success: true, deviceId: savedDevice._id!.toString(), @@ -119,6 +151,8 @@ export default class UserPushAPI extends BaseAPI< try { req = req as OneUptimeRequest; + const userId: ObjectID = getAuthenticatedUserId(req); + if (!req.body.deviceToken) { return Response.sendErrorResponse( req, @@ -127,9 +161,6 @@ export default class UserPushAPI extends BaseAPI< ); } - const userId: ObjectID = (req as OneUptimeRequest).userAuthorization! - .userId!; - await this.service.deleteBy({ query: { userId: userId, @@ -159,6 +190,8 @@ export default class UserPushAPI extends BaseAPI< try { req = req as OneUptimeRequest; + const userId: ObjectID = getAuthenticatedUserId(req); + if (!req.params["deviceId"]) { return Response.sendErrorResponse( req, @@ -192,10 +225,7 @@ export default class UserPushAPI extends BaseAPI< } // Check if the device belongs to the current user - if ( - device.userId?.toString() !== - (req as OneUptimeRequest).userAuthorization!.userId!.toString() - ) { + if (device.userId?.toString() !== userId.toString()) { return Response.sendErrorResponse( req, res, @@ -264,6 +294,8 @@ export default class UserPushAPI extends BaseAPI< try { req = req as OneUptimeRequest; + const userId: ObjectID = getAuthenticatedUserId(req); + if (!req.params["deviceId"]) { return Response.sendErrorResponse( req, @@ -279,6 +311,7 @@ export default class UserPushAPI extends BaseAPI< }, select: { userId: true, + projectId: true, }, }); @@ -291,10 +324,7 @@ export default class UserPushAPI extends BaseAPI< } // Check if the device belongs to the current user - if ( - device.userId?.toString() !== - (req as OneUptimeRequest).userAuthorization!.userId!.toString() - ) { + if (device.userId?.toString() !== userId.toString()) { return Response.sendErrorResponse( req, res, @@ -304,6 +334,21 @@ export default class UserPushAPI extends BaseAPI< await this.service.verifyDevice(device._id!.toString()); + // Create default notification rules for this verified push device + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(device.projectId!.toString()), + userId, + notificationMethod: { + userPushId: device.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendEmptySuccessResponse(req, res); } catch (error) { return next(error); @@ -318,6 +363,8 @@ export default class UserPushAPI extends BaseAPI< try { req = req as OneUptimeRequest; + const userId: ObjectID = getAuthenticatedUserId(req); + if (!req.params["deviceId"]) { return Response.sendErrorResponse( req, @@ -345,10 +392,7 @@ export default class UserPushAPI extends BaseAPI< } // Check if the device belongs to the current user - if ( - device.userId?.toString() !== - (req as OneUptimeRequest).userAuthorization!.userId!.toString() - ) { + if (device.userId?.toString() !== userId.toString()) { return Response.sendErrorResponse( req, res, diff --git a/Common/Server/API/UserSmsAPI.ts b/Common/Server/API/UserSmsAPI.ts index 3c698402fd..ffe588a7c2 100644 --- a/Common/Server/API/UserSmsAPI.ts +++ b/Common/Server/API/UserSmsAPI.ts @@ -2,6 +2,7 @@ import UserMiddleware from "../Middleware/UserAuthorization"; import UserSMSService, { Service as UserSMSServiceType, } from "../Services/UserSmsService"; +import UserNotificationRuleService from "../Services/UserNotificationRuleService"; import { ExpressRequest, ExpressResponse, @@ -9,8 +10,10 @@ import { OneUptimeRequest, } from "../Utils/Express"; import Response from "../Utils/Response"; +import logger from "../Utils/Logger"; import BaseAPI from "./BaseAPI"; import BadDataException from "../../Types/Exception/BadDataException"; +import ObjectID from "../../Types/ObjectID"; import UserSMS from "../../Models/DatabaseModels/UserSMS"; export default class UserSMSAPI extends BaseAPI { @@ -48,6 +51,7 @@ export default class UserSMSAPI extends BaseAPI { }, select: { userId: true, + projectId: true, verificationCode: true, }, }); @@ -91,6 +95,21 @@ export default class UserSMSAPI extends BaseAPI { }, }); + // Create default notification rules for this verified SMS + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(item.projectId!.toString()), + userId: new ObjectID(item.userId!.toString()), + notificationMethod: { + userSmsId: item.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendEmptySuccessResponse(req, res); } catch (err) { return next(err); diff --git a/Common/Server/API/UserWhatsAppAPI.ts b/Common/Server/API/UserWhatsAppAPI.ts index 1724c5dea9..b7679d7253 100644 --- a/Common/Server/API/UserWhatsAppAPI.ts +++ b/Common/Server/API/UserWhatsAppAPI.ts @@ -2,6 +2,7 @@ import UserMiddleware from "../Middleware/UserAuthorization"; import UserWhatsAppService, { Service as UserWhatsAppServiceType, } from "../Services/UserWhatsAppService"; +import UserNotificationRuleService from "../Services/UserNotificationRuleService"; import { ExpressRequest, ExpressResponse, @@ -9,8 +10,10 @@ import { OneUptimeRequest, } from "../Utils/Express"; import Response from "../Utils/Response"; +import logger from "../Utils/Logger"; import BaseAPI from "./BaseAPI"; import BadDataException from "../../Types/Exception/BadDataException"; +import ObjectID from "../../Types/ObjectID"; import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp"; export default class UserWhatsAppAPI extends BaseAPI< @@ -50,6 +53,7 @@ export default class UserWhatsAppAPI extends BaseAPI< }, select: { userId: true, + projectId: true, verificationCode: true, isVerified: true, }, @@ -100,6 +104,21 @@ export default class UserWhatsAppAPI extends BaseAPI< }, }); + // Create default notification rules for this verified WhatsApp number + try { + await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod( + { + projectId: new ObjectID(item.projectId!.toString()), + userId: new ObjectID(item.userId!.toString()), + notificationMethod: { + userWhatsAppId: item.id!, + }, + }, + ); + } catch (e) { + logger.error(e); + } + return Response.sendEmptySuccessResponse(req, res); } catch (err) { return next(err); diff --git a/Common/Server/EnvironmentConfig.ts b/Common/Server/EnvironmentConfig.ts index 91dc48b530..6eccd75d1c 100644 --- a/Common/Server/EnvironmentConfig.ts +++ b/Common/Server/EnvironmentConfig.ts @@ -161,6 +161,14 @@ export const ClusterKey: ObjectID = new ObjectID( export const HasClusterKey: boolean = Boolean(process.env["ONEUPTIME_SECRET"]); +export const RegisterProbeKey: ObjectID = new ObjectID( + process.env["REGISTER_PROBE_KEY"] || "secret", +); + +export const HasRegisterProbeKey: boolean = Boolean( + process.env["REGISTER_PROBE_KEY"], +); + export const AppApiHostname: Hostname = Hostname.fromString( `${process.env["SERVER_APP_HOSTNAME"] || "localhost"}:${ process.env["APP_PORT"] || 80 @@ -529,6 +537,13 @@ export const VapidPrivateKey: string | undefined = export const VapidSubject: string = process.env["VAPID_SUBJECT"] || "mailto:support@oneuptime.com"; +export const ExpoAccessToken: string | undefined = + process.env["EXPO_ACCESS_TOKEN"] || undefined; + +export const PushNotificationRelayUrl: string = + process.env["PUSH_NOTIFICATION_RELAY_URL"] || + "https://oneuptime.com/api/notification/push-relay/send"; + export const EnterpriseLicenseValidationUrl: URL = URL.fromString( "https://oneuptime.com/api/enterprise-license/validate", ); diff --git a/Common/Server/Services/PushNotificationService.ts b/Common/Server/Services/PushNotificationService.ts index e1170e3ce0..0f278a0304 100644 --- a/Common/Server/Services/PushNotificationService.ts +++ b/Common/Server/Services/PushNotificationService.ts @@ -10,9 +10,16 @@ import { VapidPublicKey, VapidPrivateKey, VapidSubject, + ExpoAccessToken, + PushNotificationRelayUrl, } from "../EnvironmentConfig"; import webpush from "web-push"; import { Expo, ExpoPushMessage, ExpoPushTicket } from "expo-server-sdk"; +import API from "../../Utils/API"; +import URL from "../../Types/API/URL"; +import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse"; +import HTTPResponse from "../../Types/API/HTTPResponse"; +import { JSONObject } from "../../Types/JSON"; import PushNotificationUtil from "../Utils/PushNotificationUtil"; import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax"; import UserPush from "../../Models/DatabaseModels/UserPush"; @@ -43,7 +50,9 @@ export interface PushNotificationOptions { export default class PushNotificationService { public static isWebPushInitialized = false; - private static expoClient: Expo = new Expo(); + private static expoClient: Expo = new Expo( + ExpoAccessToken ? { accessToken: ExpoAccessToken } : undefined, + ); public static initializeWebPush(): void { if (this.isWebPushInitialized) { @@ -340,20 +349,33 @@ export default class PushNotificationService { ); } + const dataPayload: { [key: string]: string } = {}; + if (message.data) { + for (const key of Object.keys(message.data)) { + dataPayload[key] = String(message.data[key]); + } + } + if (message.url || message.clickAction) { + dataPayload["url"] = message.url || message.clickAction || ""; + } + + const channelId: string = + deviceType === PushDeviceType.Android ? "oncall_high" : "default"; + + // If EXPO_ACCESS_TOKEN is not set, relay through the push notification gateway + if (!ExpoAccessToken) { + await this.sendViaRelay( + expoPushToken, + message, + dataPayload, + channelId, + deviceType, + ); + return; + } + + // Send directly via Expo SDK try { - const dataPayload: { [key: string]: string } = {}; - if (message.data) { - for (const key of Object.keys(message.data)) { - dataPayload[key] = String(message.data[key]); - } - } - if (message.url || message.clickAction) { - dataPayload["url"] = message.url || message.clickAction || ""; - } - - const channelId: string = - deviceType === PushDeviceType.Android ? "oncall_high" : "default"; - const expoPushMessage: ExpoPushMessage = { to: expoPushToken, title: message.title, @@ -403,6 +425,108 @@ export default class PushNotificationService { } } + private static async sendViaRelay( + expoPushToken: string, + message: PushNotificationMessage, + dataPayload: { [key: string]: string }, + channelId: string, + deviceType: PushDeviceType, + ): Promise { + logger.info( + `Sending ${deviceType} push notification via relay: ${PushNotificationRelayUrl}`, + ); + + try { + const response: HTTPErrorResponse | HTTPResponse = + await API.post({ + url: URL.fromString(PushNotificationRelayUrl), + data: { + to: expoPushToken, + title: message.title || "", + body: message.body || "", + data: dataPayload, + sound: "default", + priority: "high", + channelId: channelId, + }, + }); + + if (response instanceof HTTPErrorResponse) { + throw new Error( + `Push relay error: ${JSON.stringify(response.jsonData)}`, + ); + } + + logger.info( + `Push notification sent via relay successfully to ${deviceType} device`, + ); + } catch (error: any) { + logger.error( + `Failed to send push notification via relay to ${deviceType} device: ${error.message}`, + ); + throw error; + } + } + + public static isValidExpoPushToken(token: string): boolean { + return Expo.isExpoPushToken(token); + } + + public static hasExpoAccessToken(): boolean { + return Boolean(ExpoAccessToken); + } + + public static async sendRelayPushNotification(data: { + to: string; + title?: string; + body?: string; + data?: { [key: string]: string }; + sound?: string; + priority?: string; + channelId?: string; + }): Promise { + if (!ExpoAccessToken) { + throw new Error( + "Push relay is not configured. EXPO_ACCESS_TOKEN is not set on this server.", + ); + } + + const expoPushMessage: ExpoPushMessage = { + to: data.to, + title: data.title || "", + body: data.body || "", + data: data.data || {}, + sound: (data.sound as "default" | null) || "default", + priority: (data.priority as "default" | "normal" | "high") || "high", + channelId: data.channelId || "default", + }; + + const tickets: ExpoPushTicket[] = + await this.expoClient.sendPushNotificationsAsync([expoPushMessage]); + + const ticket: ExpoPushTicket | undefined = tickets[0]; + + if (ticket && ticket.status === "error") { + const errorTicket: ExpoPushTicket & { + message?: string; + details?: { error?: string }; + } = ticket as ExpoPushTicket & { + message?: string; + details?: { error?: string }; + }; + + logger.error( + `Push relay: Expo push notification error: ${errorTicket.message}`, + ); + + throw new Error( + `Failed to send push notification: ${errorTicket.message}`, + ); + } + + logger.info(`Push relay: notification sent successfully to ${data.to}`); + } + public static async sendPushNotificationToUser( userId: ObjectID, projectId: ObjectID, diff --git a/Common/Server/Services/UserNotificationRuleService.ts b/Common/Server/Services/UserNotificationRuleService.ts index d9a0bc6e1e..55bee3e74c 100644 --- a/Common/Server/Services/UserNotificationRuleService.ts +++ b/Common/Server/Services/UserNotificationRuleService.ts @@ -69,6 +69,14 @@ import PushNotificationMessage from "../../Types/PushNotification/PushNotificati import logger from "../Utils/Logger"; import CaptureSpan from "../Utils/Telemetry/CaptureSpan"; +export interface NotificationMethodDescriptor { + userEmailId?: ObjectID; + userSmsId?: ObjectID; + userCallId?: ObjectID; + userWhatsAppId?: ObjectID; + userPushId?: ObjectID; +} + export class Service extends DatabaseService { public constructor() { super(Model); @@ -2207,13 +2215,89 @@ export class Service extends DatabaseService { } @CaptureSpan() - public async addDefaultIncidentNotificationRuleForUser(data: { + public async addDefaultNotificationRulesForVerifiedMethod(data: { projectId: ObjectID; userId: ObjectID; - userEmail: UserEmail; + notificationMethod: NotificationMethodDescriptor; }): Promise { - const { projectId, userId, userEmail } = data; + const { projectId, userId, notificationMethod } = data; + await this.createIncidentOnCallRules(projectId, userId, notificationMethod); + await this.createAlertOnCallRules(projectId, userId, notificationMethod); + await this.createSingleRule( + projectId, + userId, + notificationMethod, + NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE, + ); + await this.createSingleRule( + projectId, + userId, + notificationMethod, + NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE, + ); + await this.createSingleRule( + projectId, + userId, + notificationMethod, + NotificationRuleType.WHEN_USER_GOES_ON_CALL, + ); + await this.createSingleRule( + projectId, + userId, + notificationMethod, + NotificationRuleType.WHEN_USER_GOES_OFF_CALL, + ); + } + + private applyNotificationMethod( + rule: Model, + descriptor: NotificationMethodDescriptor, + ): void { + if (descriptor.userEmailId) { + rule.userEmailId = descriptor.userEmailId; + } + if (descriptor.userSmsId) { + rule.userSmsId = descriptor.userSmsId; + } + if (descriptor.userCallId) { + rule.userCallId = descriptor.userCallId; + } + if (descriptor.userWhatsAppId) { + rule.userWhatsAppId = descriptor.userWhatsAppId; + } + if (descriptor.userPushId) { + rule.userPushId = descriptor.userPushId; + } + } + + private getNotificationMethodQuery( + descriptor: NotificationMethodDescriptor, + ): Record { + const query: Record = {}; + if (descriptor.userEmailId) { + query["userEmailId"] = descriptor.userEmailId; + } + if (descriptor.userSmsId) { + query["userSmsId"] = descriptor.userSmsId; + } + if (descriptor.userCallId) { + query["userCallId"] = descriptor.userCallId; + } + if (descriptor.userWhatsAppId) { + query["userWhatsAppId"] = descriptor.userWhatsAppId; + } + if (descriptor.userPushId) { + query["userPushId"] = descriptor.userPushId; + } + return query; + } + + private async createIncidentOnCallRules( + projectId: ObjectID, + userId: ObjectID, + notificationMethod: NotificationMethodDescriptor, + ): Promise { const incidentSeverities: Array = await IncidentSeverityService.findBy({ query: { @@ -2229,38 +2313,34 @@ export class Service extends DatabaseService { }, }); - // create for incident severities. for (const incidentSeverity of incidentSeverities) { - //check if this rule already exists. const existingRule: Model | null = await this.findOneBy({ query: { projectId, userId, - userEmailId: userEmail.id!, + ...this.getNotificationMethodQuery(notificationMethod), incidentSeverityId: incidentSeverity.id!, ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT, - }, + } as any, props: { isRoot: true, }, }); if (existingRule) { - continue; // skip this rule. + continue; } - const notificationRule: Model = new Model(); - - notificationRule.projectId = projectId; - notificationRule.userId = userId; - notificationRule.userEmailId = userEmail.id!; - notificationRule.incidentSeverityId = incidentSeverity.id!; - notificationRule.notifyAfterMinutes = 0; - notificationRule.ruleType = - NotificationRuleType.ON_CALL_EXECUTED_INCIDENT; + const rule: Model = new Model(); + rule.projectId = projectId; + rule.userId = userId; + this.applyNotificationMethod(rule, notificationMethod); + rule.incidentSeverityId = incidentSeverity.id!; + rule.notifyAfterMinutes = 0; + rule.ruleType = NotificationRuleType.ON_CALL_EXECUTED_INCIDENT; await this.create({ - data: notificationRule, + data: rule, props: { isRoot: true, }, @@ -2268,14 +2348,11 @@ export class Service extends DatabaseService { } } - @CaptureSpan() - public async addDefaultAlertNotificationRulesForUser(data: { - projectId: ObjectID; - userId: ObjectID; - userEmail: UserEmail; - }): Promise { - const { projectId, userId, userEmail } = data; - + private async createAlertOnCallRules( + projectId: ObjectID, + userId: ObjectID, + notificationMethod: NotificationMethodDescriptor, + ): Promise { const alertSeverities: Array = await AlertSeverityService.findBy({ query: { @@ -2291,37 +2368,34 @@ export class Service extends DatabaseService { }, }); - // create for Alert severities. for (const alertSeverity of alertSeverities) { - //check if this rule already exists. const existingRule: Model | null = await this.findOneBy({ query: { projectId, userId, - userEmailId: userEmail.id!, + ...this.getNotificationMethodQuery(notificationMethod), alertSeverityId: alertSeverity.id!, ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT, - }, + } as any, props: { isRoot: true, }, }); if (existingRule) { - continue; // skip this rule. + continue; } - const notificationRule: Model = new Model(); - - notificationRule.projectId = projectId; - notificationRule.userId = userId; - notificationRule.userEmailId = userEmail.id!; - notificationRule.alertSeverityId = alertSeverity.id!; - notificationRule.notifyAfterMinutes = 0; - notificationRule.ruleType = NotificationRuleType.ON_CALL_EXECUTED_ALERT; + const rule: Model = new Model(); + rule.projectId = projectId; + rule.userId = userId; + this.applyNotificationMethod(rule, notificationMethod); + rule.alertSeverityId = alertSeverity.id!; + rule.notifyAfterMinutes = 0; + rule.ruleType = NotificationRuleType.ON_CALL_EXECUTED_ALERT; await this.create({ - data: notificationRule, + data: rule, props: { isRoot: true, }, @@ -2329,6 +2403,43 @@ export class Service extends DatabaseService { } } + private async createSingleRule( + projectId: ObjectID, + userId: ObjectID, + notificationMethod: NotificationMethodDescriptor, + ruleType: NotificationRuleType, + ): Promise { + const existingRule: Model | null = await this.findOneBy({ + query: { + projectId, + userId, + ...this.getNotificationMethodQuery(notificationMethod), + ruleType, + } as any, + props: { + isRoot: true, + }, + }); + + if (existingRule) { + return; + } + + const rule: Model = new Model(); + rule.projectId = projectId; + rule.userId = userId; + this.applyNotificationMethod(rule, notificationMethod); + rule.notifyAfterMinutes = 0; + rule.ruleType = ruleType; + + await this.create({ + data: rule, + props: { + isRoot: true, + }, + }); + } + @CaptureSpan() public async addDefaultNotificationRuleForUser( projectId: ObjectID, @@ -2361,82 +2472,13 @@ export class Service extends DatabaseService { }); } - // add default incident rules for user - await this.addDefaultIncidentNotificationRuleForUser({ + await this.addDefaultNotificationRulesForVerifiedMethod({ projectId, userId, - userEmail, - }); - - // add default alert rules for user, just like the incident - - await this.addDefaultAlertNotificationRulesForUser({ - projectId, - userId, - userEmail, - }); - - //check if this rule already exists. - const existingRuleOnCall: Model | null = await this.findOneBy({ - query: { - projectId, - userId, + notificationMethod: { userEmailId: userEmail.id!, - ruleType: NotificationRuleType.WHEN_USER_GOES_ON_CALL, - }, - props: { - isRoot: true, }, }); - - if (!existingRuleOnCall) { - // on and off call. - const onCallRule: Model = new Model(); - - onCallRule.projectId = projectId; - onCallRule.userId = userId; - onCallRule.userEmailId = userEmail.id!; - onCallRule.notifyAfterMinutes = 0; - onCallRule.ruleType = NotificationRuleType.WHEN_USER_GOES_ON_CALL; - - await this.create({ - data: onCallRule, - props: { - isRoot: true, - }, - }); - } - - //check if this rule already exists. - const existingRuleOffCall: Model | null = await this.findOneBy({ - query: { - projectId, - userId, - userEmailId: userEmail.id!, - ruleType: NotificationRuleType.WHEN_USER_GOES_OFF_CALL, - }, - props: { - isRoot: true, - }, - }); - - if (!existingRuleOffCall) { - // on and off call. - const offCallRule: Model = new Model(); - - offCallRule.projectId = projectId; - offCallRule.userId = userId; - offCallRule.userEmailId = userEmail.id!; - offCallRule.notifyAfterMinutes = 0; - offCallRule.ruleType = NotificationRuleType.WHEN_USER_GOES_OFF_CALL; - - await this.create({ - data: offCallRule, - props: { - isRoot: true, - }, - }); - } } } export default new Service(); diff --git a/Common/Server/Utils/VM/VMRunner.ts b/Common/Server/Utils/VM/VMRunner.ts index 7054620e1e..8140abfcff 100644 --- a/Common/Server/Utils/VM/VMRunner.ts +++ b/Common/Server/Utils/VM/VMRunner.ts @@ -1,12 +1,8 @@ -import Dictionary from "../../../Types/Dictionary"; -import GenericObject from "../../../Types/GenericObject"; import ReturnResult from "../../../Types/IsolatedVM/ReturnResult"; -import { JSONObject, JSONValue } from "../../../Types/JSON"; -import axios from "axios"; -import http from "http"; -import https from "https"; +import { JSONObject } from "../../../Types/JSON"; +import axios, { AxiosResponse } from "axios"; import crypto from "crypto"; -import vm, { Context } from "node:vm"; +import ivm from "isolated-vm"; import CaptureSpan from "../Telemetry/CaptureSpan"; export default class VMRunner { @@ -16,49 +12,230 @@ export default class VMRunner { options: { timeout?: number; args?: JSONObject | undefined; - context?: Dictionary | undefined; }; }): Promise { const { code, options } = data; + const timeout: number = options.timeout || 5000; const logMessages: string[] = []; - let sandbox: Context = { - console: { - log: (...args: JSONValue[]) => { + const isolate: ivm.Isolate = new ivm.Isolate({ memoryLimit: 128 }); + + try { + const context: ivm.Context = await isolate.createContext(); + const jail: ivm.Reference> = context.global; + + // Set up global object + await jail.set("global", jail.derefInto()); + + // console.log - fire-and-forget callback + await jail.set( + "_log", + new ivm.Callback((...args: string[]) => { logMessages.push(args.join(" ")); + }), + ); + + await context.eval(` + const console = { log: (...a) => _log(...a.map(v => { + try { return typeof v === 'object' ? JSON.stringify(v) : String(v); } + catch(_) { return String(v); } + }))}; + `); + + // args - deep copy into isolate + if (options.args) { + await jail.set("_args", new ivm.ExternalCopy(options.args).copyInto()); + await context.eval("const args = _args;"); + } else { + await context.eval("const args = {};"); + } + + // axios (get, post, put, delete) - bridged via applySyncPromise + const axiosRef: ivm.Reference< + (method: string, url: string, dataOrConfig?: string) => Promise + > = new ivm.Reference( + async ( + method: string, + url: string, + dataOrConfig?: string, + ): Promise => { + const parsed: JSONObject | undefined = dataOrConfig + ? (JSON.parse(dataOrConfig) as JSONObject) + : undefined; + + let response: AxiosResponse; + + switch (method) { + case "get": + response = await axios.get(url, parsed); + break; + case "post": + response = await axios.post(url, parsed); + break; + case "put": + response = await axios.put(url, parsed); + break; + case "delete": + response = await axios.delete(url, parsed); + break; + default: + throw new Error(`Unsupported HTTP method: ${method}`); + } + + return JSON.stringify({ + status: response.status, + headers: response.headers, + data: response.data, + }); }, - }, - http: http, - https: https, - axios: axios, - crypto: crypto, - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - ...options.context, - }; + ); - if (options.args) { - sandbox = { - ...sandbox, - args: options.args, - }; - } + await jail.set("_axiosRef", axiosRef); - vm.createContext(sandbox); // Contextify the object. + await context.eval(` + const axios = { + get: async (url, config) => { + const r = await _axiosRef.applySyncPromise(undefined, ['get', url, config ? JSON.stringify(config) : undefined]); + return JSON.parse(r); + }, + post: async (url, data) => { + const r = await _axiosRef.applySyncPromise(undefined, ['post', url, data ? JSON.stringify(data) : undefined]); + return JSON.parse(r); + }, + put: async (url, data) => { + const r = await _axiosRef.applySyncPromise(undefined, ['put', url, data ? JSON.stringify(data) : undefined]); + return JSON.parse(r); + }, + delete: async (url, config) => { + const r = await _axiosRef.applySyncPromise(undefined, ['delete', url, config ? JSON.stringify(config) : undefined]); + return JSON.parse(r); + }, + }; + `); - const script: string = `(async()=>{ - ${code} + // crypto (createHash, createHmac, randomBytes) - bridged via applySync + const cryptoRef: ivm.Reference< + (op: string, ...args: string[]) => string + > = new ivm.Reference((op: string, ...args: string[]): string => { + switch (op) { + case "createHash": { + const [algorithm, inputData, encoding] = args; + return crypto + .createHash(algorithm!) + .update(inputData!) + .digest((encoding as crypto.BinaryToTextEncoding) || "hex"); + } + case "createHmac": { + const [algorithm, key, inputData, encoding] = args; + return crypto + .createHmac(algorithm!, key!) + .update(inputData!) + .digest((encoding as crypto.BinaryToTextEncoding) || "hex"); + } + case "randomBytes": { + const [size] = args; + return crypto.randomBytes(parseInt(size!)).toString("hex"); + } + default: + throw new Error(`Unsupported crypto operation: ${op}`); + } + }); + + await jail.set("_cryptoRef", cryptoRef); + + await context.eval(` + const crypto = { + createHash: (algorithm) => ({ + _alg: algorithm, _data: '', + update(d) { this._data = d; return this; }, + digest(enc) { return _cryptoRef.applySync(undefined, ['createHash', this._alg, this._data, enc || 'hex']); } + }), + createHmac: (algorithm, key) => ({ + _alg: algorithm, _key: key, _data: '', + update(d) { this._data = d; return this; }, + digest(enc) { return _cryptoRef.applySync(undefined, ['createHmac', this._alg, this._key, this._data, enc || 'hex']); } + }), + randomBytes: (size) => ({ + toString(enc) { return _cryptoRef.applySync(undefined, ['randomBytes', String(size)]); } + }), + }; + `); + + // setTimeout / sleep - bridged via applySyncPromise + const sleepRef: ivm.Reference<(ms: number) => Promise> = + new ivm.Reference((ms: number): Promise => { + return new Promise((resolve: () => void) => { + global.setTimeout(resolve, Math.min(ms, timeout)); + }); + }); + + await jail.set("_sleepRef", sleepRef); + + await context.eval(` + function setTimeout(fn, ms) { + _sleepRef.applySyncPromise(undefined, [ms || 0]); + if (typeof fn === 'function') fn(); + } + async function sleep(ms) { + await _sleepRef.applySyncPromise(undefined, [ms || 0]); + } + `); + + /* + * Wrap user code in async IIFE. JSON.stringify the return value inside + * the isolate so only a plain string crosses the boundary — this avoids + * "A non-transferable value was passed" errors when user code returns + * objects containing functions, class instances, or other non-cloneable types. + */ + const wrappedCode: string = `(async () => { + const __result = await (async () => { + ${code} + })(); + try { return JSON.stringify(__result); } + catch(_) { return undefined; } })()`; - const returnVal: any = await vm.runInContext(script, sandbox, { - timeout: options.timeout || 5000, - }); // run the script + // Run with overall timeout covering both CPU and I/O wait + const resultPromise: Promise = context.eval(wrappedCode, { + promise: true, + timeout: timeout, + }); - return { - returnValue: returnVal, - logMessages, - }; + const overallTimeout: Promise = new Promise( + (_resolve: (value: never) => void, reject: (reason: Error) => void) => { + global.setTimeout(() => { + reject(new Error("Script execution timed out")); + }, timeout + 5000); // 5s grace period beyond isolate timeout + }, + ); + + const result: unknown = await Promise.race([ + resultPromise, + overallTimeout, + ]); + + // Parse the JSON string returned from inside the isolate + let returnValue: unknown; + + if (typeof result === "string") { + try { + returnValue = JSON.parse(result); + } catch { + returnValue = result; + } + } else { + returnValue = result; + } + + return { + returnValue, + logMessages, + }; + } finally { + if (!isolate.isDisposed) { + isolate.dispose(); + } + } } } diff --git a/Common/package-lock.json b/Common/package-lock.json index c05b216352..15afcc8baa 100644 --- a/Common/package-lock.json +++ b/Common/package-lock.json @@ -62,6 +62,7 @@ "formik": "^2.4.6", "history": "^5.3.0", "ioredis": "^5.3.2", + "isolated-vm": "^6.0.2", "json2csv": "^5.0.7", "json5": "^2.2.3", "jsonwebtoken": "^9.0.0", @@ -423,7 +424,6 @@ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.0", @@ -926,60 +926,47 @@ "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.23.0.tgz", "integrity": "sha512-iI/Ssl8T5ZEn9s899Qz67m92M6RU8thf/aqD7cUHB2yHmkCjqbw7s7NaODTsyArAsnyu7DGJMWm7EhbfFXDNgQ==", "license": "MIT", - "peer": true, "dependencies": { "@bull-board/api": "5.23.0" } }, "node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.1.tgz", + "integrity": "sha512-fRHyv6/f542qQqiRGalrfJl/evD39mAvbJLCekPazhiextEatq1Jx1K/i9gSd5NNO0ds03ek0Cbo/4uVKmOBcw==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/gast": "11.1.1", + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/cst-dts-gen/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==", - "license": "MIT" - }, "node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.1.tgz", + "integrity": "sha512-Ko/5vPEYy1vn5CbCjjvnSO4U7GgxyGm+dfUZZJIWTlQFkXkyym0jFYrWEU10hyCjrA7rQtiHtBr0EaZqvHFZvg==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/gast/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==", - "license": "MIT" - }, "node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.1.tgz", + "integrity": "sha512-ctRw1OKSXkOrR8VTvOxrQ5USEc4sNrfwXHa1NuTcR7wre4YbjPcKw+82C2uylg/TEwFRgwLmbhlln4qkmDyteg==", "license": "Apache-2.0" }, "node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.1.tgz", + "integrity": "sha512-wb2ToxG8LkgPYnKe9FH8oGn3TMCBdnwiuNC5l5y+CtlaVRbCytU0kbVsk6CGrqTL4ZN4ksJa0TXOYbxpbthtqw==", "license": "Apache-2.0" }, "node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.1.tgz", + "integrity": "sha512-71eTYMzYXYSFPrbg/ZwftSaSDld7UYlS8OQa3lNnn9jzNtpFbaReRRyghzqS7rI3CDaorqpPJJcXGHK+FE1TVQ==", "license": "Apache-2.0" }, "node_modules/@clickhouse/client": { @@ -2202,12 +2189,12 @@ "license": "MIT" }, "node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", + "integrity": "sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==", "license": "MIT", "dependencies": { - "langium": "3.3.1" + "langium": "^4.0.0" } }, "node_modules/@monaco-editor/loader": { @@ -2366,7 +2353,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -5516,7 +5502,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5692,7 +5677,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-1.0.6.tgz", "integrity": "sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/unist": { "version": "2.0.11", @@ -5862,7 +5848,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6430,6 +6415,55 @@ "node": ">=6.0.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/bn.js": { "version": "4.12.2", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", @@ -6755,7 +6789,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001669", "electron-to-chromium": "^1.5.41", @@ -7078,17 +7111,17 @@ } }, "node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.1.tgz", + "integrity": "sha512-f0yv5CPKaFxfsPTBzX7vGuim4oIC1/gcS7LUGdBSwl2dU6+FON6LVUksdOo1qJjoUvXNn45urgh8C+0a24pACQ==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/cst-dts-gen": "11.1.1", + "@chevrotain/gast": "11.1.1", + "@chevrotain/regexp-to-ast": "11.1.1", + "@chevrotain/types": "11.1.1", + "@chevrotain/utils": "11.1.1", + "lodash-es": "4.17.23" } }, "node_modules/chevrotain-allstar": { @@ -7103,12 +7136,6 @@ "chevrotain": "^11.0.0" } }, - "node_modules/chevrotain/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==", - "license": "MIT" - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -7125,6 +7152,12 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -7593,7 +7626,6 @@ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10" } @@ -8015,7 +8047,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -8199,6 +8230,21 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -8239,6 +8285,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deepmerge": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", @@ -8398,7 +8453,6 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -8653,6 +8707,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/engine.io": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", @@ -9030,6 +9093,15 @@ "node": ">= 0.8.0" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/expect": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", @@ -9491,6 +9563,12 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "11.3.2", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", @@ -9634,6 +9712,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -10140,6 +10224,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/inline-style-parser": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", @@ -10675,6 +10765,19 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/isolated-vm": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/isolated-vm/-/isolated-vm-6.0.2.tgz", + "integrity": "sha512-Qw6AJuagG/VJuh2AIcSWmQPsAArti/L+lKhjXU+lyhYkbt3J57XZr+ZjgfTnOr4NJcY1r3f8f0eePS7MRGp+pg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": ">=22.0.0" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -10795,7 +10898,6 @@ "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^28.1.3", "@jest/types": "^28.1.3", @@ -12185,19 +12287,20 @@ } }, "node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", "license": "MIT", "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" + "vscode-uri": "~3.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.10.0", + "npm": ">=10.2.3" } }, "node_modules/layout-base": { @@ -13099,14 +13202,14 @@ } }, "node_modules/mermaid": { - "version": "11.12.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", - "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "version": "11.12.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.3.tgz", + "integrity": "sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", - "@mermaid-js/parser": "^0.6.3", + "@mermaid-js/parser": "^1.0.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -13118,7 +13221,7 @@ "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", - "lodash-es": "^4.17.21", + "lodash-es": "^4.17.23", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", @@ -13785,6 +13888,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -13843,6 +13958,12 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/mlly": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", @@ -13947,6 +14068,12 @@ "node": ">= 10.16.0" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13973,6 +14100,18 @@ "tslib": "^2.0.3" } }, + "node_modules/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", @@ -14200,7 +14339,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" @@ -14511,7 +14649,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", @@ -14788,6 +14925,32 @@ "url": "https://opencollective.com/preact" } }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -14894,7 +15057,6 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -14973,6 +15135,16 @@ "punycode": "^2.3.1" } }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -15193,12 +15365,35 @@ "node": ">= 0.8" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -15283,7 +15478,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -15804,8 +15998,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/refractor": { "version": "5.0.0", @@ -16585,6 +16778,51 @@ "dev": true, "license": "ISC" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -17552,6 +17790,48 @@ "url": "https://github.com/sponsors/dcastil" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar-stream": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", @@ -17851,6 +18131,18 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/twilio": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/twilio/-/twilio-4.23.0.tgz", @@ -18630,9 +18922,9 @@ "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "license": "MIT" }, "node_modules/w3c-xmlserializer": { @@ -18921,7 +19213,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": { @@ -19102,7 +19393,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -19111,8 +19401,7 @@ "version": "0.14.10", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz", "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/zustand": { "version": "4.5.5", diff --git a/Common/package.json b/Common/package.json index 1d723eda8e..459ced9c7d 100644 --- a/Common/package.json +++ b/Common/package.json @@ -101,6 +101,7 @@ "formik": "^2.4.6", "history": "^5.3.0", "ioredis": "^5.3.2", + "isolated-vm": "^6.0.2", "json2csv": "^5.0.7", "json5": "^2.2.3", "jsonwebtoken": "^9.0.0", diff --git a/Dashboard/package-lock.json b/Dashboard/package-lock.json index 35c13bd772..f793f45760 100644 --- a/Dashboard/package-lock.json +++ b/Dashboard/package-lock.json @@ -386,45 +386,45 @@ } }, "../Common/node_modules/@aws-sdk/client-sso": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.980.0.tgz", - "integrity": "sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.990.0.tgz", + "integrity": "sha512-xTEaPjZwOqVjGbLOP7qzwbdOWJOo1ne2mUhTZwEBBkPvNk4aXB/vcYwWwrjoSWUqtit4+GDbO75ePc/S6TUJYQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", + "@aws-sdk/util-endpoints": "3.990.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.8", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.23.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.14", + "@smithy/middleware-retry": "^4.4.31", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.30", + "@smithy/util-defaults-mode-node": "^4.2.33", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -436,9 +436,9 @@ } }, "../Common/node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -453,20 +453,20 @@ } }, "../Common/node_modules/@aws-sdk/core": { - "version": "3.973.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.5.tgz", - "integrity": "sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA==", + "version": "3.973.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.10.tgz", + "integrity": "sha512-4u/FbyyT3JqzfsESI70iFg6e2yp87MB5kS2qcxIA66m52VSTN1fvuvbCY1h/LKq1LvuxIrlJ1ItcyjvcKoaPLg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", - "@aws-sdk/xml-builder": "^3.972.2", - "@smithy/core": "^3.22.0", + "@aws-sdk/xml-builder": "^3.972.4", + "@smithy/core": "^3.23.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", @@ -478,13 +478,13 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.3.tgz", - "integrity": "sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.8.tgz", + "integrity": "sha512-r91OOPAcHnLCSxaeu/lzZAVRCZ/CtTNuwmJkUwpwSDshUrP7bkX1OmFn2nUMWd9kN53Q4cEo8b7226G4olt2Mg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", @@ -495,21 +495,21 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.5.tgz", - "integrity": "sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg==", + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.10.tgz", + "integrity": "sha512-DTtuyXSWB+KetzLcWaSahLJCtTUe/3SXtlGp4ik9PCe9xD6swHEkG8n8/BNsQ9dsihb9nhFvuUB4DpdBGDcvVg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.10", + "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" }, "engines": { @@ -517,20 +517,20 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.3.tgz", - "integrity": "sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.8.tgz", + "integrity": "sha512-n2dMn21gvbBIEh00E8Nb+j01U/9rSqFIamWRdGm/mE5e+vHQ9g0cBNdrYFlM6AAiryKVHZmShWT9D1JAWJ3ISw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-login": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/credential-provider-env": "^3.972.8", + "@aws-sdk/credential-provider-http": "^3.972.10", + "@aws-sdk/credential-provider-login": "^3.972.8", + "@aws-sdk/credential-provider-process": "^3.972.8", + "@aws-sdk/credential-provider-sso": "^3.972.8", + "@aws-sdk/credential-provider-web-identity": "^3.972.8", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -543,14 +543,14 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.3.tgz", - "integrity": "sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.8.tgz", + "integrity": "sha512-rMFuVids8ICge/X9DF5pRdGMIvkVhDV9IQFQ8aTYk6iF0rl9jOUa1C3kjepxiXUlpgJQT++sLZkT9n0TMLHhQw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", @@ -563,18 +563,18 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.4.tgz", - "integrity": "sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ==", + "version": "3.972.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.9.tgz", + "integrity": "sha512-LfJfO0ClRAq2WsSnA9JuUsNyIicD2eyputxSlSL0EiMrtxOxELLRG6ZVYDf/a1HCepaYPXeakH4y8D5OLCauag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-ini": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", + "@aws-sdk/credential-provider-env": "^3.972.8", + "@aws-sdk/credential-provider-http": "^3.972.10", + "@aws-sdk/credential-provider-ini": "^3.972.8", + "@aws-sdk/credential-provider-process": "^3.972.8", + "@aws-sdk/credential-provider-sso": "^3.972.8", + "@aws-sdk/credential-provider-web-identity": "^3.972.8", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -587,13 +587,13 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.3.tgz", - "integrity": "sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.8.tgz", + "integrity": "sha512-6cg26ffFltxM51OOS8NH7oE41EccaYiNlbd5VgUYwhiGCySLfHoGuGrLm2rMB4zhy+IO5nWIIG0HiodX8zdvHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -605,15 +605,15 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.3.tgz", - "integrity": "sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.8.tgz", + "integrity": "sha512-35kqmFOVU1n26SNv+U37sM8b2TzG8LyqAcd6iM9gprqxyHEh/8IM3gzN4Jzufs3qM6IrH8e43ryZWYdvfVzzKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.980.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/token-providers": "3.980.0", + "@aws-sdk/client-sso": "3.990.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/token-providers": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -625,14 +625,14 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.3.tgz", - "integrity": "sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.8.tgz", + "integrity": "sha512-CZhN1bOc1J3ubQPqbmr5b4KaMJBgdDvYsmEIZuX++wFlzmZsKj1bwkaiTEb5U2V7kXuzLlpF5HJSOM9eY/6nGA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -692,16 +692,16 @@ } }, "../Common/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.5.tgz", - "integrity": "sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg==", + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.10.tgz", + "integrity": "sha512-bBEL8CAqPQkI91ZM5a9xnFAzedpzH6NYCOtNyLarRAzTUTFN2DKqaC60ugBa7pnU1jSi4mA7WAXBsrod7nJltg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", - "@smithy/core": "^3.22.0", + "@aws-sdk/util-endpoints": "3.990.0", + "@smithy/core": "^3.23.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -711,9 +711,9 @@ } }, "../Common/node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -728,45 +728,45 @@ } }, "../Common/node_modules/@aws-sdk/nested-clients": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.980.0.tgz", - "integrity": "sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.990.0.tgz", + "integrity": "sha512-3NA0s66vsy8g7hPh36ZsUgO4SiMyrhwcYvuuNK1PezO52vX3hXDW4pQrC6OQLGKGJV0o6tbEyQtXb/mPs8zg8w==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", + "@aws-sdk/util-endpoints": "3.990.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.8", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.23.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.14", + "@smithy/middleware-retry": "^4.4.31", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.30", + "@smithy/util-defaults-mode-node": "^4.2.33", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -778,9 +778,9 @@ } }, "../Common/node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -812,14 +812,14 @@ } }, "../Common/node_modules/@aws-sdk/token-providers": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.980.0.tgz", - "integrity": "sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.990.0.tgz", + "integrity": "sha512-L3BtUb2v9XmYgQdfGBzbBtKMXaP5fV973y3Qdxeevs6oUTVXFmi/mV1+LnScA/1wVPJC9/hlK+1o5vbt7cG7EQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -888,13 +888,13 @@ } }, "../Common/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.3.tgz", - "integrity": "sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.8.tgz", + "integrity": "sha512-XJZuT0LWsFCW1C8dEpPAXSa7h6Pb3krr2y//1X0Zidpcl0vmgY5nL/X0JuBZlntpBzaN3+U4hvKjuijyiiR8zw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/types": "^3.973.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", @@ -913,9 +913,9 @@ } }, "../Common/node_modules/@aws-sdk/xml-builder": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.3.tgz", - "integrity": "sha512-bCk63RsBNCWW4tt5atv5Sbrh+3J3e8YzgyF6aZb1JeXcdzG4k5SlPLeTMFOIXFuuFHIwgphUhn4i3uS/q49eww==", + "version": "3.972.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.4.tgz", + "integrity": "sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1687,54 +1687,42 @@ } }, "../Common/node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.1.tgz", + "integrity": "sha512-fRHyv6/f542qQqiRGalrfJl/evD39mAvbJLCekPazhiextEatq1Jx1K/i9gSd5NNO0ds03ek0Cbo/4uVKmOBcw==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/gast": "11.1.1", + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "../Common/node_modules/@chevrotain/cst-dts-gen/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==", - "license": "MIT" - }, "../Common/node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.1.tgz", + "integrity": "sha512-Ko/5vPEYy1vn5CbCjjvnSO4U7GgxyGm+dfUZZJIWTlQFkXkyym0jFYrWEU10hyCjrA7rQtiHtBr0EaZqvHFZvg==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "../Common/node_modules/@chevrotain/gast/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==", - "license": "MIT" - }, "../Common/node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.1.tgz", + "integrity": "sha512-ctRw1OKSXkOrR8VTvOxrQ5USEc4sNrfwXHa1NuTcR7wre4YbjPcKw+82C2uylg/TEwFRgwLmbhlln4qkmDyteg==", "license": "Apache-2.0" }, "../Common/node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.1.tgz", + "integrity": "sha512-wb2ToxG8LkgPYnKe9FH8oGn3TMCBdnwiuNC5l5y+CtlaVRbCytU0kbVsk6CGrqTL4ZN4ksJa0TXOYbxpbthtqw==", "license": "Apache-2.0" }, "../Common/node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.1.tgz", + "integrity": "sha512-71eTYMzYXYSFPrbg/ZwftSaSDld7UYlS8OQa3lNnn9jzNtpFbaReRRyghzqS7rI3CDaorqpPJJcXGHK+FE1TVQ==", "license": "Apache-2.0" }, "../Common/node_modules/@clickhouse/client": { @@ -3039,12 +3027,12 @@ "license": "MIT" }, "../Common/node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", + "integrity": "sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==", "license": "MIT", "dependencies": { - "langium": "3.3.1" + "langium": "^4.0.0" } }, "../Common/node_modules/@monaco-editor/loader": { @@ -5084,9 +5072,9 @@ } }, "../Common/node_modules/@smithy/core": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.22.1.tgz", - "integrity": "sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==", + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.2.tgz", + "integrity": "sha512-HaaH4VbGie4t0+9nY3tNBRSxVTr96wzIqexUa6C2qx3MPePAuz7lIxPxYtt1Wc//SPfJLNoZJzfdt0B6ksj2jA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5096,7 +5084,7 @@ "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", - "@smithy/util-stream": "^4.5.11", + "@smithy/util-stream": "^4.5.12", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" @@ -5198,13 +5186,13 @@ } }, "../Common/node_modules/@smithy/middleware-endpoint": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.13.tgz", - "integrity": "sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==", + "version": "4.4.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.16.tgz", + "integrity": "sha512-L5GICFCSsNhbJ5JSKeWFGFy16Q2OhoBizb3X2DrxaJwXSEujVvjG9Jt386dpQn2t7jINglQl0b4K/Su69BdbMA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.22.1", + "@smithy/core": "^3.23.2", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -5218,16 +5206,16 @@ } }, "../Common/node_modules/@smithy/middleware-retry": { - "version": "4.4.30", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.30.tgz", - "integrity": "sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg==", + "version": "4.4.33", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.33.tgz", + "integrity": "sha512-jLqZOdJhtIL4lnA9hXnAG6GgnJlo1sD3FqsTxm9wSfjviqgWesY/TMBVnT84yr4O0Vfe0jWoXlfFbzsBVph3WA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -5284,9 +5272,9 @@ } }, "../Common/node_modules/@smithy/node-http-handler": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.9.tgz", - "integrity": "sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.10.tgz", + "integrity": "sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5405,18 +5393,18 @@ } }, "../Common/node_modules/@smithy/smithy-client": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.11.2.tgz", - "integrity": "sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==", + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.11.5.tgz", + "integrity": "sha512-xixwBRqoeP2IUgcAl3U9dvJXc+qJum4lzo3maaJxifsZxKUYLfVfCXvhT4/jD01sRrHg5zjd1cw2Zmjr4/SuKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.22.1", - "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/core": "^3.23.2", + "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.11", + "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" }, "engines": { @@ -5520,14 +5508,14 @@ } }, "../Common/node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.29", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.29.tgz", - "integrity": "sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q==", + "version": "4.3.32", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.32.tgz", + "integrity": "sha512-092sjYfFMQ/iaPH798LY/OJFBcYu0sSK34Oy9vdixhsU36zlZu8OcYjF3TD4e2ARupyK7xaxPXl+T0VIJTEkkg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5536,9 +5524,9 @@ } }, "../Common/node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.32", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.32.tgz", - "integrity": "sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q==", + "version": "4.2.35", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.35.tgz", + "integrity": "sha512-miz/ggz87M8VuM29y7jJZMYkn7+IErM5p5UgKIf8OtqVs/h2bXr1Bt3uTsREsI/4nK8a0PQERbAPsVPVNIsG7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5546,7 +5534,7 @@ "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5612,14 +5600,14 @@ } }, "../Common/node_modules/@smithy/util-stream": { - "version": "4.5.11", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.11.tgz", - "integrity": "sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==", + "version": "4.5.12", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.12.tgz", + "integrity": "sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.9", + "@smithy/node-http-handler": "^4.4.10", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", @@ -8040,17 +8028,17 @@ } }, "../Common/node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.1.tgz", + "integrity": "sha512-f0yv5CPKaFxfsPTBzX7vGuim4oIC1/gcS7LUGdBSwl2dU6+FON6LVUksdOo1qJjoUvXNn45urgh8C+0a24pACQ==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/cst-dts-gen": "11.1.1", + "@chevrotain/gast": "11.1.1", + "@chevrotain/regexp-to-ast": "11.1.1", + "@chevrotain/types": "11.1.1", + "@chevrotain/utils": "11.1.1", + "lodash-es": "4.17.23" } }, "../Common/node_modules/chevrotain-allstar": { @@ -8065,12 +8053,6 @@ "chevrotain": "^11.0.0" } }, - "../Common/node_modules/chevrotain/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==", - "license": "MIT" - }, "../Common/node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -13296,19 +13278,20 @@ } }, "../Common/node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", "license": "MIT", "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" + "vscode-uri": "~3.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.10.0", + "npm": ">=10.2.3" } }, "../Common/node_modules/layout-base": { @@ -14106,14 +14089,14 @@ } }, "../Common/node_modules/mermaid": { - "version": "11.12.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", - "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "version": "11.12.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.3.tgz", + "integrity": "sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", - "@mermaid-js/parser": "^0.6.3", + "@mermaid-js/parser": "^1.0.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -14125,7 +14108,7 @@ "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", - "lodash-es": "^4.17.21", + "lodash-es": "^4.17.23", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", @@ -19836,9 +19819,9 @@ "license": "MIT" }, "../Common/node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "license": "MIT" }, "../Common/node_modules/w3c-xmlserializer": { diff --git a/HelmChart/Public/oneuptime/templates/_helpers.tpl b/HelmChart/Public/oneuptime/templates/_helpers.tpl index 86c42e2fc4..dbd4a39676 100644 --- a/HelmChart/Public/oneuptime/templates/_helpers.tpl +++ b/HelmChart/Public/oneuptime/templates/_helpers.tpl @@ -198,11 +198,29 @@ Usage: {{- end }} {{- end }} +{{- define "oneuptime.env.registerProbeKey" }} +- name: REGISTER_PROBE_KEY + {{- if $.Values.registerProbeKey }} + value: {{ $.Values.registerProbeKey }} + {{- else }} + valueFrom: + secretKeyRef: + name: {{ printf "%s-%s" $.Release.Name "secrets" }} + key: register-probe-key + {{- end }} +{{- end }} + {{- define "oneuptime.env.runtime" }} - name: VAPID_PRIVATE_KEY value: {{ $.Values.vapid.privateKey }} +- name: EXPO_ACCESS_TOKEN + value: {{ default "" $.Values.expo.accessToken | quote }} + +- name: PUSH_NOTIFICATION_RELAY_URL + value: {{ default "https://oneuptime.com/api/notification/push-relay/send" $.Values.pushNotification.relayUrl | quote }} + - name: SLACK_APP_CLIENT_SECRET value: {{ $.Values.slackApp.clientSecret }} diff --git a/HelmChart/Public/oneuptime/templates/isolated-vm.yaml b/HelmChart/Public/oneuptime/templates/isolated-vm.yaml index d930b41a77..9086f14b79 100644 --- a/HelmChart/Public/oneuptime/templates/isolated-vm.yaml +++ b/HelmChart/Public/oneuptime/templates/isolated-vm.yaml @@ -73,12 +73,23 @@ spec: {{- end }} imagePullPolicy: {{ $.Values.image.pullPolicy }} env: - {{- include "oneuptime.env.common" . | nindent 12 }} {{- include "oneuptime.env.oneuptimeSecret" . | nindent 12 }} - name: PORT value: {{ $.Values.isolatedVM.ports.http | quote }} + - name: LOG_LEVEL + value: {{ $.Values.logLevel }} + - name: NODE_ENV + value: {{ $.Values.nodeEnvironment }} - name: DISABLE_TELEMETRY value: {{ $.Values.isolatedVM.disableTelemetryCollection | quote }} + {{- if $.Values.openTelemetryExporter.endpoint }} + - name: OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT + value: {{ $.Values.openTelemetryExporter.endpoint }} + {{- end }} + {{- if $.Values.openTelemetryExporter.headers }} + - name: OPENTELEMETRY_EXPORTER_OTLP_HEADERS + value: {{ $.Values.openTelemetryExporter.headers }} + {{- end }} ports: - containerPort: {{ $.Values.isolatedVM.ports.http }} diff --git a/HelmChart/Public/oneuptime/templates/probe-ingest.yaml b/HelmChart/Public/oneuptime/templates/probe-ingest.yaml index 24d3eb3c09..46001257c3 100644 --- a/HelmChart/Public/oneuptime/templates/probe-ingest.yaml +++ b/HelmChart/Public/oneuptime/templates/probe-ingest.yaml @@ -112,6 +112,7 @@ spec: value: {{ $.Values.probeIngest.disableTelemetryCollection | quote }} - name: PROBE_INGEST_CONCURRENCY value: {{ $.Values.probeIngest.concurrency | squote }} + {{- include "oneuptime.env.registerProbeKey" (dict "Values" $.Values "Release" $.Release) | nindent 12 }} ports: - containerPort: {{ $.Values.probeIngest.ports.http }} protocol: TCP diff --git a/HelmChart/Public/oneuptime/templates/probe.yaml b/HelmChart/Public/oneuptime/templates/probe.yaml index f99631636e..3c5de0fb93 100644 --- a/HelmChart/Public/oneuptime/templates/probe.yaml +++ b/HelmChart/Public/oneuptime/templates/probe.yaml @@ -131,7 +131,7 @@ spec: - name: NO_PROXY value: {{ $val.proxy.noProxy | squote }} {{- end }} - {{- include "oneuptime.env.runtime" (dict "Values" $.Values "Release" $.Release) | nindent 12 }} + {{- include "oneuptime.env.registerProbeKey" (dict "Values" $.Values "Release" $.Release) | nindent 12 }} ports: - containerPort: {{ if and $val.ports $val.ports.http }}{{ $val.ports.http }}{{ else }}3874{{ end }} protocol: TCP diff --git a/HelmChart/Public/oneuptime/templates/secrets.yaml b/HelmChart/Public/oneuptime/templates/secrets.yaml index 38465a9db7..6cf517a168 100644 --- a/HelmChart/Public/oneuptime/templates/secrets.yaml +++ b/HelmChart/Public/oneuptime/templates/secrets.yaml @@ -17,6 +17,13 @@ stringData: {{- else }} oneuptime-secret: {{ index (lookup "v1" "Secret" $.Release.Namespace (printf "%s-secrets" $.Release.Name)).data "oneuptime-secret" | b64dec }} {{- end }} + {{- if .Values.registerProbeKey }} + register-probe-key: {{ .Values.registerProbeKey | quote }} + {{- else if (index (lookup "v1" "Secret" $.Release.Namespace (printf "%s-secrets" $.Release.Name)).data "register-probe-key") }} + register-probe-key: {{ index (lookup "v1" "Secret" $.Release.Namespace (printf "%s-secrets" $.Release.Name)).data "register-probe-key" | b64dec }} + {{- else }} + register-probe-key: {{ randAlphaNum 32 | quote }} + {{- end }} {{- if .Values.encryptionSecret }} encryption-secret: {{ .Values.encryptionSecret | quote }} {{- else }} @@ -48,6 +55,11 @@ stringData: {{- else }} oneuptime-secret: {{ randAlphaNum 32 | quote }} {{- end }} + {{- if .Values.registerProbeKey }} + register-probe-key: {{ .Values.registerProbeKey | quote }} + {{- else }} + register-probe-key: {{ randAlphaNum 32 | quote }} + {{- end }} {{- if .Values.encryptionSecret }} encryption-secret: {{ .Values.encryptionSecret | quote }} {{- else }} diff --git a/HelmChart/Public/oneuptime/values.schema.json b/HelmChart/Public/oneuptime/values.schema.json index 9e0858dd9c..1bfd4a042e 100644 --- a/HelmChart/Public/oneuptime/values.schema.json +++ b/HelmChart/Public/oneuptime/values.schema.json @@ -35,6 +35,9 @@ "oneuptimeSecret": { "type": ["string", "null"] }, + "registerProbeKey": { + "type": ["string", "null"] + }, "encryptionSecret": { "type": ["string", "null"] }, @@ -727,6 +730,24 @@ }, "additionalProperties": false }, + "expo": { + "type": "object", + "properties": { + "accessToken": { + "type": ["string", "null"] + } + }, + "additionalProperties": false + }, + "pushNotification": { + "type": "object", + "properties": { + "relayUrl": { + "type": ["string", "null"] + } + }, + "additionalProperties": false + }, "incidents": { "type": "object", "properties": { diff --git a/HelmChart/Public/oneuptime/values.yaml b/HelmChart/Public/oneuptime/values.yaml index 225880a91f..296804e6d3 100644 --- a/HelmChart/Public/oneuptime/values.yaml +++ b/HelmChart/Public/oneuptime/values.yaml @@ -32,6 +32,7 @@ image: # Important: You do need to set this to a long random values if you're using OneUptime in production. # Please set this to string. oneuptimeSecret: +registerProbeKey: encryptionSecret: # External Secrets @@ -287,6 +288,15 @@ vapid: privateKey: subject: mailto:support@oneuptime.com +# Expo access token for sending mobile push notifications directly via Expo SDK. +# If not set, notifications are relayed through the push notification relay URL. +expo: + accessToken: + +# Push notification relay URL for self-hosted instances without Expo credentials +pushNotification: + relayUrl: https://oneuptime.com/api/notification/push-relay/send + incidents: disableAutomaticCreation: false diff --git a/IsolatedVM/Dockerfile.tpl b/IsolatedVM/Dockerfile.tpl index 1c9bd720da..5ba8e5c893 100644 --- a/IsolatedVM/Dockerfile.tpl +++ b/IsolatedVM/Dockerfile.tpl @@ -3,7 +3,7 @@ # # Pull base image nodejs image. -FROM public.ecr.aws/docker/library/node:21.6-alpine3.18 +FROM public.ecr.aws/docker/library/node:24.9-alpine3.21 RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global RUN npm config set fetch-retries 5 diff --git a/MCP/package-lock.json b/MCP/package-lock.json index 66b698572b..fe4289214f 100644 --- a/MCP/package-lock.json +++ b/MCP/package-lock.json @@ -1297,9 +1297,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", diff --git a/MobileApp/app.json b/MobileApp/app.json index 0c65778632..d7d2d4a8d8 100644 --- a/MobileApp/app.json +++ b/MobileApp/app.json @@ -1,7 +1,7 @@ { "expo": { "name": "OneUptime", - "slug": "oneuptime", + "slug": "oneuptime-on-call", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", @@ -11,7 +11,7 @@ "splash": { "image": "./assets/splash-icon.png", "resizeMode": "contain", - "backgroundColor": "#FFFFFF" + "backgroundColor": "#0D1117" }, "ios": { "supportsTablet": true, @@ -29,9 +29,22 @@ "backgroundColor": "#0D1117" }, "edgeToEdgeEnabled": false, - "package": "com.oneuptime.oncall" + "package": "com.oneuptime.oncall", + "googleServicesFile": "./google-services.json", + "permissions": [ + "android.permission.USE_BIOMETRIC", + "android.permission.USE_FINGERPRINT" + ] }, "plugins": [ + [ + "expo-splash-screen", + { + "backgroundColor": "#0D1117", + "image": "./assets/splash-icon.png", + "imageWidth": 200 + } + ], [ "expo-notifications", { @@ -43,6 +56,12 @@ ], "web": { "favicon": "./assets/favicon.png" - } + }, + "extra": { + "eas": { + "projectId": "d9f87edc-1c3e-466f-b032-1ced7621aa8a" + } + }, + "owner": "oneuptime" } } diff --git a/MobileApp/assets/adaptive-icon.png b/MobileApp/assets/adaptive-icon.png index 03d6f6b6c6..0787b7607d 100644 Binary files a/MobileApp/assets/adaptive-icon.png and b/MobileApp/assets/adaptive-icon.png differ diff --git a/MobileApp/assets/favicon.png b/MobileApp/assets/favicon.png index e75f697b18..e77e17d2c8 100644 Binary files a/MobileApp/assets/favicon.png and b/MobileApp/assets/favicon.png differ diff --git a/MobileApp/assets/icon.png b/MobileApp/assets/icon.png index a0b1526fc7..b5bf5a6373 100644 Binary files a/MobileApp/assets/icon.png and b/MobileApp/assets/icon.png differ diff --git a/MobileApp/assets/splash-icon.png b/MobileApp/assets/splash-icon.png index 03d6f6b6c6..10a95fa59a 100644 Binary files a/MobileApp/assets/splash-icon.png and b/MobileApp/assets/splash-icon.png differ diff --git a/MobileApp/eas.json b/MobileApp/eas.json new file mode 100644 index 0000000000..bbabbc87ef --- /dev/null +++ b/MobileApp/eas.json @@ -0,0 +1,18 @@ +{ + "cli": { + "version": ">= 3.0.0" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal" + }, + "preview": { + "distribution": "internal" + }, + "production": {} + }, + "submit": { + "production": {} + } +} diff --git a/MobileApp/google-services.json b/MobileApp/google-services.json new file mode 100644 index 0000000000..c1ab824b3c --- /dev/null +++ b/MobileApp/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "877286215861", + "project_id": "oneuptime-on-call", + "storage_bucket": "oneuptime-on-call.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:877286215861:android:f783c4aa68be6cba54eefc", + "android_client_info": { + "package_name": "com.oneuptime.oncall" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyBVUYdIldBliGtG0mIGa-nNs6eUJkJmKOM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} diff --git a/MobileApp/package-lock.json b/MobileApp/package-lock.json index f22d5d6263..8724ad4874 100644 --- a/MobileApp/package-lock.json +++ b/MobileApp/package-lock.json @@ -97,7 +97,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1378,6 +1377,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -3171,7 +3171,6 @@ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.28.tgz", "integrity": "sha512-d1QDn+KNHfHGt3UIwOZvupvdsDdiHYZBEj7+wL2yDVo3tMezamYy60H9s3EnNVE1Ae1ty0trc7F2OKqo/RmsdQ==", "license": "MIT", - "peer": true, "dependencies": { "@react-navigation/core": "^7.14.0", "escape-string-regexp": "^4.0.0", @@ -3290,7 +3289,6 @@ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.20.tgz", "integrity": "sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==", "license": "MIT", - "peer": true, "dependencies": { "@tanstack/query-core": "5.90.20" }, @@ -3408,7 +3406,6 @@ "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -4130,7 +4127,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5206,7 +5202,6 @@ "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz", "integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "54.0.23", @@ -5294,7 +5289,6 @@ "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz", "integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==", "license": "MIT", - "peer": true, "dependencies": { "fontfaceobserver": "^2.1.0" }, @@ -7206,7 +7200,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -8739,7 +8732,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9071,7 +9063,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9091,7 +9082,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -9122,7 +9112,6 @@ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz", "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==", "license": "MIT", - "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.81.5", @@ -9486,6 +9475,7 @@ "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.2.1.tgz", "integrity": "sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg==", "license": "MIT", + "peer": true, "dependencies": { "react-native-is-edge-to-edge": "1.2.1", "semver": "7.7.3" @@ -9501,6 +9491,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", + "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -9513,7 +9504,6 @@ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", "license": "MIT", - "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -9524,7 +9514,6 @@ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", "license": "MIT", - "peer": true, "dependencies": { "react-freeze": "^1.0.0", "react-native-is-edge-to-edge": "^1.2.1", @@ -9555,7 +9544,6 @@ "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", "integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", @@ -9588,6 +9576,7 @@ "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.7.3.tgz", "integrity": "sha512-m/CIUCHvLQulboBn0BtgpsesXjOTeubU7t+V0lCPpBj0t2ExigwqDHoKj3ck7OeErnjgkD27wdAtQCubYATe3g==", "license": "MIT", + "peer": true, "dependencies": { "@babel/plugin-transform-arrow-functions": "7.27.1", "@babel/plugin-transform-class-properties": "7.27.1", @@ -9612,6 +9601,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -9628,6 +9618,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", @@ -9648,6 +9639,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -9663,6 +9655,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -9679,6 +9672,7 @@ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -9698,6 +9692,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", + "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -9794,7 +9789,6 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -10626,7 +10620,6 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -10660,9 +10653,9 @@ } }, "node_modules/tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -10855,7 +10848,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -11416,7 +11408,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, diff --git a/MobileApp/src/App.tsx b/MobileApp/src/App.tsx index ee7d2fc19e..1189ec2732 100644 --- a/MobileApp/src/App.tsx +++ b/MobileApp/src/App.tsx @@ -51,7 +51,7 @@ function AppContent(): React.JSX.Element { borderRadius: 999, }} /> - + diff --git a/MobileApp/src/api/pushDevice.ts b/MobileApp/src/api/pushDevice.ts index e9e103f043..ab443d96f2 100644 --- a/MobileApp/src/api/pushDevice.ts +++ b/MobileApp/src/api/pushDevice.ts @@ -1,6 +1,7 @@ import { Platform } from "react-native"; import * as Device from "expo-device"; import apiClient from "./client"; +import logger from "../utils/logger"; export async function registerPushDevice(params: { deviceToken: string; @@ -8,10 +9,10 @@ export async function registerPushDevice(params: { }): Promise { const deviceType: string = Platform.OS === "ios" - ? "iOS" + ? "ios" : Platform.OS === "android" - ? "Android" - : "Web"; + ? "android" + : "web"; try { await apiClient.post("/api/user-push/register", { @@ -20,11 +21,29 @@ export async function registerPushDevice(params: { deviceName: Device.modelName || "Unknown Device", projectId: params.projectId, }); - } catch (error: any) { + logger.info( + `[PushNotifications] Device registered successfully for project ${params.projectId}`, + ); + } catch (error: unknown) { + const status: number | undefined = ( + error as { response?: { status?: number } } + )?.response?.status; + const message: string = + (error as { response?: { data?: { message?: string } } })?.response?.data + ?.message || String(error); + // Treat "already registered" as success - if (error?.response?.status === 400) { + if (status === 400 && message.includes("already registered")) { + logger.info( + `[PushNotifications] Device already registered for project ${params.projectId}`, + ); return; } + + // Log and re-throw other errors + logger.error( + `[PushNotifications] Registration failed (status=${status}): ${message}`, + ); throw error; } } diff --git a/MobileApp/src/components/AddNoteModal.tsx b/MobileApp/src/components/AddNoteModal.tsx index b126b42ef5..28e26e04ee 100644 --- a/MobileApp/src/components/AddNoteModal.tsx +++ b/MobileApp/src/components/AddNoteModal.tsx @@ -49,32 +49,53 @@ export default function AddNoteModal({ onRequestClose={handleClose} > - + - + @@ -85,8 +106,9 @@ export default function AddNoteModal({ /> - + { return { flex: 1, - paddingVertical: 12, + height: 50, borderRadius: 12, alignItems: "center" as const, justifyContent: "center" as const, - minHeight: 48, borderWidth: 1, borderColor: theme.colors.borderDefault, opacity: pressed ? 0.7 : 1, @@ -131,21 +162,23 @@ export default function AddNoteModal({ disabled={isSubmitting} > Cancel - - - + diff --git a/MobileApp/src/components/AlertCard.tsx b/MobileApp/src/components/AlertCard.tsx index 446a920fd5..591e7fdef6 100644 --- a/MobileApp/src/components/AlertCard.tsx +++ b/MobileApp/src/components/AlertCard.tsx @@ -45,13 +45,14 @@ export default function AlertCard({ accessibilityLabel={`Alert ${alert.alertNumberWithPrefix || alert.alertNumber}, ${alert.title}. State: ${alert.currentAlertState?.name ?? "unknown"}. Severity: ${alert.alertSeverity?.name ?? "unknown"}.`} > - - - + + + {projectName ? : null} - + - + {timeString} - + {alert.title} @@ -139,21 +172,40 @@ export default function AlertCard({ /> - + {alert.currentAlertState ? ( {alert.currentAlertState.name} @@ -162,12 +214,21 @@ export default function AlertCard({ {alert.alertSeverity ? ( {alert.alertSeverity.name} @@ -177,33 +238,45 @@ export default function AlertCard({ {alert.monitor ? ( - + {alert.monitor.name} Linked monitor diff --git a/MobileApp/src/components/EmptyState.tsx b/MobileApp/src/components/EmptyState.tsx index f68ea683d3..54fbef3116 100644 --- a/MobileApp/src/components/EmptyState.tsx +++ b/MobileApp/src/components/EmptyState.tsx @@ -32,10 +32,22 @@ export default function EmptyState({ const { theme } = useTheme(); return ( - + @@ -47,20 +59,35 @@ export default function EmptyState({ {title} {subtitle ? ( - + {subtitle} ) : null} {actionLabel && onAction ? ( - + ) : null} diff --git a/MobileApp/src/components/EpisodeCard.tsx b/MobileApp/src/components/EpisodeCard.tsx index ed73345afa..f7f7c07b79 100644 --- a/MobileApp/src/components/EpisodeCard.tsx +++ b/MobileApp/src/components/EpisodeCard.tsx @@ -61,169 +61,242 @@ export default function EpisodeCard( ); return ( - { - return { - marginBottom: 12, - opacity: pressed ? 0.7 : muted ? 0.5 : 1, - }; - }} - onPress={onPress} - accessibilityRole="button" - accessibilityLabel={`${type === "incident" ? "Incident" : "Alert"} episode ${episode.episodeNumberWithPrefix || episode.episodeNumber}, ${episode.title}. State: ${state?.name ?? "unknown"}. Severity: ${severity?.name ?? "unknown"}.`} - > - + { + return { + opacity: pressed ? 0.7 : muted ? 0.5 : 1, + }; }} + onPress={onPress} + accessibilityRole="button" + accessibilityLabel={`${type === "incident" ? "Incident" : "Alert"} episode ${episode.episodeNumberWithPrefix || episode.episodeNumber}, ${episode.title}. State: ${state?.name ?? "unknown"}. Severity: ${severity?.name ?? "unknown"}.`} > - - - - {projectName ? : null} + > + + + + {projectName ? : null} + + + + {type === "incident" ? "INCIDENT EPISODE" : "ALERT EPISODE"} + + + + + {episode.episodeNumberWithPrefix || + `#${episode.episodeNumber}`} + + + + - {type === "incident" ? "INCIDENT EPISODE" : "ALERT EPISODE"} - - - - - {episode.episodeNumberWithPrefix || - `#${episode.episodeNumber}`} + {timeString} - - - - {timeString} - - - - - - {episode.title} - - - - - - {state ? ( - + {episode.title} + + + + + + {state ? ( - - {state.name} - - - ) : null} + + + {state.name} + + + ) : null} - {severity ? ( - - - {severity.name} - - - ) : null} + + {severity.name} + + + ) : null} - {childCount > 0 ? ( - - 0 ? ( + - {childCount} {type === "incident" ? "incident" : "alert"} - {childCount !== 1 ? "s" : ""} - - - ) : null} + + {childCount} {type === "incident" ? "incident" : "alert"} + {childCount !== 1 ? "s" : ""} + + + ) : null} + - - + + ); } diff --git a/MobileApp/src/components/FeedTimeline.tsx b/MobileApp/src/components/FeedTimeline.tsx index 438efc3038..0abbd6531b 100644 --- a/MobileApp/src/components/FeedTimeline.tsx +++ b/MobileApp/src/components/FeedTimeline.tsx @@ -28,24 +28,35 @@ export default function FeedTimeline({ const moreText: string | undefined = entry.moreInformationInMarkdown; return ( - - + + {!isLast ? ( ) : null} {moreText ? ( - + ) : null} {timeString} diff --git a/MobileApp/src/components/GlassCard.tsx b/MobileApp/src/components/GlassCard.tsx index 614d460a11..50e7ce9d54 100644 --- a/MobileApp/src/components/GlassCard.tsx +++ b/MobileApp/src/components/GlassCard.tsx @@ -17,17 +17,16 @@ export default function GlassCard({ return ( {children} diff --git a/MobileApp/src/components/GradientButton.tsx b/MobileApp/src/components/GradientButton.tsx index 3eeed771f1..1cd65c72bf 100644 --- a/MobileApp/src/components/GradientButton.tsx +++ b/MobileApp/src/components/GradientButton.tsx @@ -29,9 +29,7 @@ export default function GradientButton({ style, }: GradientButtonProps): React.JSX.Element { const { theme } = useTheme(); - const primaryContentColor: string = theme.isDark - ? theme.colors.backgroundPrimary - : "#FFFFFF"; + const primaryContentColor: string = theme.colors.backgroundPrimary; const isDisabled: boolean = disabled || loading; diff --git a/MobileApp/src/components/IncidentCard.tsx b/MobileApp/src/components/IncidentCard.tsx index 3e49ef68fb..8a120941f3 100644 --- a/MobileApp/src/components/IncidentCard.tsx +++ b/MobileApp/src/components/IncidentCard.tsx @@ -53,13 +53,14 @@ export default function IncidentCard({ accessibilityLabel={`Incident ${incident.incidentNumberWithPrefix || incident.incidentNumber}, ${incident.title}. State: ${incident.currentIncidentState?.name ?? "unknown"}. Severity: ${incident.incidentSeverity?.name ?? "unknown"}.`} > - - - + + + {projectName ? : null} - + - + {timeString} - + {incident.title} @@ -148,21 +181,40 @@ export default function IncidentCard({ /> - + {incident.currentIncidentState ? ( {incident.currentIncidentState.name} @@ -171,12 +223,21 @@ export default function IncidentCard({ {incident.incidentSeverity ? ( {incident.incidentSeverity.name} @@ -186,33 +247,45 @@ export default function IncidentCard({ {monitorCount > 0 ? ( - + {monitorNames} {monitorCount} monitor{monitorCount !== 1 ? "s" : ""} diff --git a/MobileApp/src/components/NotesSection.tsx b/MobileApp/src/components/NotesSection.tsx index 338f069b5d..998781dd52 100644 --- a/MobileApp/src/components/NotesSection.tsx +++ b/MobileApp/src/components/NotesSection.tsx @@ -16,14 +16,19 @@ export default function NotesSection({ setNoteModalVisible, }: NotesSectionProps): React.JSX.Element { const { theme } = useTheme(); - const addNoteContentColor: string = theme.isDark - ? theme.colors.backgroundPrimary - : "#FFFFFF"; + const addNoteContentColor: string = "#FFFFFF"; return ( - - - + + + Internal Notes @@ -45,7 +55,7 @@ export default function NotesSection({ borderRadius: 8, paddingHorizontal: 12, paddingVertical: 6, - backgroundColor: theme.colors.actionPrimary, + backgroundColor: theme.colors.accentGradientStart, opacity: pressed ? 0.85 : 1, }; }} @@ -60,8 +70,11 @@ export default function NotesSection({ style={{ marginRight: 4 }} /> Add Note @@ -76,39 +89,52 @@ export default function NotesSection({ return ( - + {noteText} - + {note.createdByUser ? ( {authorName} ) : null} {formatDateTime(note.createdAt)} @@ -121,16 +147,20 @@ export default function NotesSection({ {notes && notes.length === 0 ? ( No notes yet. diff --git a/MobileApp/src/components/OfflineBanner.tsx b/MobileApp/src/components/OfflineBanner.tsx index 7ecc9e35dc..3ef000169a 100644 --- a/MobileApp/src/components/OfflineBanner.tsx +++ b/MobileApp/src/components/OfflineBanner.tsx @@ -26,8 +26,15 @@ export default function OfflineBanner(): React.JSX.Element | null { return ( - + - + No internet connection diff --git a/MobileApp/src/components/ProjectBadge.tsx b/MobileApp/src/components/ProjectBadge.tsx index 4140e88822..bbbc044bf7 100644 --- a/MobileApp/src/components/ProjectBadge.tsx +++ b/MobileApp/src/components/ProjectBadge.tsx @@ -13,14 +13,22 @@ export default function ProjectBadge({ }: ProjectBadgeProps): React.JSX.Element { const { theme } = useTheme(); return ( - + {name} diff --git a/MobileApp/src/components/RootCauseCard.tsx b/MobileApp/src/components/RootCauseCard.tsx index 6db238ca45..126d4d7351 100644 --- a/MobileApp/src/components/RootCauseCard.tsx +++ b/MobileApp/src/components/RootCauseCard.tsx @@ -14,20 +14,24 @@ export default function RootCauseCard({ return ( - + {rootCauseText ? ( ) : ( No root cause documented yet. diff --git a/MobileApp/src/components/SectionHeader.tsx b/MobileApp/src/components/SectionHeader.tsx index 4e1b19783b..9d4ce31ceb 100644 --- a/MobileApp/src/components/SectionHeader.tsx +++ b/MobileApp/src/components/SectionHeader.tsx @@ -14,10 +14,21 @@ export default function SectionHeader({ }: SectionHeaderProps): React.JSX.Element { const { theme } = useTheme(); return ( - + { @@ -19,52 +19,46 @@ export default function SegmentedControl({ onSelect, }: SegmentedControlProps): React.JSX.Element { const { theme } = useTheme(); - const activeContentColor: string = theme.isDark - ? theme.colors.backgroundPrimary - : "#FFFFFF"; + const activeContentColor: string = theme.colors.backgroundPrimary; return ( - {segments.map((segment: Segment) => { + {segments.map((segment: Segment, index: number) => { const isActive: boolean = segment.key === selected; return ( - { - return [ - { - flex: 1, - alignItems: "center" as const, - paddingVertical: 10, - borderRadius: 12, - opacity: pressed ? 0.7 : 1, - }, - isActive - ? { - backgroundColor: theme.colors.actionPrimary, - shadowColor: theme.colors.actionPrimary, - shadowOpacity: theme.isDark ? 0.28 : 0.18, - shadowOffset: { width: 0, height: 5 }, - shadowRadius: 10, - elevation: 4, - } - : undefined, - ]; - }} + activeOpacity={0.7} onPress={() => { return onSelect(segment.key); }} + style={{ + flex: 1, + alignItems: "center", + paddingVertical: 10, + borderRadius: 12, + marginLeft: index > 0 ? 4 : 0, + backgroundColor: isActive + ? theme.colors.actionPrimary + : "transparent", + }} > ({ > {segment.label} - + ); })} diff --git a/MobileApp/src/components/SeverityBadge.tsx b/MobileApp/src/components/SeverityBadge.tsx index 6b5d0d8139..5382feb44f 100644 --- a/MobileApp/src/components/SeverityBadge.tsx +++ b/MobileApp/src/components/SeverityBadge.tsx @@ -43,12 +43,21 @@ export default function SeverityBadge({ return ( {displayLabel.toUpperCase()} diff --git a/MobileApp/src/components/SkeletonCard.tsx b/MobileApp/src/components/SkeletonCard.tsx index b649729dfd..deab0c9818 100644 --- a/MobileApp/src/components/SkeletonCard.tsx +++ b/MobileApp/src/components/SkeletonCard.tsx @@ -59,8 +59,10 @@ export default function SkeletonCard({ if (variant === "compact") { return ( - - + + @@ -98,14 +120,15 @@ export default function SkeletonCard({ if (variant === "detail") { return ( - + - + - + {Array.from({ length: 3 }).map((_: unknown, index: number) => { return ( - + ); @@ -171,8 +225,10 @@ export default function SkeletonCard({ return ( - - + + - + {Array.from({ length: Math.max(lines - 1, 1) }).map( @@ -217,8 +307,10 @@ export default function SkeletonCard({ return ( + - + {displayLabel.charAt(0).toUpperCase() + displayLabel.slice(1)} diff --git a/MobileApp/src/components/SwipeableCard.tsx b/MobileApp/src/components/SwipeableCard.tsx index 520d55a793..2e779546db 100644 --- a/MobileApp/src/components/SwipeableCard.tsx +++ b/MobileApp/src/components/SwipeableCard.tsx @@ -94,25 +94,63 @@ export default function SwipeableCard({ ).current; return ( - + {/* Background actions */} - + {leftAction ? ( - + {leftAction.label} ) : null} {rightAction ? ( - + {rightAction.label} @@ -121,8 +159,8 @@ export default function SwipeableCard({ {/* Foreground content */} Promise = async (): Promise => { - const token: string | null = await requestPermissionsAndGetToken(); + let token: string | null = null; + let attempt: number = 0; + + // Retry obtaining the push token + while (!token && attempt < MAX_RETRIES && !cancelled) { + token = await requestPermissionsAndGetToken(); + if (!token && !cancelled) { + attempt++; + if (attempt < MAX_RETRIES) { + logger.warn( + `[PushNotifications] Push token not available, retrying in ${RETRY_DELAY_MS}ms (attempt ${attempt}/${MAX_RETRIES})`, + ); + await new Promise((resolve: () => void): void => { + setTimeout(resolve, RETRY_DELAY_MS); + }); + } + } + } + if (!token || cancelled) { + if (!token) { + logger.warn( + "[PushNotifications] Could not obtain push token after all retries — device will not be registered", + ); + } return; } @@ -63,13 +90,21 @@ export function usePushNotifications(navigationRef: unknown): void { deviceToken: token, projectId: project._id, }); - } catch { - // Continue registering with other projects + } catch (error: unknown) { + logger.warn( + `[PushNotifications] Failed to register device for project ${project._id}:`, + error, + ); } } }; - register(); + register().catch((error: unknown): void => { + logger.error( + "[PushNotifications] Unexpected error during push registration:", + error, + ); + }); return (): void => { cancelled = true; diff --git a/MobileApp/src/navigation/MainTabNavigator.tsx b/MobileApp/src/navigation/MainTabNavigator.tsx index 2bb60e7156..f57ce1118b 100644 --- a/MobileApp/src/navigation/MainTabNavigator.tsx +++ b/MobileApp/src/navigation/MainTabNavigator.tsx @@ -27,12 +27,15 @@ function TabIcon({ accentColor: string; }): React.JSX.Element { return ( - + {focused ? ( @@ -74,10 +77,8 @@ export default function MainTabNavigator(): React.JSX.Element { height: Platform.OS === "ios" ? 78 : 68, paddingBottom: Platform.OS === "ios" ? 18 : 10, paddingTop: 10, - shadowColor: theme.isDark - ? "#000000" - : theme.colors.accentGradientMid, - shadowOpacity: theme.isDark ? 0.35 : 0.12, + shadowColor: "#000000", + shadowOpacity: 0.35, shadowOffset: { width: 0, height: 8 }, shadowRadius: 18, elevation: 16, diff --git a/MobileApp/src/navigation/RootNavigator.tsx b/MobileApp/src/navigation/RootNavigator.tsx index b3f5cd1edb..0a8cb37c97 100644 --- a/MobileApp/src/navigation/RootNavigator.tsx +++ b/MobileApp/src/navigation/RootNavigator.tsx @@ -74,7 +74,7 @@ export default function RootNavigator(): React.JSX.Element { const navigationTheme: Theme = { ...DefaultTheme, - dark: theme.isDark, + dark: true, colors: { ...DefaultTheme.colors, primary: theme.colors.actionPrimary, diff --git a/MobileApp/src/notifications/setup.ts b/MobileApp/src/notifications/setup.ts index b2b0d2bf81..fb67d4ea9c 100644 --- a/MobileApp/src/notifications/setup.ts +++ b/MobileApp/src/notifications/setup.ts @@ -4,6 +4,7 @@ import * as Device from "expo-device"; import Constants from "expo-constants"; import { Platform } from "react-native"; import { PermissionStatus } from "expo-modules-core"; +import logger from "../utils/logger"; // Show notifications when app is in foreground Notifications.setNotificationHandler({ @@ -80,6 +81,9 @@ export async function setupNotificationCategories(): Promise { export async function requestPermissionsAndGetToken(): Promise { if (!Device.isDevice) { + logger.warn( + "[PushNotifications] Not a physical device — skipping push token registration", + ); return null; } @@ -92,6 +96,10 @@ export async function requestPermissionsAndGetToken(): Promise { } if (finalStatus !== "granted") { + logger.warn( + "[PushNotifications] Push notification permission not granted:", + finalStatus, + ); return null; } @@ -100,12 +108,20 @@ export async function requestPermissionsAndGetToken(): Promise { Constants.easConfig?.projectId; if (!projectId) { + logger.warn( + "[PushNotifications] EAS project ID not found — cannot register for push notifications", + ); return null; } - const tokenData: ExpoPushToken = await Notifications.getExpoPushTokenAsync({ - projectId, - }); + try { + const tokenData: ExpoPushToken = await Notifications.getExpoPushTokenAsync({ + projectId, + }); - return tokenData.data; + return tokenData.data; + } catch (error: unknown) { + logger.error("[PushNotifications] Failed to get push token:", error); + return null; + } } diff --git a/MobileApp/src/screens/AlertDetailScreen.tsx b/MobileApp/src/screens/AlertDetailScreen.tsx index 00cfb3ac6a..40e5689c79 100644 --- a/MobileApp/src/screens/AlertDetailScreen.tsx +++ b/MobileApp/src/screens/AlertDetailScreen.tsx @@ -140,8 +140,7 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { if (isLoading) { return ( @@ -151,13 +150,14 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { if (!alert) { return ( - + Alert not found. @@ -203,13 +203,15 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { > {/* Header card */} - + {alert.alertNumberWithPrefix || `#${alert.alertNumber}`} - + {alert.currentAlertState ? ( {alert.currentAlertState.name} @@ -272,12 +300,21 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { {alert.alertSeverity ? ( {alert.alertSeverity.name} @@ -289,19 +326,23 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { {/* Description */} {descriptionText ? ( - + {descriptionText} @@ -309,49 +350,60 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { ) : null} - + {/* Details */} - + - - + + Created {formatDateTime(alert.createdAt)} {alert.monitor ? ( - + Monitor {alert.monitor.name} @@ -363,103 +415,118 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { {/* State Change Actions */} {!isResolved ? ( - + - + {!isAcknowledged && !isResolved && acknowledgeState ? ( - { - return handleStateChange( - acknowledgeState._id, - acknowledgeState.name, - ); - }} - disabled={changingState} - accessibilityRole="button" - accessibilityLabel="Acknowledge alert" - > - {changingState ? ( - - ) : ( - <> - - - Acknowledge - - - )} - + + { + return handleStateChange( + acknowledgeState._id, + acknowledgeState.name, + ); + }} + disabled={changingState} + accessibilityRole="button" + accessibilityLabel="Acknowledge alert" + > + {changingState ? ( + + ) : ( + <> + + + Acknowledge + + + )} + + ) : null} {resolveState ? ( - { - return handleStateChange( - resolveState._id, - resolveState.name, - ); - }} - disabled={changingState} - accessibilityRole="button" - accessibilityLabel="Resolve alert" > - {changingState ? ( - - ) : ( - <> - - - Resolve - - - )} - + { + return handleStateChange( + resolveState._id, + resolveState.name, + ); + }} + disabled={changingState} + accessibilityRole="button" + accessibilityLabel="Resolve alert" + > + {changingState ? ( + + ) : ( + <> + + + Resolve + + + )} + + ) : null} @@ -468,7 +535,7 @@ export default function AlertDetailScreen({ route }: Props): React.JSX.Element { {/* Activity Feed */} {feed && feed.length > 0 ? ( - + diff --git a/MobileApp/src/screens/AlertEpisodeDetailScreen.tsx b/MobileApp/src/screens/AlertEpisodeDetailScreen.tsx index 3e7e596747..9488460c0d 100644 --- a/MobileApp/src/screens/AlertEpisodeDetailScreen.tsx +++ b/MobileApp/src/screens/AlertEpisodeDetailScreen.tsx @@ -148,8 +148,7 @@ export default function AlertEpisodeDetailScreen({ if (isLoading) { return ( @@ -159,13 +158,14 @@ export default function AlertEpisodeDetailScreen({ if (!episode) { return ( - + Episode not found. @@ -210,13 +210,15 @@ export default function AlertEpisodeDetailScreen({ } > - + {episode.episodeNumberWithPrefix || `#${episode.episodeNumber}`} {episode.title} - + {episode.currentAlertState ? ( {episode.currentAlertState.name} @@ -268,12 +299,21 @@ export default function AlertEpisodeDetailScreen({ ) : null} {episode.alertSeverity ? ( {episode.alertSeverity.name} @@ -284,19 +324,23 @@ export default function AlertEpisodeDetailScreen({ {descriptionText ? ( - + {descriptionText} @@ -304,19 +348,21 @@ export default function AlertEpisodeDetailScreen({ ) : null} - + - + - - + + Created {formatDateTime(episode.createdAt)} - + Alerts {episode.alertCount ?? 0} @@ -371,98 +428,113 @@ export default function AlertEpisodeDetailScreen({ {!isResolved ? ( - + - + {!isAcknowledged && !isResolved && acknowledgeState ? ( - { - return handleStateChange( - acknowledgeState._id, - acknowledgeState.name, - ); - }} - disabled={changingState} - > - {changingState ? ( - - ) : ( - <> - - - Acknowledge - - - )} - + + { + return handleStateChange( + acknowledgeState._id, + acknowledgeState.name, + ); + }} + disabled={changingState} + > + {changingState ? ( + + ) : ( + <> + + + Acknowledge + + + )} + + ) : null} {resolveState ? ( - { - return handleStateChange( - resolveState._id, - resolveState.name, - ); - }} - disabled={changingState} > - {changingState ? ( - - ) : ( - <> - - - Resolve - - - )} - + { + return handleStateChange( + resolveState._id, + resolveState.name, + ); + }} + disabled={changingState} + > + {changingState ? ( + + ) : ( + <> + + + Resolve + + + )} + + ) : null} @@ -470,7 +542,7 @@ export default function AlertEpisodeDetailScreen({ ) : null} {feed && feed.length > 0 ? ( - + diff --git a/MobileApp/src/screens/AlertsScreen.tsx b/MobileApp/src/screens/AlertsScreen.tsx index a77e140506..7f6d10bd62 100644 --- a/MobileApp/src/screens/AlertsScreen.tsx +++ b/MobileApp/src/screens/AlertsScreen.tsx @@ -60,8 +60,13 @@ function SectionHeader({ const { theme } = useTheme(); return ( - + @@ -325,8 +335,7 @@ export default function AlertsScreen(): React.JSX.Element { }; return ( + @@ -47,8 +57,10 @@ export default function BiometricLockScreen({ Use {biometricType.toLowerCase()} to unlock - + { - return { - flex: 1, - borderRadius: 24, - overflow: "hidden" as const, - opacity: pressed ? 0.7 : 1, - }; - }} + - + @@ -105,8 +116,9 @@ function StatCard({ /> - + ); } @@ -181,10 +195,22 @@ export default function HomeScreen(): React.JSX.Element { /> } > - + You don't have access to any projects. Contact your administrator or pull to refresh. - + @@ -250,15 +288,19 @@ export default function HomeScreen(): React.JSX.Element { /> } > - + - + - + {getGreeting()} - + - + Total active items - + { return { - borderRadius: 24, - overflow: "hidden" as const, - padding: 16, - backgroundColor: theme.colors.backgroundElevated, - borderWidth: 1, - borderColor: theme.colors.borderGlass, - shadowColor: theme.isDark - ? "#000" - : theme.colors.accentGradientMid, - shadowOpacity: theme.isDark ? 0.24 : 0.09, - shadowOffset: { width: 0, height: 8 }, - shadowRadius: 14, - elevation: 5, opacity: pressed ? 0.8 : 1, }; }} accessibilityRole="button" accessibilityLabel="View my on-call assignments" > - + > + - - + - - - - - My On-Call Policies - - - {onCallLoading - ? "Loading assignments..." - : totalAssignments > 0 - ? `${totalAssignments} active ${totalAssignments === 1 ? "assignment" : "assignments"} across ${onCallProjects.length} ${onCallProjects.length === 1 ? "project" : "projects"}` - : "You are not currently on-call"} - - - - - - - {onCallLoading ? "--" : totalAssignments} - - + + + + + + My On-Call Policies + + + {onCallLoading + ? "Loading assignments..." + : totalAssignments > 0 + ? `${totalAssignments} active ${totalAssignments === 1 ? "assignment" : "assignments"} across ${onCallProjects.length} ${onCallProjects.length === 1 ? "project" : "projects"}` + : "You are not currently on-call"} + + + + + + + {onCallLoading ? "--" : totalAssignments} + + + @@ -448,69 +522,83 @@ export default function HomeScreen(): React.JSX.Element { Incidents - - { - return navigation.navigate("Incidents"); - }} - /> - { - return navigation.navigate("Incidents"); - }} - /> + + + { + return navigation.navigate("Incidents"); + }} + /> + + + { + return navigation.navigate("Incidents"); + }} + /> + Alerts - - { - return navigation.navigate("Alerts"); - }} - /> - { - return navigation.navigate("Alerts"); - }} - /> + + + { + return navigation.navigate("Alerts"); + }} + /> + + + { + return navigation.navigate("Alerts"); + }} + /> + diff --git a/MobileApp/src/screens/IncidentDetailScreen.tsx b/MobileApp/src/screens/IncidentDetailScreen.tsx index f41347f775..5f0b6706d0 100644 --- a/MobileApp/src/screens/IncidentDetailScreen.tsx +++ b/MobileApp/src/screens/IncidentDetailScreen.tsx @@ -152,8 +152,7 @@ export default function IncidentDetailScreen({ if (isLoading) { return ( @@ -163,13 +162,14 @@ export default function IncidentDetailScreen({ if (!incident) { return ( - + Incident not found. @@ -217,13 +217,15 @@ export default function IncidentDetailScreen({ > {/* Header card */} - + {incident.incidentNumberWithPrefix || `#${incident.incidentNumber}`} - + {incident.currentIncidentState ? ( {incident.currentIncidentState.name} @@ -286,12 +314,21 @@ export default function IncidentDetailScreen({ {incident.incidentSeverity ? ( {incident.incidentSeverity.name} @@ -303,19 +340,23 @@ export default function IncidentDetailScreen({ {/* Description */} {descriptionText ? ( - + {descriptionText} @@ -323,66 +364,83 @@ export default function IncidentDetailScreen({ ) : null} - + {/* Details */} - + - + {incident.declaredAt ? ( - + Declared {formatDateTime(incident.declaredAt)} ) : null} - + Created {formatDateTime(incident.createdAt)} {incident.monitors?.length > 0 ? ( - + Monitors {incident.monitors .map((m: NamedEntity) => { @@ -398,103 +456,118 @@ export default function IncidentDetailScreen({ {/* State Change Actions */} {!isResolved ? ( - + - + {!isAcknowledged && !isResolved && acknowledgeState ? ( - { - return handleStateChange( - acknowledgeState._id, - acknowledgeState.name, - ); - }} - disabled={changingState} - accessibilityRole="button" - accessibilityLabel="Acknowledge incident" - > - {changingState ? ( - - ) : ( - <> - - - Acknowledge - - - )} - + + { + return handleStateChange( + acknowledgeState._id, + acknowledgeState.name, + ); + }} + disabled={changingState} + accessibilityRole="button" + accessibilityLabel="Acknowledge incident" + > + {changingState ? ( + + ) : ( + <> + + + Acknowledge + + + )} + + ) : null} {resolveState ? ( - { - return handleStateChange( - resolveState._id, - resolveState.name, - ); - }} - disabled={changingState} - accessibilityRole="button" - accessibilityLabel="Resolve incident" > - {changingState ? ( - - ) : ( - <> - - - Resolve - - - )} - + { + return handleStateChange( + resolveState._id, + resolveState.name, + ); + }} + disabled={changingState} + accessibilityRole="button" + accessibilityLabel="Resolve incident" + > + {changingState ? ( + + ) : ( + <> + + + Resolve + + + )} + + ) : null} @@ -503,7 +576,7 @@ export default function IncidentDetailScreen({ {/* Activity Feed */} {feed && feed.length > 0 ? ( - + diff --git a/MobileApp/src/screens/IncidentEpisodeDetailScreen.tsx b/MobileApp/src/screens/IncidentEpisodeDetailScreen.tsx index c62237bcd0..9ed151971c 100644 --- a/MobileApp/src/screens/IncidentEpisodeDetailScreen.tsx +++ b/MobileApp/src/screens/IncidentEpisodeDetailScreen.tsx @@ -155,8 +155,7 @@ export default function IncidentEpisodeDetailScreen({ if (isLoading) { return ( @@ -166,13 +165,14 @@ export default function IncidentEpisodeDetailScreen({ if (!episode) { return ( - + Episode not found. @@ -219,13 +219,15 @@ export default function IncidentEpisodeDetailScreen({ } > - + {episode.episodeNumberWithPrefix || `#${episode.episodeNumber}`} {episode.title} - + {episode.currentIncidentState ? ( {episode.currentIncidentState.name} @@ -277,12 +308,21 @@ export default function IncidentEpisodeDetailScreen({ ) : null} {episode.incidentSeverity ? ( {episode.incidentSeverity.name} @@ -293,19 +333,23 @@ export default function IncidentEpisodeDetailScreen({ {descriptionText ? ( - + {descriptionText} @@ -313,62 +357,78 @@ export default function IncidentEpisodeDetailScreen({ ) : null} - + - + - + {episode.declaredAt ? ( - + Declared {formatDateTime(episode.declaredAt)} ) : null} - + Created {formatDateTime(episode.createdAt)} - + Incidents {episode.incidentCount ?? 0} @@ -378,98 +438,113 @@ export default function IncidentEpisodeDetailScreen({ {!isResolved ? ( - + - + {!isAcknowledged && !isResolved && acknowledgeState ? ( - { - return handleStateChange( - acknowledgeState._id, - acknowledgeState.name, - ); - }} - disabled={changingState} - > - {changingState ? ( - - ) : ( - <> - - - Acknowledge - - - )} - + + { + return handleStateChange( + acknowledgeState._id, + acknowledgeState.name, + ); + }} + disabled={changingState} + > + {changingState ? ( + + ) : ( + <> + + + Acknowledge + + + )} + + ) : null} {resolveState ? ( - { - return handleStateChange( - resolveState._id, - resolveState.name, - ); - }} - disabled={changingState} > - {changingState ? ( - - ) : ( - <> - - - Resolve - - - )} - + { + return handleStateChange( + resolveState._id, + resolveState.name, + ); + }} + disabled={changingState} + > + {changingState ? ( + + ) : ( + <> + + + Resolve + + + )} + + ) : null} @@ -477,7 +552,7 @@ export default function IncidentEpisodeDetailScreen({ ) : null} {feed && feed.length > 0 ? ( - + diff --git a/MobileApp/src/screens/IncidentsScreen.tsx b/MobileApp/src/screens/IncidentsScreen.tsx index a0ff398fae..76f75c6304 100644 --- a/MobileApp/src/screens/IncidentsScreen.tsx +++ b/MobileApp/src/screens/IncidentsScreen.tsx @@ -63,8 +63,13 @@ function SectionHeader({ const { theme } = useTheme(); return ( - + @@ -330,8 +340,7 @@ export default function IncidentsScreen(): React.JSX.Element { }; return ( + - - - - + > + - + Live duty assignments @@ -204,16 +194,19 @@ export default function MyOnCallPoliciesScreen(): React.JSX.Element { {summaryText} @@ -233,8 +230,9 @@ export default function MyOnCallPoliciesScreen(): React.JSX.Element { {projects.length === 0 ? ( ) : ( - + {projects.map((projectData: ProjectOnCallAssignments) => { return ( - + {projectData.projectName} @@ -290,16 +299,21 @@ export default function MyOnCallPoliciesScreen(): React.JSX.Element { {projectData.assignments.length} active @@ -319,44 +333,53 @@ export default function MyOnCallPoliciesScreen(): React.JSX.Element { successBg: theme.colors.oncallActiveBg, info: theme.colors.severityInfo, infoBg: theme.colors.severityInfoBg, - warning: theme.colors.severityWarning, - warningBg: theme.colors.severityWarningBg, + purple: "#A855F7", + purpleBg: "rgba(168, 85, 247, 0.12)", }, ); return ( - { - return [ - { - paddingHorizontal: 16, - paddingVertical: 14, - opacity: pressed ? 0.82 : 1, - }, - assignmentIndex !== - projectData.assignments.length - 1 - ? { - borderBottomWidth: 1, - borderBottomColor: - theme.colors.borderSubtle, - } - : undefined, - ]; + - + {assignment.policyName} @@ -366,45 +389,66 @@ export default function MyOnCallPoliciesScreen(): React.JSX.Element { color={badge.color} /> {badge.label} - - + + Rule: {assignment.escalationRuleName} - + {assignment.assignmentDetail} - + ); }, )} diff --git a/MobileApp/src/screens/SettingsScreen.tsx b/MobileApp/src/screens/SettingsScreen.tsx index eba41406f0..2473299a53 100644 --- a/MobileApp/src/screens/SettingsScreen.tsx +++ b/MobileApp/src/screens/SettingsScreen.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import { View, Text, ScrollView, Switch, Pressable } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { LinearGradient } from "expo-linear-gradient"; -import { useTheme, ThemeMode } from "../theme"; +import { useTheme } from "../theme"; import { useAuth } from "../hooks/useAuth"; import { useBiometric } from "../hooks/useBiometric"; import { useHaptics } from "../hooks/useHaptics"; @@ -34,21 +34,30 @@ function SettingsRow({ const content: React.JSX.Element = ( - + {iconName ? ( ) : null} {rightElement ?? (value ? ( - + {value} ) : onPress ? ( @@ -111,26 +119,16 @@ function SettingsRow({ } export default function SettingsScreen(): React.JSX.Element { - const { theme, themeMode, setThemeMode } = useTheme(); + const { theme } = useTheme(); const { logout } = useAuth(); const biometric: ReturnType = useBiometric(); const { selectionFeedback } = useHaptics(); const [serverUrl, setServerUrlState] = useState(""); - const activeThemeOptionColor: string = theme.isDark - ? theme.colors.backgroundPrimary - : "#FFFFFF"; useEffect(() => { getServerUrl().then(setServerUrlState); }, []); - const handleThemeChange: (mode: ThemeMode) => void = ( - mode: ThemeMode, - ): void => { - selectionFeedback(); - setThemeMode(mode); - }; - const handleBiometricToggle: (value: boolean) => Promise = async ( value: boolean, ): Promise => { @@ -147,13 +145,16 @@ export default function SettingsScreen(): React.JSX.Element { > {/* Header */} - + - + Preferences - + {serverUrl || "oneuptime.com"} @@ -235,106 +259,26 @@ export default function SettingsScreen(): React.JSX.Element { - {/* Appearance */} - - - Appearance - - - - - {(["dark", "light", "system"] as ThemeMode[]).map( - (mode: ThemeMode) => { - const isActive: boolean = themeMode === mode; - return ( - { - return [ - { - flex: 1, - flexDirection: "row" as const, - alignItems: "center" as const, - justifyContent: "center" as const, - paddingVertical: 10, - borderRadius: 10, - gap: 6, - overflow: "hidden" as const, - opacity: pressed ? 0.7 : 1, - }, - isActive - ? { - backgroundColor: theme.colors.actionPrimary, - shadowColor: theme.colors.actionPrimary, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - shadowRadius: 6, - elevation: 3, - } - : undefined, - ]; - }} - onPress={() => { - return handleThemeChange(mode); - }} - > - - - {mode.charAt(0).toUpperCase() + mode.slice(1)} - - - ); - }, - )} - - - - - {/* Security */} {biometric.isAvailable ? ( - + Security Require biometrics to unlock the app @@ -367,16 +316,24 @@ export default function SettingsScreen(): React.JSX.Element { ) : null} {/* Server */} - + Server {/* Account */} - + Account {/* About */} - + About {/* Footer */} - + - - + + Thank you for supporting open source software. Built and maintained by contributors around the world. - + - + Licensed under Apache 2.0 diff --git a/MobileApp/src/screens/auth/LoginScreen.tsx b/MobileApp/src/screens/auth/LoginScreen.tsx index f64366552b..f58bd8dd2b 100644 --- a/MobileApp/src/screens/auth/LoginScreen.tsx +++ b/MobileApp/src/screens/auth/LoginScreen.tsx @@ -74,28 +74,33 @@ export default function LoginScreen(): React.JSX.Element { return ( - - + + - + Sign in to continue {serverUrl ? ( {serverUrl} @@ -128,14 +138,22 @@ export default function LoginScreen(): React.JSX.Element { Email { setEmail(text); @@ -178,14 +199,23 @@ export default function LoginScreen(): React.JSX.Element { Password { setPassword(text); @@ -227,7 +260,13 @@ export default function LoginScreen(): React.JSX.Element { {error ? ( - + {error} ) : null} - + - + - - + + - + Connect to your OneUptime instance @@ -103,14 +113,22 @@ export default function ServerUrlScreen(): React.JSX.Element { Server URL { setUrl(text); @@ -155,7 +176,13 @@ export default function ServerUrlScreen(): React.JSX.Element { {error ? ( - + {error} ) : null} - + Self-hosting? Enter your OneUptime server URL above. diff --git a/MobileApp/src/storage/preferences.ts b/MobileApp/src/storage/preferences.ts index ecd9210824..6ae2fe6779 100644 --- a/MobileApp/src/storage/preferences.ts +++ b/MobileApp/src/storage/preferences.ts @@ -1,26 +1,11 @@ import AsyncStorage from "@react-native-async-storage/async-storage"; -import type { ThemeMode } from "../theme"; const KEYS: { - readonly THEME_MODE: "oneuptime_theme_mode"; readonly BIOMETRIC_ENABLED: "oneuptime_biometric_enabled"; } = { - THEME_MODE: "oneuptime_theme_mode", BIOMETRIC_ENABLED: "oneuptime_biometric_enabled", } as const; -export async function getThemeMode(): Promise { - const stored: string | null = await AsyncStorage.getItem(KEYS.THEME_MODE); - if (stored === "dark" || stored === "light" || stored === "system") { - return stored; - } - return "dark"; -} - -export async function setThemeMode(mode: ThemeMode): Promise { - await AsyncStorage.setItem(KEYS.THEME_MODE, mode); -} - export async function getBiometricEnabled(): Promise { const stored: string | null = await AsyncStorage.getItem( KEYS.BIOMETRIC_ENABLED, diff --git a/MobileApp/src/theme/ThemeContext.tsx b/MobileApp/src/theme/ThemeContext.tsx index 1192b15dfe..5f8c20cf4c 100644 --- a/MobileApp/src/theme/ThemeContext.tsx +++ b/MobileApp/src/theme/ThemeContext.tsx @@ -1,33 +1,19 @@ -import React, { - createContext, - useContext, - useState, - useEffect, - useMemo, - ReactNode, -} from "react"; -import { View, useColorScheme } from "react-native"; -import { ColorTokens, darkColors, lightColors } from "./colors"; -import { - getThemeMode as loadThemeMode, - setThemeMode as saveThemeMode, -} from "../storage/preferences"; - -export type ThemeMode = "dark" | "light" | "system"; +import React, { createContext, useContext, ReactNode } from "react"; +import { View } from "react-native"; +import { ColorTokens, darkColors } from "./colors"; export interface Theme { colors: ColorTokens; - isDark: boolean; } interface ThemeContextValue { theme: Theme; - themeMode: ThemeMode; - setThemeMode: (mode: ThemeMode) => void; } -const ThemeContext: React.Context = - createContext(undefined); +const theme: Theme = { colors: darkColors }; + +const ThemeContext: React.Context = + createContext({ theme }); interface ThemeProviderProps { children: ReactNode; @@ -36,56 +22,13 @@ interface ThemeProviderProps { export function ThemeProvider({ children, }: ThemeProviderProps): React.JSX.Element { - const systemColorScheme: "light" | "dark" | null | undefined = - useColorScheme(); - const [themeMode, setThemeModeState] = useState("light"); - - // Load persisted theme on mount - useEffect(() => { - loadThemeMode().then((mode: ThemeMode) => { - setThemeModeState(mode); - }); - }, []); - - const setThemeMode: (mode: ThemeMode) => void = (mode: ThemeMode): void => { - setThemeModeState(mode); - saveThemeMode(mode); - }; - - const theme: Theme = useMemo((): Theme => { - let isDark: boolean; - - if (themeMode === "system") { - isDark = systemColorScheme !== "light"; - } else { - isDark = themeMode === "dark"; - } - - return { - colors: isDark ? darkColors : lightColors, - isDark, - }; - }, [themeMode, systemColorScheme]); - - const value: ThemeContextValue = useMemo((): ThemeContextValue => { - return { - theme, - themeMode, - setThemeMode, - }; - }, [theme, themeMode]); - return ( - + {children} ); } export function useTheme(): ThemeContextValue { - const context: ThemeContextValue | undefined = useContext(ThemeContext); - if (!context) { - throw new Error("useTheme must be used within a ThemeProvider"); - } - return context; + return useContext(ThemeContext); } diff --git a/MobileApp/src/theme/colors.ts b/MobileApp/src/theme/colors.ts index 8c5851df2f..6907b0e9e9 100644 --- a/MobileApp/src/theme/colors.ts +++ b/MobileApp/src/theme/colors.ts @@ -141,75 +141,3 @@ export const darkColors: ColorTokens = { statusError: "#EF4444", statusErrorBg: "rgba(239, 68, 68, 0.12)", }; - -export const lightColors: ColorTokens = { - // Background — clean white with warm gray tones - backgroundPrimary: "#FFFFFF", - backgroundSecondary: "#F9FAFB", - backgroundTertiary: "#F3F4F6", - backgroundElevated: "#FFFFFF", - - // Accent - cardAccent: "rgba(0, 0, 0, 0.02)", - backgroundGlass: "rgba(255, 255, 255, 0.80)", - iconBackground: "rgba(0, 0, 0, 0.05)", - - // Gradient — neutral monochrome accent - accentGradientStart: "#52525B", - accentGradientMid: "#3F3F46", - accentGradientEnd: "#27272A", - accentCyan: "#52525B", - accentCyanBg: "rgba(82, 82, 91, 0.08)", - surfaceGlow: "rgba(0, 0, 0, 0.04)", - headerGradient: "rgba(0, 0, 0, 0.03)", - gradientStart: "rgba(0, 0, 0, 0.04)", - gradientEnd: "transparent", - - // Border - borderDefault: "#E5E7EB", - borderSubtle: "#F3F4F6", - borderGlass: "rgba(0, 0, 0, 0.05)", - - // Text - textPrimary: "#111827", - textSecondary: "#6B7280", - textTertiary: "#9CA3AF", - textInverse: "#FFFFFF", - - // Severity - severityCritical: "#DC2626", - severityCriticalBg: "rgba(220, 38, 38, 0.08)", - severityMajor: "#EA580C", - severityMajorBg: "rgba(234, 88, 12, 0.08)", - severityMinor: "#CA8A04", - severityMinorBg: "rgba(202, 138, 4, 0.08)", - severityWarning: "#D97706", - severityWarningBg: "rgba(217, 119, 6, 0.08)", - severityInfo: "#2563EB", - severityInfoBg: "rgba(37, 99, 235, 0.08)", - - // State - stateCreated: "#DC2626", - stateAcknowledged: "#D97706", - stateResolved: "#16A34A", - stateInvestigating: "#EA580C", - stateMuted: "#9CA3AF", - - // On-Call - oncallActive: "#16A34A", - oncallActiveBg: "rgba(22, 163, 74, 0.08)", - oncallInactive: "#9CA3AF", - oncallInactiveBg: "rgba(156, 163, 175, 0.08)", - - // Action — neutral accent - actionPrimary: "#27272A", - actionPrimaryPressed: "#3F3F46", - actionDestructive: "#DC2626", - actionDestructivePressed: "#B91C1C", - - // Status - statusSuccess: "#16A34A", - statusSuccessBg: "rgba(22, 163, 74, 0.08)", - statusError: "#DC2626", - statusErrorBg: "rgba(220, 38, 38, 0.08)", -}; diff --git a/MobileApp/src/theme/index.ts b/MobileApp/src/theme/index.ts index 1604d23a9d..2784bd5d58 100644 --- a/MobileApp/src/theme/index.ts +++ b/MobileApp/src/theme/index.ts @@ -1,4 +1,4 @@ -export { darkColors, lightColors } from "./colors"; +export { darkColors } from "./colors"; export type { ColorTokens } from "./colors"; export { ThemeProvider, useTheme } from "./ThemeContext"; -export type { Theme, ThemeMode } from "./ThemeContext"; +export type { Theme } from "./ThemeContext"; diff --git a/MobileApp/src/utils/logger.ts b/MobileApp/src/utils/logger.ts new file mode 100644 index 0000000000..1a973956f1 --- /dev/null +++ b/MobileApp/src/utils/logger.ts @@ -0,0 +1,19 @@ +/* eslint-disable no-console */ + +const logger: { + info: (...args: unknown[]) => void; + warn: (...args: unknown[]) => void; + error: (...args: unknown[]) => void; +} = { + info: (...args: unknown[]): void => { + console.info(...args); + }, + warn: (...args: unknown[]): void => { + console.warn(...args); + }, + error: (...args: unknown[]): void => { + console.error(...args); + }, +}; + +export default logger; diff --git a/Nginx/Dockerfile.tpl b/Nginx/Dockerfile.tpl index e1aa0ace7c..1884343f05 100644 --- a/Nginx/Dockerfile.tpl +++ b/Nginx/Dockerfile.tpl @@ -1,4 +1,4 @@ -FROM nginx:1.29.3-alpine +FROM nginx:1.29.5-alpine ARG GIT_SHA diff --git a/Probe/Services/Register.ts b/Probe/Services/Register.ts index fa25b40fbd..56de930094 100644 --- a/Probe/Services/Register.ts +++ b/Probe/Services/Register.ts @@ -15,10 +15,12 @@ import { JSONObject } from "Common/Types/JSON"; import ProbeStatusReport from "Common/Types/Probe/ProbeStatusReport"; import Sleep from "Common/Types/Sleep"; import API from "Common/Utils/API"; -import { HasClusterKey } from "Common/Server/EnvironmentConfig"; +import { + HasRegisterProbeKey, + RegisterProbeKey, +} from "Common/Server/EnvironmentConfig"; import LocalCache from "Common/Server/Infrastructure/LocalCache"; import logger from "Common/Server/Utils/Logger"; -import ClusterKeyAuthorization from "Common/Server/Middleware/ClusterKeyAuthorization"; import ProxyConfig from "../Utils/ProxyConfig"; export default class Register { @@ -117,7 +119,7 @@ export default class Register { } private static async _registerProbe(): Promise { - if (HasClusterKey) { + if (HasRegisterProbeKey) { const probeRegistrationUrl: URL = URL.fromString( PROBE_INGEST_URL.toString(), ).addRoute("/register"); @@ -131,7 +133,7 @@ export default class Register { probeKey: PROBE_KEY, probeName: PROBE_NAME, probeDescription: PROBE_DESCRIPTION, - clusterKey: ClusterKeyAuthorization.getClusterKey(), + registerProbeKey: RegisterProbeKey.toString(), }, options: { ...ProxyConfig.getRequestProxyAgents(probeRegistrationUrl), @@ -149,7 +151,7 @@ export default class Register { } else { // validate probe. if (!PROBE_ID) { - logger.error("PROBE_ID or ONEUPTIME_SECRET should be set"); + logger.error("PROBE_ID or REGISTER_PROBE_KEY should be set"); return process.exit(); } diff --git a/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts index a85629fc50..0cc9f5a801 100644 --- a/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts +++ b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts @@ -1,16 +1,12 @@ import { PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS } from "../../../Config"; import ProxyConfig from "../../ProxyConfig"; -import BadDataException from "Common/Types/Exception/BadDataException"; -import ReturnResult from "Common/Types/IsolatedVM/ReturnResult"; import BrowserType from "Common/Types/Monitor/SyntheticMonitors/BrowserType"; import ScreenSizeType from "Common/Types/Monitor/SyntheticMonitors/ScreenSizeType"; import SyntheticMonitorResponse from "Common/Types/Monitor/SyntheticMonitors/SyntheticMonitorResponse"; import ObjectID from "Common/Types/ObjectID"; import logger from "Common/Server/Utils/Logger"; -import VMRunner from "Common/Server/Utils/VM/VMRunner"; -import { Browser, BrowserContext, Page, chromium, firefox } from "playwright"; -import LocalFile from "Common/Server/Utils/LocalFile"; -import os from "os"; +import { ChildProcess, fork } from "child_process"; +import path from "path"; export interface SyntheticMonitorOptions { monitorId?: ObjectID | undefined; @@ -20,24 +16,26 @@ export interface SyntheticMonitorOptions { retryCountOnError?: number | undefined; } -interface BrowserLaunchOptions { - executablePath?: string; - proxy?: { - server: string; - username?: string; - password?: string; - bypass?: string; - }; - args?: string[]; - headless?: boolean; - devtools?: boolean; - timeout?: number; +interface WorkerConfig { + script: string; + browserType: BrowserType; + screenSizeType: ScreenSizeType; + timeout: number; + proxy?: + | { + server: string; + username?: string | undefined; + password?: string | undefined; + } + | undefined; } -interface BrowserSession { - browser: Browser; - context: BrowserContext; - page: Page; +interface WorkerResult { + logMessages: string[]; + scriptError?: string | undefined; + result?: unknown | undefined; + screenshots: Record; + executionTimeInMS: number; } export default class SyntheticMonitor { @@ -111,13 +109,72 @@ export default class SyntheticMonitor { return result; } + private static getSanitizedEnv(): Record { + /* + * Only pass safe environment variables to the worker process. + * Explicitly exclude all secrets (DATABASE_PASSWORD, REDIS_PASSWORD, + * CLICKHOUSE_PASSWORD, ONEUPTIME_SECRET, ENCRYPTION_SECRET, BILLING_PRIVATE_KEY, etc.) + */ + const safeKeys: string[] = [ + "PATH", + "HOME", + "NODE_ENV", + "PLAYWRIGHT_BROWSERS_PATH", + "HTTP_PROXY_URL", + "http_proxy", + "HTTPS_PROXY_URL", + "https_proxy", + "NO_PROXY", + "no_proxy", + ]; + + const env: Record = {}; + + for (const key of safeKeys) { + if (process.env[key]) { + env[key] = process.env[key]!; + } + } + + return env; + } + + private static getProxyConfig(): WorkerConfig["proxy"] | undefined { + if (!ProxyConfig.isProxyConfigured()) { + return undefined; + } + + const httpsProxyUrl: string | null = ProxyConfig.getHttpsProxyUrl(); + const httpProxyUrl: string | null = ProxyConfig.getHttpProxyUrl(); + const proxyUrl: string | null = httpsProxyUrl || httpProxyUrl; + + if (!proxyUrl) { + return undefined; + } + + const proxyConfig: WorkerConfig["proxy"] = { + server: proxyUrl, + }; + + try { + const parsedUrl: globalThis.URL = new URL(proxyUrl); + if (parsedUrl.username && parsedUrl.password) { + proxyConfig.username = parsedUrl.username; + proxyConfig.password = parsedUrl.password; + } + } catch (error) { + logger.warn(`Failed to parse proxy URL for authentication: ${error}`); + } + + return proxyConfig; + } + private static async executeByBrowserAndScreenSize(options: { script: string; browserType: BrowserType; screenSizeType: ScreenSizeType; }): Promise { if (!options) { - // this should never happen options = { script: "", browserType: BrowserType.Chromium, @@ -135,385 +192,124 @@ export default class SyntheticMonitor { screenSizeType: options.screenSizeType, }; - let browserSession: BrowserSession | null = null; + const timeout: number = PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS; + + const workerConfig: WorkerConfig = { + script: options.script, + browserType: options.browserType, + screenSizeType: options.screenSizeType, + timeout: timeout, + proxy: this.getProxyConfig(), + }; try { - let result: ReturnResult | null = null; - - const startTime: [number, number] = process.hrtime(); - - browserSession = await SyntheticMonitor.getPageByBrowserType({ - browserType: options.browserType, - screenSizeType: options.screenSizeType, - }); - - if (!browserSession) { - throw new BadDataException( - "Could not create Playwright browser session", - ); - } - - result = await VMRunner.runCodeInSandbox({ - code: options.script, - options: { - timeout: PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS, - args: {}, - context: { - browser: browserSession.browser, - page: browserSession.page, - screenSizeType: options.screenSizeType, - browserType: options.browserType, - }, - }, - }); - - const endTime: [number, number] = process.hrtime(startTime); - - const executionTimeInMS: number = Math.ceil( - (endTime[0] * 1000000000 + endTime[1]) / 1000000, + const workerResult: WorkerResult = await this.forkWorker( + workerConfig, + timeout, ); - scriptResult.executionTimeInMS = executionTimeInMS; - - scriptResult.logMessages = result.logMessages; - - if (result.returnValue?.screenshots) { - if (!scriptResult.screenshots) { - scriptResult.screenshots = {}; - } - - for (const screenshotName in result.returnValue.screenshots) { - if (!result.returnValue.screenshots[screenshotName]) { - continue; - } - - // check if this is of type Buffer. If it is not, continue. - - if ( - !(result.returnValue.screenshots[screenshotName] instanceof Buffer) - ) { - continue; - } - - const screenshotBuffer: Buffer = result.returnValue.screenshots[ - screenshotName - ] as Buffer; - scriptResult.screenshots[screenshotName] = - screenshotBuffer.toString("base64"); // convert screenshots to base 64 - } - } - - scriptResult.result = result?.returnValue?.data; + scriptResult.logMessages = workerResult.logMessages; + scriptResult.scriptError = workerResult.scriptError; + scriptResult.result = workerResult.result as typeof scriptResult.result; + scriptResult.screenshots = workerResult.screenshots; + scriptResult.executionTimeInMS = workerResult.executionTimeInMS; } catch (err: unknown) { logger.error(err); scriptResult.scriptError = (err as Error)?.message || (err as Error).toString(); - } finally { - // Always dispose browser session to prevent zombie processes - await SyntheticMonitor.disposeBrowserSession(browserSession); } return scriptResult; } - private static getViewportHeightAndWidth(options: { - screenSizeType: ScreenSizeType; - }): { - height: number; - width: number; - } { - let viewPortHeight: number = 0; - let viewPortWidth: number = 0; - - switch (options.screenSizeType) { - case ScreenSizeType.Desktop: - viewPortHeight = 1080; - viewPortWidth = 1920; - break; - case ScreenSizeType.Mobile: - viewPortHeight = 640; - viewPortWidth = 360; - break; - case ScreenSizeType.Tablet: - viewPortHeight = 768; - viewPortWidth = 1024; - break; - default: - viewPortHeight = 1080; - viewPortWidth = 1920; - break; - } - - return { height: viewPortHeight, width: viewPortWidth }; - } - - private static getPlaywrightBrowsersPath(): string { - return ( - process.env["PLAYWRIGHT_BROWSERS_PATH"] || - `${os.homedir()}/.cache/ms-playwright` - ); - } - - public static async getChromeExecutablePath(): Promise { - const browsersPath: string = this.getPlaywrightBrowsersPath(); - - const doesDirectoryExist: boolean = - await LocalFile.doesDirectoryExist(browsersPath); - if (!doesDirectoryExist) { - throw new BadDataException("Chrome executable path not found."); - } - - // get list of files in the directory - const directories: string[] = - await LocalFile.getListOfDirectories(browsersPath); - - if (directories.length === 0) { - throw new BadDataException("Chrome executable path not found."); - } - - const chromeInstallationName: string | undefined = directories.find( - (directory: string) => { - return directory.includes("chromium"); - }, - ); - - if (!chromeInstallationName) { - throw new BadDataException("Chrome executable path not found."); - } - - const chromeExecutableCandidates: Array = [ - `${browsersPath}/${chromeInstallationName}/chrome-linux/chrome`, - `${browsersPath}/${chromeInstallationName}/chrome-linux64/chrome`, - `${browsersPath}/${chromeInstallationName}/chrome64/chrome`, - `${browsersPath}/${chromeInstallationName}/chrome/chrome`, - ]; - - for (const executablePath of chromeExecutableCandidates) { - if (await LocalFile.doesFileExist(executablePath)) { - return executablePath; - } - } - - throw new BadDataException("Chrome executable path not found."); - } - - public static async getFirefoxExecutablePath(): Promise { - const browsersPath: string = this.getPlaywrightBrowsersPath(); - - const doesDirectoryExist: boolean = - await LocalFile.doesDirectoryExist(browsersPath); - if (!doesDirectoryExist) { - throw new BadDataException("Firefox executable path not found."); - } - - // get list of files in the directory - const directories: string[] = - await LocalFile.getListOfDirectories(browsersPath); - - if (directories.length === 0) { - throw new BadDataException("Firefox executable path not found."); - } - - const firefoxInstallationName: string | undefined = directories.find( - (directory: string) => { - return directory.includes("firefox"); - }, - ); - - if (!firefoxInstallationName) { - throw new BadDataException("Firefox executable path not found."); - } - - const firefoxExecutableCandidates: Array = [ - `${browsersPath}/${firefoxInstallationName}/firefox/firefox`, - `${browsersPath}/${firefoxInstallationName}/firefox-linux64/firefox`, - `${browsersPath}/${firefoxInstallationName}/firefox64/firefox`, - `${browsersPath}/${firefoxInstallationName}/firefox-64/firefox`, - ]; - - for (const executablePath of firefoxExecutableCandidates) { - if (await LocalFile.doesFileExist(executablePath)) { - return executablePath; - } - } - - throw new BadDataException("Firefox executable path not found."); - } - - private static async getPageByBrowserType(data: { - browserType: BrowserType; - screenSizeType: ScreenSizeType; - }): Promise { - const viewport: { - height: number; - width: number; - } = SyntheticMonitor.getViewportHeightAndWidth({ - screenSizeType: data.screenSizeType, - }); - - // Prepare browser launch options with proxy support - const baseOptions: BrowserLaunchOptions = {}; - - // Configure proxy if available - if (ProxyConfig.isProxyConfigured()) { - const httpsProxyUrl: string | null = ProxyConfig.getHttpsProxyUrl(); - const httpProxyUrl: string | null = ProxyConfig.getHttpProxyUrl(); - - // Prefer HTTPS proxy, fall back to HTTP proxy - const proxyUrl: string | null = httpsProxyUrl || httpProxyUrl; - - if (proxyUrl) { - baseOptions.proxy = { - server: proxyUrl, - }; - - // Extract username and password if present in proxy URL - try { - const parsedUrl: globalThis.URL = new URL(proxyUrl); - if (parsedUrl.username && parsedUrl.password) { - baseOptions.proxy.username = parsedUrl.username; - baseOptions.proxy.password = parsedUrl.password; - } - } catch (error) { - logger.warn(`Failed to parse proxy URL for authentication: ${error}`); - } - - logger.debug( - `Synthetic Monitor using proxy: ${proxyUrl} (HTTPS: ${Boolean(httpsProxyUrl)}, HTTP: ${Boolean(httpProxyUrl)})`, + private static async forkWorker( + config: WorkerConfig, + timeout: number, + ): Promise { + return new Promise( + ( + resolve: (value: WorkerResult) => void, + reject: (reason: Error) => void, + ) => { + const workerPath: string = path.resolve( + __dirname, + "SyntheticMonitorWorker", ); - } - } - if (data.browserType === BrowserType.Chromium) { - const browser: Browser = await chromium.launch({ - executablePath: await this.getChromeExecutablePath(), - ...baseOptions, - }); - - const context: BrowserContext = await browser.newContext({ - viewport: { - width: viewport.width, - height: viewport.height, - }, - }); - - const page: Page = await context.newPage(); - - return { - browser, - context, - page, - }; - } - - if (data.browserType === BrowserType.Firefox) { - const browser: Browser = await firefox.launch({ - executablePath: await this.getFirefoxExecutablePath(), - ...baseOptions, - }); - - let context: BrowserContext | null = null; - - try { - context = await browser.newContext({ - viewport: { - width: viewport.width, - height: viewport.height, - }, + const child: ChildProcess = fork(workerPath, [], { + env: this.getSanitizedEnv(), + timeout: timeout + 30000, // fork-level timeout: script timeout + 30s for browser startup/shutdown + stdio: ["pipe", "pipe", "pipe", "ipc"], }); - const page: Page = await context.newPage(); + let resolved: boolean = false; + let stderrOutput: string = ""; - return { - browser, - context, - page, - }; - } catch (error) { - await SyntheticMonitor.safeCloseBrowserContext(context); - await SyntheticMonitor.safeCloseBrowser(browser); - throw error; - } - } + // Capture child stderr for debugging worker crashes + if (child.stderr) { + child.stderr.on("data", (data: Buffer) => { + stderrOutput += data.toString(); + }); + } - throw new BadDataException("Invalid Browser Type."); - } + // Explicit kill timer as final safety net + const killTimer: ReturnType = global.setTimeout( + () => { + if (!resolved) { + resolved = true; + child.kill("SIGKILL"); + reject( + new Error("Synthetic monitor worker killed after timeout"), + ); + } + }, + timeout + 60000, // kill after script timeout + 60s + ); - private static async disposeBrowserSession( - session: BrowserSession | null, - ): Promise { - if (!session) { - return; - } + child.on("message", (result: WorkerResult) => { + if (!resolved) { + resolved = true; + global.clearTimeout(killTimer); + resolve(result); + } + }); - await SyntheticMonitor.safeClosePage(session.page); - await SyntheticMonitor.safeCloseBrowserContexts({ - browser: session.browser, - }); - await SyntheticMonitor.safeCloseBrowser(session.browser); - } + child.on("error", (err: Error) => { + if (!resolved) { + resolved = true; + global.clearTimeout(killTimer); + reject(err); + } + }); - private static async safeClosePage(page?: Page | null): Promise { - if (!page) { - return; - } + child.on("exit", (exitCode: number | null) => { + if (!resolved) { + resolved = true; + global.clearTimeout(killTimer); - try { - if (!page.isClosed()) { - await page.close(); - } - } catch (error) { - logger.warn( - `Failed to close Playwright page: ${(error as Error)?.message || error}`, - ); - } - } + const stderrInfo: string = stderrOutput.trim() + ? `: ${stderrOutput.trim().substring(0, 500)}` + : ""; - private static async safeCloseBrowserContext( - context?: BrowserContext | null, - ): Promise { - if (!context) { - return; - } + if (exitCode !== 0) { + reject( + new Error( + `Synthetic monitor worker exited with code ${exitCode}${stderrInfo}`, + ), + ); + } else { + reject( + new Error( + `Synthetic monitor worker exited without sending results${stderrInfo}`, + ), + ); + } + } + }); - try { - await context.close(); - } catch (error) { - logger.warn( - `Failed to close Playwright browser context: ${(error as Error)?.message || error}`, - ); - } - } - - private static async safeCloseBrowser( - browser?: Browser | null, - ): Promise { - if (!browser) { - return; - } - - try { - if (browser.isConnected()) { - await browser.close(); - } - } catch (error) { - logger.warn( - `Failed to close Playwright browser: ${(error as Error)?.message || error}`, - ); - } - } - - private static async safeCloseBrowserContexts(data: { - browser: Browser; - }): Promise { - if (!data.browser || !data.browser.contexts) { - return; - } - - const contexts: Array = data.browser.contexts(); - - for (const context of contexts) { - await SyntheticMonitor.safeCloseBrowserContext(context); - } + // Send config to worker via IPC + child.send(config); + }, + ); } } diff --git a/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitorWorker.ts b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitorWorker.ts new file mode 100644 index 0000000000..a4d3e339be --- /dev/null +++ b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitorWorker.ts @@ -0,0 +1,354 @@ +/* + * This script is executed via child_process.fork() with a sanitized environment + * It launches Playwright, runs user code with node:vm (safe because env is stripped), + * and sends results back via IPC. + */ + +import BrowserType from "Common/Types/Monitor/SyntheticMonitors/BrowserType"; +import ScreenSizeType from "Common/Types/Monitor/SyntheticMonitors/ScreenSizeType"; +import vm, { Context } from "node:vm"; +import { Browser, BrowserContext, Page, chromium, firefox } from "playwright"; +import LocalFile from "Common/Server/Utils/LocalFile"; +import os from "os"; + +interface WorkerConfig { + script: string; + browserType: BrowserType; + screenSizeType: ScreenSizeType; + timeout: number; + proxy?: + | { + server: string; + username?: string | undefined; + password?: string | undefined; + } + | undefined; +} + +interface WorkerResult { + logMessages: string[]; + scriptError?: string | undefined; + result?: unknown | undefined; + screenshots: Record; + executionTimeInMS: number; +} + +interface ProxyOptions { + server: string; + username?: string | undefined; + password?: string | undefined; +} + +function getViewportHeightAndWidth(screenSizeType: ScreenSizeType): { + height: number; + width: number; +} { + switch (screenSizeType) { + case ScreenSizeType.Desktop: + return { height: 1080, width: 1920 }; + case ScreenSizeType.Mobile: + return { height: 640, width: 360 }; + case ScreenSizeType.Tablet: + return { height: 768, width: 1024 }; + default: + return { height: 1080, width: 1920 }; + } +} + +function getPlaywrightBrowsersPath(): string { + return ( + process.env["PLAYWRIGHT_BROWSERS_PATH"] || + `${os.homedir()}/.cache/ms-playwright` + ); +} + +async function getChromeExecutablePath(): Promise { + const browsersPath: string = getPlaywrightBrowsersPath(); + + const doesDirectoryExist: boolean = + await LocalFile.doesDirectoryExist(browsersPath); + if (!doesDirectoryExist) { + throw new Error("Chrome executable path not found."); + } + + const directories: string[] = + await LocalFile.getListOfDirectories(browsersPath); + + if (directories.length === 0) { + throw new Error("Chrome executable path not found."); + } + + const chromeInstallationName: string | undefined = directories.find( + (directory: string) => { + return directory.includes("chromium"); + }, + ); + + if (!chromeInstallationName) { + throw new Error("Chrome executable path not found."); + } + + const candidates: Array = [ + `${browsersPath}/${chromeInstallationName}/chrome-linux/chrome`, + `${browsersPath}/${chromeInstallationName}/chrome-linux64/chrome`, + `${browsersPath}/${chromeInstallationName}/chrome64/chrome`, + `${browsersPath}/${chromeInstallationName}/chrome/chrome`, + ]; + + for (const executablePath of candidates) { + if (await LocalFile.doesFileExist(executablePath)) { + return executablePath; + } + } + + throw new Error("Chrome executable path not found."); +} + +async function getFirefoxExecutablePath(): Promise { + const browsersPath: string = getPlaywrightBrowsersPath(); + + const doesDirectoryExist: boolean = + await LocalFile.doesDirectoryExist(browsersPath); + if (!doesDirectoryExist) { + throw new Error("Firefox executable path not found."); + } + + const directories: string[] = + await LocalFile.getListOfDirectories(browsersPath); + + if (directories.length === 0) { + throw new Error("Firefox executable path not found."); + } + + const firefoxInstallationName: string | undefined = directories.find( + (directory: string) => { + return directory.includes("firefox"); + }, + ); + + if (!firefoxInstallationName) { + throw new Error("Firefox executable path not found."); + } + + const candidates: Array = [ + `${browsersPath}/${firefoxInstallationName}/firefox/firefox`, + `${browsersPath}/${firefoxInstallationName}/firefox-linux64/firefox`, + `${browsersPath}/${firefoxInstallationName}/firefox64/firefox`, + `${browsersPath}/${firefoxInstallationName}/firefox-64/firefox`, + ]; + + for (const executablePath of candidates) { + if (await LocalFile.doesFileExist(executablePath)) { + return executablePath; + } + } + + throw new Error("Firefox executable path not found."); +} + +async function launchBrowser( + config: WorkerConfig, +): Promise<{ browser: Browser; context: BrowserContext; page: Page }> { + const viewport: { height: number; width: number } = getViewportHeightAndWidth( + config.screenSizeType, + ); + + let proxyOptions: ProxyOptions | undefined; + + if (config.proxy) { + proxyOptions = { + server: config.proxy.server, + }; + + if (config.proxy.username && config.proxy.password) { + proxyOptions.username = config.proxy.username; + proxyOptions.password = config.proxy.password; + } + } + + let browser: Browser; + + if (config.browserType === BrowserType.Chromium) { + const launchOptions: Record = { + executablePath: await getChromeExecutablePath(), + }; + + if (proxyOptions) { + launchOptions["proxy"] = proxyOptions; + } + + browser = await chromium.launch(launchOptions); + } else if (config.browserType === BrowserType.Firefox) { + const launchOptions: Record = { + executablePath: await getFirefoxExecutablePath(), + }; + + if (proxyOptions) { + launchOptions["proxy"] = proxyOptions; + } + + browser = await firefox.launch(launchOptions); + } else { + throw new Error("Invalid Browser Type."); + } + + const context: BrowserContext = await browser.newContext({ + viewport: { + width: viewport.width, + height: viewport.height, + }, + }); + + const page: Page = await context.newPage(); + + return { browser, context, page }; +} + +async function run(config: WorkerConfig): Promise { + const workerResult: WorkerResult = { + logMessages: [], + scriptError: undefined, + result: undefined, + screenshots: {}, + executionTimeInMS: 0, + }; + + let browser: Browser | null = null; + + try { + const startTime: [number, number] = process.hrtime(); + + const session: { browser: Browser; context: BrowserContext; page: Page } = + await launchBrowser(config); + + browser = session.browser; + + const logMessages: string[] = []; + + const sandbox: Context = { + console: { + log: (...args: unknown[]) => { + logMessages.push( + args + .map((v: unknown) => { + return typeof v === "object" ? JSON.stringify(v) : String(v); + }) + .join(" "), + ); + }, + }, + browser: session.browser, + page: session.page, + screenSizeType: config.screenSizeType, + browserType: config.browserType, + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + }; + + vm.createContext(sandbox); + + const script: string = `(async()=>{ + ${config.script} + })()`; + + const returnVal: unknown = await vm.runInContext(script, sandbox, { + timeout: config.timeout, + }); + + const endTime: [number, number] = process.hrtime(startTime); + const executionTimeInMS: number = Math.ceil( + (endTime[0] * 1000000000 + endTime[1]) / 1000000, + ); + + workerResult.executionTimeInMS = executionTimeInMS; + workerResult.logMessages = logMessages; + + // Convert screenshots from Buffer to base64 + const returnObj: Record = + returnVal && typeof returnVal === "object" + ? (returnVal as Record) + : {}; + + if (returnObj["screenshots"]) { + const screenshots: Record = returnObj[ + "screenshots" + ] as Record; + + for (const screenshotName in screenshots) { + if (!screenshots[screenshotName]) { + continue; + } + + if (!(screenshots[screenshotName] instanceof Buffer)) { + continue; + } + + const screenshotBuffer: Buffer = screenshots[screenshotName] as Buffer; + workerResult.screenshots[screenshotName] = + screenshotBuffer.toString("base64"); + } + } + + workerResult.result = returnObj["data"]; + } catch (err: unknown) { + workerResult.scriptError = (err as Error)?.message || String(err); + } finally { + // Close browser + if (browser) { + try { + const contexts: Array = browser.contexts(); + for (const ctx of contexts) { + try { + await ctx.close(); + } catch { + // ignore + } + } + if (browser.isConnected()) { + await browser.close(); + } + } catch { + // ignore cleanup errors + } + } + } + + return workerResult; +} + +// Entry point: receive config via IPC message +process.on("message", (config: WorkerConfig) => { + run(config) + .then((result: WorkerResult) => { + if (process.send) { + /* + * Wait for the IPC message to be flushed before exiting. + * process.send() is async — calling process.exit() immediately + * can kill the process before the message is delivered. + */ + process.send(result, () => { + process.exit(0); + }); + } else { + process.exit(0); + } + }) + .catch((err: unknown) => { + const errorResult: WorkerResult = { + logMessages: [], + scriptError: (err as Error)?.message || String(err), + result: undefined, + screenshots: {}, + executionTimeInMS: 0, + }; + + if (process.send) { + process.send(errorResult, () => { + process.exit(1); + }); + } else { + process.exit(1); + } + }); +}); diff --git a/Probe/package.json b/Probe/package.json index ab7693db05..765f670ab6 100644 --- a/Probe/package.json +++ b/Probe/package.json @@ -29,7 +29,7 @@ "https-proxy-agent": "^7.0.5", "net-snmp": "^3.26.1", "ping": "^0.4.4", - "playwright": "^1.57.0", + "playwright": "^1.58.0", "ts-node": "^10.9.1", "whois-json": "^2.0.4" }, diff --git a/ProbeIngest/API/Register.ts b/ProbeIngest/API/Register.ts index 22c1c6eabd..4b67e334fa 100644 --- a/ProbeIngest/API/Register.ts +++ b/ProbeIngest/API/Register.ts @@ -1,7 +1,7 @@ import OneUptimeDate from "Common/Types/Date"; import BadDataException from "Common/Types/Exception/BadDataException"; import { JSONObject } from "Common/Types/JSON"; -import ClusterKeyAuthorization from "Common/Server/Middleware/ClusterKeyAuthorization"; +import { RegisterProbeKey } from "Common/Server/EnvironmentConfig"; import ProbeService from "Common/Server/Services/ProbeService"; import Express, { ExpressRequest, @@ -19,7 +19,6 @@ const router: ExpressRouter = Express.getRouter(); // Register Global Probe. Custom Probe can be registered via dashboard. router.post( "/register", - ClusterKeyAuthorization.isAuthorizedServiceMiddleware, async ( req: ExpressRequest, res: ExpressResponse, @@ -28,6 +27,23 @@ router.post( try { const data: JSONObject = req.body; + const registerProbeKey: string | undefined = data[ + "registerProbeKey" + ] as string; + + if ( + !registerProbeKey || + registerProbeKey !== RegisterProbeKey.toString() + ) { + return Response.sendErrorResponse( + req, + res, + new BadDataException( + "Invalid or missing registerProbeKey. Please check REGISTER_PROBE_KEY environment variable.", + ), + ); + } + if (!data["probeKey"]) { return Response.sendErrorResponse( req, diff --git a/Scripts/package-lock.json b/Scripts/package-lock.json index bc5777bafe..2a4c001fe2 100644 --- a/Scripts/package-lock.json +++ b/Scripts/package-lock.json @@ -1386,9 +1386,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -5737,9 +5737,9 @@ } }, "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", diff --git a/StatusPage/package-lock.json b/StatusPage/package-lock.json index 545e0c2186..cdb2d31e57 100644 --- a/StatusPage/package-lock.json +++ b/StatusPage/package-lock.json @@ -383,45 +383,45 @@ } }, "../Common/node_modules/@aws-sdk/client-sso": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.980.0.tgz", - "integrity": "sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.990.0.tgz", + "integrity": "sha512-xTEaPjZwOqVjGbLOP7qzwbdOWJOo1ne2mUhTZwEBBkPvNk4aXB/vcYwWwrjoSWUqtit4+GDbO75ePc/S6TUJYQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", + "@aws-sdk/util-endpoints": "3.990.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.8", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.23.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.14", + "@smithy/middleware-retry": "^4.4.31", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.30", + "@smithy/util-defaults-mode-node": "^4.2.33", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -433,9 +433,9 @@ } }, "../Common/node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -450,20 +450,20 @@ } }, "../Common/node_modules/@aws-sdk/core": { - "version": "3.973.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.5.tgz", - "integrity": "sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA==", + "version": "3.973.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.10.tgz", + "integrity": "sha512-4u/FbyyT3JqzfsESI70iFg6e2yp87MB5kS2qcxIA66m52VSTN1fvuvbCY1h/LKq1LvuxIrlJ1ItcyjvcKoaPLg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", - "@aws-sdk/xml-builder": "^3.972.2", - "@smithy/core": "^3.22.0", + "@aws-sdk/xml-builder": "^3.972.4", + "@smithy/core": "^3.23.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", @@ -475,13 +475,13 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.3.tgz", - "integrity": "sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.8.tgz", + "integrity": "sha512-r91OOPAcHnLCSxaeu/lzZAVRCZ/CtTNuwmJkUwpwSDshUrP7bkX1OmFn2nUMWd9kN53Q4cEo8b7226G4olt2Mg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", @@ -492,21 +492,21 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.5.tgz", - "integrity": "sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg==", + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.10.tgz", + "integrity": "sha512-DTtuyXSWB+KetzLcWaSahLJCtTUe/3SXtlGp4ik9PCe9xD6swHEkG8n8/BNsQ9dsihb9nhFvuUB4DpdBGDcvVg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.10", + "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" }, "engines": { @@ -514,20 +514,20 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.3.tgz", - "integrity": "sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.8.tgz", + "integrity": "sha512-n2dMn21gvbBIEh00E8Nb+j01U/9rSqFIamWRdGm/mE5e+vHQ9g0cBNdrYFlM6AAiryKVHZmShWT9D1JAWJ3ISw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-login": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/credential-provider-env": "^3.972.8", + "@aws-sdk/credential-provider-http": "^3.972.10", + "@aws-sdk/credential-provider-login": "^3.972.8", + "@aws-sdk/credential-provider-process": "^3.972.8", + "@aws-sdk/credential-provider-sso": "^3.972.8", + "@aws-sdk/credential-provider-web-identity": "^3.972.8", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -540,14 +540,14 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.3.tgz", - "integrity": "sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.8.tgz", + "integrity": "sha512-rMFuVids8ICge/X9DF5pRdGMIvkVhDV9IQFQ8aTYk6iF0rl9jOUa1C3kjepxiXUlpgJQT++sLZkT9n0TMLHhQw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", @@ -560,18 +560,18 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.4.tgz", - "integrity": "sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ==", + "version": "3.972.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.9.tgz", + "integrity": "sha512-LfJfO0ClRAq2WsSnA9JuUsNyIicD2eyputxSlSL0EiMrtxOxELLRG6ZVYDf/a1HCepaYPXeakH4y8D5OLCauag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-ini": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", + "@aws-sdk/credential-provider-env": "^3.972.8", + "@aws-sdk/credential-provider-http": "^3.972.10", + "@aws-sdk/credential-provider-ini": "^3.972.8", + "@aws-sdk/credential-provider-process": "^3.972.8", + "@aws-sdk/credential-provider-sso": "^3.972.8", + "@aws-sdk/credential-provider-web-identity": "^3.972.8", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -584,13 +584,13 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.3.tgz", - "integrity": "sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.8.tgz", + "integrity": "sha512-6cg26ffFltxM51OOS8NH7oE41EccaYiNlbd5VgUYwhiGCySLfHoGuGrLm2rMB4zhy+IO5nWIIG0HiodX8zdvHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -602,15 +602,15 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.3.tgz", - "integrity": "sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.8.tgz", + "integrity": "sha512-35kqmFOVU1n26SNv+U37sM8b2TzG8LyqAcd6iM9gprqxyHEh/8IM3gzN4Jzufs3qM6IrH8e43ryZWYdvfVzzKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.980.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/token-providers": "3.980.0", + "@aws-sdk/client-sso": "3.990.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/token-providers": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -622,14 +622,14 @@ } }, "../Common/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.3.tgz", - "integrity": "sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.8.tgz", + "integrity": "sha512-CZhN1bOc1J3ubQPqbmr5b4KaMJBgdDvYsmEIZuX++wFlzmZsKj1bwkaiTEb5U2V7kXuzLlpF5HJSOM9eY/6nGA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -689,16 +689,16 @@ } }, "../Common/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.5.tgz", - "integrity": "sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg==", + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.10.tgz", + "integrity": "sha512-bBEL8CAqPQkI91ZM5a9xnFAzedpzH6NYCOtNyLarRAzTUTFN2DKqaC60ugBa7pnU1jSi4mA7WAXBsrod7nJltg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", - "@smithy/core": "^3.22.0", + "@aws-sdk/util-endpoints": "3.990.0", + "@smithy/core": "^3.23.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -708,9 +708,9 @@ } }, "../Common/node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -725,45 +725,45 @@ } }, "../Common/node_modules/@aws-sdk/nested-clients": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.980.0.tgz", - "integrity": "sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.990.0.tgz", + "integrity": "sha512-3NA0s66vsy8g7hPh36ZsUgO4SiMyrhwcYvuuNK1PezO52vX3hXDW4pQrC6OQLGKGJV0o6tbEyQtXb/mPs8zg8w==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", + "@aws-sdk/core": "^3.973.10", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", + "@aws-sdk/util-endpoints": "3.990.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.8", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.23.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.14", + "@smithy/middleware-retry": "^4.4.31", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.30", + "@smithy/util-defaults-mode-node": "^4.2.33", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -775,9 +775,9 @@ } }, "../Common/node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.990.0.tgz", + "integrity": "sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -809,14 +809,14 @@ } }, "../Common/node_modules/@aws-sdk/token-providers": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.980.0.tgz", - "integrity": "sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA==", + "version": "3.990.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.990.0.tgz", + "integrity": "sha512-L3BtUb2v9XmYgQdfGBzbBtKMXaP5fV973y3Qdxeevs6oUTVXFmi/mV1+LnScA/1wVPJC9/hlK+1o5vbt7cG7EQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", + "@aws-sdk/core": "^3.973.10", + "@aws-sdk/nested-clients": "3.990.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -885,13 +885,13 @@ } }, "../Common/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.3.tgz", - "integrity": "sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.8.tgz", + "integrity": "sha512-XJZuT0LWsFCW1C8dEpPAXSa7h6Pb3krr2y//1X0Zidpcl0vmgY5nL/X0JuBZlntpBzaN3+U4hvKjuijyiiR8zw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.5", + "@aws-sdk/middleware-user-agent": "^3.972.10", "@aws-sdk/types": "^3.973.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", @@ -910,9 +910,9 @@ } }, "../Common/node_modules/@aws-sdk/xml-builder": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.3.tgz", - "integrity": "sha512-bCk63RsBNCWW4tt5atv5Sbrh+3J3e8YzgyF6aZb1JeXcdzG4k5SlPLeTMFOIXFuuFHIwgphUhn4i3uS/q49eww==", + "version": "3.972.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.4.tgz", + "integrity": "sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1684,54 +1684,42 @@ } }, "../Common/node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.1.tgz", + "integrity": "sha512-fRHyv6/f542qQqiRGalrfJl/evD39mAvbJLCekPazhiextEatq1Jx1K/i9gSd5NNO0ds03ek0Cbo/4uVKmOBcw==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/gast": "11.1.1", + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "../Common/node_modules/@chevrotain/cst-dts-gen/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==", - "license": "MIT" - }, "../Common/node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.1.tgz", + "integrity": "sha512-Ko/5vPEYy1vn5CbCjjvnSO4U7GgxyGm+dfUZZJIWTlQFkXkyym0jFYrWEU10hyCjrA7rQtiHtBr0EaZqvHFZvg==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "../Common/node_modules/@chevrotain/gast/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==", - "license": "MIT" - }, "../Common/node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.1.tgz", + "integrity": "sha512-ctRw1OKSXkOrR8VTvOxrQ5USEc4sNrfwXHa1NuTcR7wre4YbjPcKw+82C2uylg/TEwFRgwLmbhlln4qkmDyteg==", "license": "Apache-2.0" }, "../Common/node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.1.tgz", + "integrity": "sha512-wb2ToxG8LkgPYnKe9FH8oGn3TMCBdnwiuNC5l5y+CtlaVRbCytU0kbVsk6CGrqTL4ZN4ksJa0TXOYbxpbthtqw==", "license": "Apache-2.0" }, "../Common/node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.1.tgz", + "integrity": "sha512-71eTYMzYXYSFPrbg/ZwftSaSDld7UYlS8OQa3lNnn9jzNtpFbaReRRyghzqS7rI3CDaorqpPJJcXGHK+FE1TVQ==", "license": "Apache-2.0" }, "../Common/node_modules/@clickhouse/client": { @@ -3092,12 +3080,12 @@ "license": "MIT" }, "../Common/node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", + "integrity": "sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==", "license": "MIT", "dependencies": { - "langium": "3.3.1" + "langium": "^4.0.0" } }, "../Common/node_modules/@monaco-editor/loader": { @@ -5137,9 +5125,9 @@ } }, "../Common/node_modules/@smithy/core": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.22.1.tgz", - "integrity": "sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==", + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.2.tgz", + "integrity": "sha512-HaaH4VbGie4t0+9nY3tNBRSxVTr96wzIqexUa6C2qx3MPePAuz7lIxPxYtt1Wc//SPfJLNoZJzfdt0B6ksj2jA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5149,7 +5137,7 @@ "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", - "@smithy/util-stream": "^4.5.11", + "@smithy/util-stream": "^4.5.12", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" @@ -5251,13 +5239,13 @@ } }, "../Common/node_modules/@smithy/middleware-endpoint": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.13.tgz", - "integrity": "sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==", + "version": "4.4.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.16.tgz", + "integrity": "sha512-L5GICFCSsNhbJ5JSKeWFGFy16Q2OhoBizb3X2DrxaJwXSEujVvjG9Jt386dpQn2t7jINglQl0b4K/Su69BdbMA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.22.1", + "@smithy/core": "^3.23.2", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -5271,16 +5259,16 @@ } }, "../Common/node_modules/@smithy/middleware-retry": { - "version": "4.4.30", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.30.tgz", - "integrity": "sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg==", + "version": "4.4.33", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.33.tgz", + "integrity": "sha512-jLqZOdJhtIL4lnA9hXnAG6GgnJlo1sD3FqsTxm9wSfjviqgWesY/TMBVnT84yr4O0Vfe0jWoXlfFbzsBVph3WA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -5337,9 +5325,9 @@ } }, "../Common/node_modules/@smithy/node-http-handler": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.9.tgz", - "integrity": "sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.10.tgz", + "integrity": "sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5458,18 +5446,18 @@ } }, "../Common/node_modules/@smithy/smithy-client": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.11.2.tgz", - "integrity": "sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==", + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.11.5.tgz", + "integrity": "sha512-xixwBRqoeP2IUgcAl3U9dvJXc+qJum4lzo3maaJxifsZxKUYLfVfCXvhT4/jD01sRrHg5zjd1cw2Zmjr4/SuKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.22.1", - "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/core": "^3.23.2", + "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.11", + "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" }, "engines": { @@ -5573,14 +5561,14 @@ } }, "../Common/node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.29", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.29.tgz", - "integrity": "sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q==", + "version": "4.3.32", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.32.tgz", + "integrity": "sha512-092sjYfFMQ/iaPH798LY/OJFBcYu0sSK34Oy9vdixhsU36zlZu8OcYjF3TD4e2ARupyK7xaxPXl+T0VIJTEkkg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5589,9 +5577,9 @@ } }, "../Common/node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.32", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.32.tgz", - "integrity": "sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q==", + "version": "4.2.35", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.35.tgz", + "integrity": "sha512-miz/ggz87M8VuM29y7jJZMYkn7+IErM5p5UgKIf8OtqVs/h2bXr1Bt3uTsREsI/4nK8a0PQERbAPsVPVNIsG7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5599,7 +5587,7 @@ "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", + "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5665,14 +5653,14 @@ } }, "../Common/node_modules/@smithy/util-stream": { - "version": "4.5.11", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.11.tgz", - "integrity": "sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==", + "version": "4.5.12", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.12.tgz", + "integrity": "sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.9", + "@smithy/node-http-handler": "^4.4.10", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", @@ -8107,17 +8095,17 @@ } }, "../Common/node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.1.tgz", + "integrity": "sha512-f0yv5CPKaFxfsPTBzX7vGuim4oIC1/gcS7LUGdBSwl2dU6+FON6LVUksdOo1qJjoUvXNn45urgh8C+0a24pACQ==", "license": "Apache-2.0", "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/cst-dts-gen": "11.1.1", + "@chevrotain/gast": "11.1.1", + "@chevrotain/regexp-to-ast": "11.1.1", + "@chevrotain/types": "11.1.1", + "@chevrotain/utils": "11.1.1", + "lodash-es": "4.17.23" } }, "../Common/node_modules/chevrotain-allstar": { @@ -8132,12 +8120,6 @@ "chevrotain": "^11.0.0" } }, - "../Common/node_modules/chevrotain/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==", - "license": "MIT" - }, "../Common/node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -13618,19 +13600,20 @@ } }, "../Common/node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", "license": "MIT", "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" + "vscode-uri": "~3.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.10.0", + "npm": ">=10.2.3" } }, "../Common/node_modules/layout-base": { @@ -14428,14 +14411,14 @@ } }, "../Common/node_modules/mermaid": { - "version": "11.12.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", - "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "version": "11.12.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.3.tgz", + "integrity": "sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", - "@mermaid-js/parser": "^0.6.3", + "@mermaid-js/parser": "^1.0.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -14447,7 +14430,7 @@ "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", - "lodash-es": "^4.17.21", + "lodash-es": "^4.17.23", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", @@ -20201,9 +20184,9 @@ "license": "MIT" }, "../Common/node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "license": "MIT" }, "../Common/node_modules/w3c-xmlserializer": { diff --git a/config.example.env b/config.example.env index bf44916dd5..d8c6a1d0a9 100644 --- a/config.example.env +++ b/config.example.env @@ -22,6 +22,7 @@ CAPTCHA_SECRET_KEY= # Secrets - PLEASE CHANGE THESE. Please change these to something random. All of these can be different values. ONEUPTIME_SECRET=please-change-this-to-random-value +REGISTER_PROBE_KEY=please-change-this-to-random-value DATABASE_PASSWORD=please-change-this-to-random-value CLICKHOUSE_PASSWORD=please-change-this-to-random-value REDIS_PASSWORD=please-change-this-to-random-value @@ -297,6 +298,14 @@ VAPID_PUBLIC_KEY= VAPID_PRIVATE_KEY= VAPID_SUBJECT=mailto:support@oneuptime.com +# Expo access token for sending mobile push notifications directly via Expo SDK. +# If not set, push notifications are relayed through the push notification relay URL below. +EXPO_ACCESS_TOKEN= + +# Push notification relay URL for self-hosted instances without Expo credentials. +# Self-hosted servers relay push notifications through this gateway. +PUSH_NOTIFICATION_RELAY_URL=https://oneuptime.com/api/notification/push-relay/send + # LLM Environment Variables # Hugging Face Token for LLM Server to downlod models from Hugging Face diff --git a/docker-compose.base.yml b/docker-compose.base.yml index c032e280f0..b7212c9cb7 100644 --- a/docker-compose.base.yml +++ b/docker-compose.base.yml @@ -82,6 +82,9 @@ x-common-runtime-variables: &common-runtime-variables VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} + EXPO_ACCESS_TOKEN: ${EXPO_ACCESS_TOKEN} + PUSH_NOTIFICATION_RELAY_URL: ${PUSH_NOTIFICATION_RELAY_URL} + DATABASE_PORT: ${DATABASE_PORT} DATABASE_USERNAME: ${DATABASE_USERNAME} DATABASE_PASSWORD: ${DATABASE_PASSWORD} @@ -392,21 +395,25 @@ services: options: max-size: "1000m" - probe-1: + probe-1: restart: always network_mode: host environment: - <<: *common-runtime-variables + ONEUPTIME_URL: ${GLOBAL_PROBE_1_ONEUPTIME_URL} + REGISTER_PROBE_KEY: ${REGISTER_PROBE_KEY} PROBE_NAME: ${GLOBAL_PROBE_1_NAME} PROBE_DESCRIPTION: ${GLOBAL_PROBE_1_DESCRIPTION} PROBE_MONITORING_WORKERS: ${GLOBAL_PROBE_1_MONITORING_WORKERS} PROBE_KEY: ${GLOBAL_PROBE_1_KEY} PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS: ${GLOBAL_PROBE_1_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS} PROBE_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS: ${GLOBAL_PROBE_1_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS} - ONEUPTIME_URL: ${GLOBAL_PROBE_1_ONEUPTIME_URL} PROBE_MONITOR_FETCH_LIMIT: ${GLOBAL_PROBE_1_MONITOR_FETCH_LIMIT} - DISABLE_TELEMETRY: ${DISABLE_TELEMETRY_FOR_PROBE} PORT: ${GLOBAL_PROBE_1_PORT} + NODE_ENV: ${ENVIRONMENT} + LOG_LEVEL: ${LOG_LEVEL} + DISABLE_TELEMETRY: ${DISABLE_TELEMETRY_FOR_PROBE} + OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT: ${OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT} + OPENTELEMETRY_EXPORTER_OTLP_HEADERS: ${OPENTELEMETRY_EXPORTER_OTLP_HEADERS} logging: driver: "local" options: @@ -416,17 +423,21 @@ services: restart: always network_mode: host environment: - <<: *common-runtime-variables + ONEUPTIME_URL: ${GLOBAL_PROBE_2_ONEUPTIME_URL} + REGISTER_PROBE_KEY: ${REGISTER_PROBE_KEY} PROBE_NAME: ${GLOBAL_PROBE_2_NAME} PROBE_DESCRIPTION: ${GLOBAL_PROBE_2_DESCRIPTION} PROBE_MONITORING_WORKERS: ${GLOBAL_PROBE_2_MONITORING_WORKERS} PROBE_KEY: ${GLOBAL_PROBE_2_KEY} - ONEUPTIME_URL: ${GLOBAL_PROBE_2_ONEUPTIME_URL} PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS: ${GLOBAL_PROBE_2_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS} PROBE_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS: ${GLOBAL_PROBE_2_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS} PROBE_MONITOR_FETCH_LIMIT: ${GLOBAL_PROBE_2_MONITOR_FETCH_LIMIT} - DISABLE_TELEMETRY: ${DISABLE_TELEMETRY_FOR_PROBE} PORT: ${GLOBAL_PROBE_2_PORT} + NODE_ENV: ${ENVIRONMENT} + LOG_LEVEL: ${LOG_LEVEL} + DISABLE_TELEMETRY: ${DISABLE_TELEMETRY_FOR_PROBE} + OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT: ${OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT} + OPENTELEMETRY_EXPORTER_OTLP_HEADERS: ${OPENTELEMETRY_EXPORTER_OTLP_HEADERS} logging: driver: "local" options: @@ -504,6 +515,7 @@ services: PORT: ${PROBE_INGEST_PORT} DISABLE_TELEMETRY: ${DISABLE_TELEMETRY_FOR_PROBE_INGEST} PROBE_INGEST_CONCURRENCY: ${PROBE_INGEST_CONCURRENCY} + REGISTER_PROBE_KEY: ${REGISTER_PROBE_KEY} logging: driver: "local" options: diff --git a/package-lock.json b/package-lock.json index d040326977..4d5f0a04ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -568,9 +568,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -586,21 +586,21 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -609,18 +609,21 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -630,9 +633,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -641,7 +644,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -665,9 +668,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -677,21 +680,21 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.2", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -1348,7 +1351,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "devOptional": true, + "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1361,7 +1364,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 8" } @@ -1370,7 +1373,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "devOptional": true, + "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1390,15 +1393,15 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@selderee/plugin-htmlparser2": { @@ -1594,21 +1597,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", - "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", + "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", "devOptional": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/type-utils": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/type-utils": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1618,8 +1620,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.44.1", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, @@ -1634,17 +1636,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", - "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", + "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1654,20 +1656,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", - "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", + "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.44.1", - "@typescript-eslint/types": "^8.44.1", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.56.0", + "@typescript-eslint/types": "^8.56.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1681,14 +1683,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", - "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", + "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1699,9 +1701,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", - "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", + "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", "devOptional": true, "license": "MIT", "engines": { @@ -1716,17 +1718,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", - "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", + "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1736,14 +1738,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", - "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", + "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", "devOptional": true, "license": "MIT", "engines": { @@ -1755,22 +1757,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", - "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", + "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.44.1", - "@typescript-eslint/tsconfig-utils": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/project-service": "8.56.0", + "@typescript-eslint/tsconfig-utils": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1810,9 +1811,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "devOptional": true, "license": "ISC", "bin": { @@ -1823,16 +1824,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", - "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", + "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", "devOptional": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1842,19 +1843,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", - "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz", + "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==", "devOptional": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.56.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1865,13 +1866,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", "devOptional": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3566,24 +3567,23 @@ } }, "node_modules/eslint": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", - "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.36.0", - "@eslint/plugin-kit": "^0.3.5", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -3626,10 +3626,11 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -3638,13 +3639,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, + "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3655,7 +3657,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -3727,13 +3729,13 @@ } }, "node_modules/eslint-plugin-unused-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.3.0.tgz", - "integrity": "sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz", + "integrity": "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==", "license": "MIT", "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^9.0.0 || ^8.0.0" + "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -3931,13 +3933,14 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3954,7 +3957,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "devOptional": true, + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -3976,7 +3979,7 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "devOptional": true, + "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -4397,12 +4400,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "devOptional": true - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -5887,18 +5884,6 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-snapshot/node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -5911,21 +5896,6 @@ "node": ">=10" } }, - "node_modules/jest-snapshot/node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, "node_modules/jest-util": { "version": "30.2.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", @@ -6539,7 +6509,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 8" } @@ -7191,10 +7161,11 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -7287,7 +7258,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -7453,7 +7424,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "devOptional": true, + "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -7469,7 +7440,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "devOptional": true, + "dev": true, "funding": [ { "type": "github", @@ -8142,19 +8113,18 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.9" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/syntax-error": { @@ -8207,6 +8177,54 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tlds": { "version": "1.261.0", "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", @@ -8261,9 +8279,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "devOptional": true, "license": "MIT", "engines": { @@ -8620,16 +8638,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.44.1.tgz", - "integrity": "sha512-0ws8uWGrUVTjEeN2OM4K1pLKHK/4NiNP/vz6ns+LjT/6sqpaYzIVFajZb1fj/IDwpsrrHb3Jy0Qm5u9CPcKaeg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.0.tgz", + "integrity": "sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.44.1", - "@typescript-eslint/parser": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1" + "@typescript-eslint/eslint-plugin": "8.56.0", + "@typescript-eslint/parser": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8639,7 +8657,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } },